# -*- coding: utf-8 -*-
"""Parcours complet dans l'interface : connexion, dépôt, suivi, aperçu,
consigne, téléchargement."""

import io, os, shutil, sys, tempfile, zipfile

BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, BASE); sys.path.insert(0, os.path.join(BASE, "tests"))
_BAC = tempfile.mkdtemp(prefix="plateforme-app-")
os.environ["PLATEFORME_PROJETS"] = os.path.join(_BAC, "projets")
os.environ["PLATEFORME_BASE"] = os.path.join(_BAC, "projets.db")
os.environ["PLATEFORME_MOTDEPASSE"] = "secret-agence"
os.environ["PLATEFORME_SECRET"] = "cle-de-test"

import app as application, claude, projets, worker
import faux_client as fc

OK = [0, 0]
def v(c, l):
    OK[0 if c else 1] += 1
    print("  %s %s" % ("ok  " if c else "ECHEC", l))

application.app.config["TESTING"] = True
c = application.app.test_client()
REF = "/tmp/claude-0/-home-user/62f16eb1-774a-5977-a315-11818ad1cb02/scratchpad/ref"

print("=== Contrôle d'accès ===")
r = c.get("/", follow_redirects=False)
v(r.status_code == 302 and "/connexion" in r.headers["Location"], "page protégée → connexion")
r = c.post("/connexion", data={"mot_de_passe": "faux"})
v("incorrect" in r.get_data(as_text=True), "mauvais mot de passe refusé")
r = c.post("/connexion", data={"mot_de_passe": "secret-agence"}, follow_redirects=True)
v(r.status_code == 200 and "Projets" in r.get_data(as_text=True), "connexion acceptée")

print("\n=== Création avec dépôt de fichiers ===")
r = c.get("/nouveau")
page = r.get_data(as_text=True)
v('name="client"' in page and 'name="contenus"' in page, "formulaire rendu")
v('name="fichiers"' in page and "multiple" in page, "dépôt multiple présent")

with open(f"{REF}/assets/img/photos/DSC00635.jpg", "rb") as f:
    photo = f.read()
with open(f"{REF}/assets/img/logos/logo-b-to-health.png", "rb") as f:
    logo = f.read()

donnees = {
    "client": "B To Health", "secteur": "HealthTech",
    "nature": "Site événementiel", "objectif": "Inscriptions et exposants",
    "slogan": "Votre business en Bourgogne-Franche-Comté",
    "pages": "la page d'accueil", "arborescence": "Accueil · Programme · Contact",
    "contenus": "Diaporama, présentation, chiffres 2026",
    "couleurs": "#1b537d, #1a88b7, #47bcc8, #555959",
    "police_titres": "Dosis", "police_textes": "Roboto",
    "fichiers": [
        (io.BytesIO(photo), "DSC 00635 (défilé).jpg"),
        (io.BytesIO(logo), "logo-b-to-health.png"),
        (io.BytesIO(b"%PDF-1.4\ntrailer<</Root 1 0 R>>\n%%EOF\n"), "charte graphique.pdf"),
    ],
}
r = c.post("/nouveau", data=donnees, content_type="multipart/form-data", follow_redirects=False)
v(r.status_code == 302, "création → redirection vers le projet")
pid = r.headers["Location"].rstrip("/").split("/")[-1]
print("  projet :", pid)

entrees = os.listdir(projets.dossier_entrees(pid))
print("  fichiers déposés :", entrees)
v(any(n.startswith("DSC-00635") for n in entrees), "nom de fichier accentué assaini")
v(all(" " not in n for n in entrees), "aucun espace dans les noms")

site = projets.dossier_site(pid)
v(os.path.isfile(os.path.join(site, "assets/img/logos/logo-b-to-health.png")),
  "logo reconnu et rangé dans logos/")
v(any(n.endswith(".jpg") for n in os.listdir(os.path.join(site, "assets/img/photos"))),
  "photo rangée dans photos/")
v(projets.lire(pid)["etat"] == projets.EN_ATTENTE, "projet en file d'attente")

print("\n=== Suivi pendant la génération ===")
page = c.get("/projet/%s" % pid).get_data(as_text=True)
v("en file" in page, "état affiché")
v("journal.json" in page, "sondage du journal actif")
v("Elementor" in page, "l'annexe Elementor est proposée en exemple")
r = c.get("/projet/%s/journal.json?depuis=0" % pid)
j = r.get_json()
v(j["actif"] is True and j["tours"] == 0, "journal.json : projet actif, 0 tour")
v(any(l["evenement"] == "depot" for l in j["lignes"]), "le dépôt est journalisé")

