<?php
namespace App\Controllers;

use App\Core\Auth;
use App\Core\Controller;
use App\Core\Csrf;
use App\Core\Permission;
use App\Models\ConsentDocument;
use App\Models\MemberProfile;
use App\Services\ConsentPdfService;
use RuntimeException;
use Throwable;

final class ConsentController extends Controller
{
    private function familyDocument(): array
    {
        $clientId=Permission::familyPortalClientId();
        if (!Permission::isFamilyPortalIdentity() || !$clientId) {
            http_response_code(403);
            exit('Ce document n’est pas accessible depuis ce portail.');
        }
        $client=\App\Models\Client::find((int)$clientId);
        $document=ConsentDocument::forFamily(
            (int)($_REQUEST['id']??0),
            (int)($client['famille_id']??0),
            (int)(Auth::user()['organisation_id']??1)
        );
        if (!$document) {
            http_response_code(404);
            exit('Document introuvable dans ce dossier familial.');
        }
        return $document;
    }

    private function familyDocumentsUrl(): string
    {
        $client=\App\Models\Client::find((int)(Permission::familyPortalClientId()??0));
        return '/adherents/fiche?ref='.rawurlencode((string)($client['code_client']??'')).'&onglet=documents';
    }

    public function familySignature(): void
    {
        Auth::requireLogin();
        $document=$this->familyDocument();
        if ((string)$document['statut']==='signe') {
            $_SESSION['success']='Ce document est déjà signé et ne peut plus être modifié.';
            $this->redirect($this->familyDocumentsUrl());
        }
        $this->view('family_consents/signature',[
            'pageTitle'=>'Signer un document',
            'document'=>$document,
        ]);
    }

    public function familySign(): void
    {
        Auth::requireLogin();
        Csrf::verify($_POST['_csrf']??null);
        $document=$this->familyDocument();
        if ((string)$document['statut']==='signe') {
            http_response_code(409);
            exit('Document déjà signé : toute modification est interdite.');
        }
        $signature=(string)($_POST['signature_data']??'');
        if ($signature==='' || !str_starts_with($signature,'data:image/')) {
            throw new RuntimeException('La signature est obligatoire.');
        }
        $pdf=(new ConsentPdfService())->generate(
            (int)$document['id'],
            trim((string)$_POST['nom_signataire']),
            trim((string)$_POST['qualite_signataire']),
            $signature
        );
        ConsentDocument::sign(
            (int)$document['id'],
            trim((string)$_POST['nom_signataire']),
            trim((string)$_POST['qualite_signataire']),
            $signature,
            'sur_place',
            $pdf['path'],
            $pdf['checksum']
        );
        \App\Services\ConsentSignedMailer::notify((int)$document['id']);
        $_SESSION['success']='Document signé et verrouillé. Il reste disponible dans votre dossier Famille.';
        $this->redirect($this->familyDocumentsUrl());
    }

    public function familyDownload(): void
    {
        Auth::requireLogin();
        $document=$this->familyDocument();
        if ((string)$document['statut']!=='signe' || empty($document['fichier_pdf'])) {
            http_response_code(404);
            exit('Aucun document signé téléchargeable.');
        }
        $path=BASE_PATH.'/'.ltrim((string)$document['fichier_pdf'],'/');
        $real=realpath($path);
        $root=realpath(BASE_PATH.'/storage/documents/consentements');
        if (!$real || !$root || !str_starts_with($real,$root.DIRECTORY_SEPARATOR) || !is_file($real)) {
            http_response_code(404);
            exit('Fichier signé introuvable.');
        }
        header('Content-Type: text/html; charset=UTF-8');
        header('Content-Disposition: attachment; filename="consentement-signe-'.(int)$document['id'].'.html"');
        header('X-Content-Type-Options: nosniff');
        readfile($real);
    }
    public function create(): void
    {
        Auth::requireLogin();
        Permission::require('consentements.create');

        $memberId=(int)($_GET['membre_id'] ?? 0);
        $member=MemberProfile::find($memberId);

        if(!$member){
            http_response_code(404);
            exit('Membre introuvable.');
        }

        $this->view('consents/form',[
            'pageTitle'=>'Nouveau document',
            'member'=>$member,
            'type'=>$_GET['type'] ?? 'rgpd',
        ]);
    }

    public function store(): void
    {
        Auth::requireLogin();
        Permission::require('consentements.create');
        Csrf::verify($_POST['_csrf'] ?? null);

        $choices=[
            'communications_email'=>isset($_POST['communications_email']),
            'communications_sms'=>isset($_POST['communications_sms']),
            'photo_individuelle'=>isset($_POST['photo_individuelle']),
            'photo_groupe'=>isset($_POST['photo_groupe']),
            'site_internet'=>isset($_POST['site_internet']),
            'reseaux_sociaux'=>isset($_POST['reseaux_sociaux']),
            'affiches'=>isset($_POST['affiches']),
            'presse'=>isset($_POST['presse']),
            'video'=>isset($_POST['video']),
        ];

        $id=ConsentDocument::create([
            'organisation_id'=>(int)(Auth::user()['organisation_id'] ?? 1),
            'membre_id'=>(int)$_POST['membre_id'],
            'famille_id'=>(int)($_POST['famille_id'] ?? 0) ?: null,
            'type_document'=>$_POST['type_document'],
            'annee_scolaire'=>$_POST['annee_scolaire'],
            'version_document'=>'1.0',
            'choix_json'=>json_encode($choices,JSON_UNESCAPED_UNICODE),
            'email_envoi'=>trim((string)($_POST['email_envoi'] ?? '')) ?: null,
            'created_by'=>(int)(Auth::user()['id'] ?? 0) ?: null,
        ]);

        $_SESSION['success']='Le document a été préparé.';
        $this->redirect('/consentements/signature?id='.$id);
    }

    public function signature(): void
    {
        Auth::requireLogin();
        Permission::require('consentements.sign');

        $document=ConsentDocument::find((int)($_GET['id'] ?? 0));

        if(!$document){
            http_response_code(404);
            exit('Document introuvable.');
        }

        $this->view('consents/signature',[
            'pageTitle'=>'Signature du document',
            'document'=>$document,
            'member'=>MemberProfile::find((int)$document['membre_id']),
        ]);
    }

    public function sign(): void
    {
        Auth::requireLogin();
        Permission::require('consentements.sign');
        Csrf::verify($_POST['_csrf'] ?? null);

        $id=(int)$_POST['id'];
        $existing=ConsentDocument::find($id);
        if (!$existing || (string)$existing['statut']==='signe') {
            http_response_code(409);
            exit('Ce document est déjà signé et verrouillé.');
        }
        $signature=(string)($_POST['signature_data'] ?? '');

        if($signature===''){
            throw new RuntimeException('La signature est obligatoire.');
        }

        $pdf=(new ConsentPdfService())->generate(
            $id,
            trim((string)$_POST['nom_signataire']),
            trim((string)$_POST['qualite_signataire']),
            $signature
        );

        ConsentDocument::sign(
            $id,
            trim((string)$_POST['nom_signataire']),
            trim((string)$_POST['qualite_signataire']),
            $signature,
            'sur_place',
            $pdf['path'],
            $pdf['checksum']
        );
        \App\Services\ConsentSignedMailer::notify($id);

        $_SESSION['success']='Le document signé a été conservé.';
        $document=ConsentDocument::find($id);
        $this->redirect('/membres/voir?id='.(int)$document['membre_id']);
    }

    public function send(): void
    {
        Auth::requireLogin();
        Permission::require('consentements.send');
        Csrf::verify($_POST['_csrf'] ?? null);

        $documentId=(int)$_POST['id'];
        $email=trim((string)$_POST['email']);
        $token=bin2hex(random_bytes(32));
        $expires=(new \DateTimeImmutable('+7 days'))->format('Y-m-d H:i:s');

        ConsentDocument::createToken(
            $documentId,
            $email,
            $token,
            $expires
        );

        $_SESSION['success']='Lien de signature généré : /public/consentement-public?token='.$token;
        $document=ConsentDocument::find($documentId);
        $this->redirect('/membres/voir?id='.(int)$document['membre_id']);
    }

    public function publicForm(): void
    {
        $token=(string)($_GET['token'] ?? '');
        $document=ConsentDocument::tokenDocument($token);

        if(!$document){
            http_response_code(410);
            exit('Lien invalide ou expiré.');
        }
        if ((string)$document['statut']==='signe') {
            http_response_code(409);
            exit('Ce document est déjà signé et verrouillé.');
        }

        $this->view('consents/public_signature',[
            'pageTitle'=>'Signature sécurisée',
            'document'=>$document,
            'member'=>MemberProfile::find((int)$document['membre_id']),
            'token'=>$token,
        ]);
    }

    public function publicSign(): void
    {
        $token=(string)($_POST['token'] ?? '');
        $document=ConsentDocument::tokenDocument($token);

        if(!$document){
            http_response_code(410);
            exit('Lien invalide ou expiré.');
        }

        $pdf=(new ConsentPdfService())->generate(
            (int)$document['id'],
            trim((string)$_POST['nom_signataire']),
            trim((string)$_POST['qualite_signataire']),
            (string)$_POST['signature_data']
        );

        ConsentDocument::sign(
            (int)$document['id'],
            trim((string)$_POST['nom_signataire']),
            trim((string)$_POST['qualite_signataire']),
            (string)$_POST['signature_data'],
            'lien_email',
            $pdf['path'],
            $pdf['checksum']
        );
        \App\Services\ConsentSignedMailer::notify((int)$document['id']);

        ConsentDocument::markTokenUsed((int)$document['token_id']);

        $this->view('consents/public_done',[
            'pageTitle'=>'Document signé',
        ]);
    }
}