print("\n=== Génération (faux client) ===")
CSS = ":root{--bleu-nuit:#1b537d}\nbody{font-family:Roboto}\n"
HTML = ('<!DOCTYPE html><html lang="fr"><head><meta charset="utf-8">'
        '<title>B To Health</title><link rel="stylesheet" href="assets/css/style.css">'
        '</head><body><h1>B To Health</h1>'
        '<img src="assets/img/logos/logo-b-to-health.png" alt="Logo" width="200" height="80">'
        '</body></html>')
_faux = fc.FauxClient([
    fc.Reponse([fc.texte("Charte : #1b537d dominante."),
                fc.appel("x1", "ecrire_fichier",
                         {"chemin": "assets/css/style.css", "contenu": CSS})], "tool_use"),
    fc.Reponse([fc.appel("x2", "ecrire_fichier", {"chemin": "index.html", "contenu": HTML})],
               "tool_use"),
    fc.Reponse([fc.appel("x3", "ecrire_fichier",
                         {"chemin": "README.md", "contenu": "# B To Health\n\nÀ remplacer : rien.\n"})],
               "tool_use"),
    fc.Reponse([fc.appel("x4", "terminer", {"resume": "Accueil livrée."})], "tool_use"),
])
claude._client = lambda: _faux   # une seule instance : sinon le scénario repart à zéro
worker.main()

print("\n=== Après génération ===")
page = c.get("/projet/%s" % pid).get_data(as_text=True)
v("terminé" in page, "état terminé affiché")
v("Accueil livrée." in page, "résumé affiché")
v("Télécharger le ZIP" in page, "bouton de téléchargement présent")
v("Aperçu du site" in page, "bouton d'aperçu présent")
v("point(s) à regarder" not in page, "aucune anomalie sur un site propre")

r = c.get("/apercu/%s/index.html" % pid)
v(r.status_code == 200 and b"B To Health" in r.data, "aperçu HTML servi")
r = c.get("/apercu/%s/assets/css/style.css" % pid)
v(r.status_code == 200 and b"--bleu-nuit" in r.data, "aperçu CSS servi")
r = c.get("/apercu/%s/assets/img/logos/logo-b-to-health.png" % pid)
v(r.status_code == 200 and r.data[:4] == b"\x89PNG", "aperçu image servi")
r = c.get("/apercu/%s/../../../etc/passwd" % pid)
v(r.status_code in (400, 403, 404), "aperçu : évasion refusée (%d)" % r.status_code)

r = c.get("/projet/%s/zip" % pid)
v(r.status_code == 200, "ZIP téléchargeable")
with zipfile.ZipFile(io.BytesIO(r.data)) as zf:
    noms = sorted(zf.namelist())
print("  archive :", noms)
v("index.html" in noms and "README.md" in noms, "HTML et README dans l'archive")
v(any(n.startswith("assets/img/") for n in noms), "visuels dans l'archive")

print("\n=== Consigne de suite ===")
r = c.post("/projet/%s/consigne" % pid, data={"consigne": "Crée la page Programme."},
           follow_redirects=True)
v("Consigne transmise" in r.get_data(as_text=True), "consigne acceptée")
v(projets.lire(pid)["etat"] == projets.EN_ATTENTE, "projet remis en file")
r = c.post("/projet/%s/consigne" % pid, data={"consigne": "   "}, follow_redirects=True)
v("Consigne vide" in r.get_data(as_text=True), "consigne vide refusée")

_faux2 = fc.FauxClient([
    fc.Reponse([fc.appel("y1", "ecrire_fichier",
                         {"chemin": "programme.html",
                          "contenu": '<html lang="fr"><body>Programme</body></html>'})], "tool_use"),
    fc.Reponse([fc.appel("y2", "terminer", {"resume": "Page Programme ajoutée."})], "tool_use"),
])
claude._client = lambda: _faux2
worker.main()
v(os.path.isfile(os.path.join(site, "programme.html")), "page ajoutée sur consigne")
page = c.get("/projet/%s" % pid).get_data(as_text=True)
v("Page Programme ajoutée." in page, "nouveau résumé affiché")

print("\n=== Liste ===")
page = c.get("/").get_data(as_text=True)
v("B To Health" in page and "terminé" in page, "projet listé avec son état")

print("\n=== 404 ===")
v(c.get("/projet/inexistant").status_code == 404, "projet inconnu → 404")
v(c.get("/apercu/inexistant/index.html").status_code == 404, "aperçu inconnu → 404")

print("\n%d ok, %d échecs" % (OK[0], OK[1]))
shutil.rmtree(_BAC, ignore_errors=True)
sys.exit(1 if OK[1] else 0)
