<?php
namespace App\Controllers;

use App\Core\{Auth,Controller,Csrf,Database,Permission};
use App\Models\Attendance;
use App\Security\SecureFileService;

final class AttendanceDocumentController extends Controller
{
    private const MAX=10485760;
    private const TYPES=['application/pdf'=>'pdf','image/jpeg'=>'jpg','image/png'=>'png','image/webp'=>'webp'];

    public function upload(): void
    {
        Auth::requireLogin();
        Permission::require('emargements.upload');
        Csrf::verify($_POST['_csrf']??null);
        $session=$this->session((string)($_POST['seance']??''));
        $f=$_FILES['document']??[];
        $dir=BASE_PATH.'/storage/emargements/'.date('Y/m');
        $stored=SecureFileService::storeUploaded($f,$dir,[
            'application/pdf'=>['pdf'],'image/jpeg'=>['jpg','jpeg'],
            'image/png'=>['png'],'image/webp'=>['webp'],
        ],self::MAX,'emargement');
        $mime=$stored['mime'];$target=$stored['path'];
        $token=bin2hex(random_bytes(32));
        $q=Database::connection()->prepare(
            "INSERT INTO emargements_documents(
                seance_id,professeur_id,titre,nom_original,chemin_stockage,mime_type,
                taille_octets,depose_par,public_token
             ) VALUES(?,?,?,?,?,?,?,?,?)"
        );
        $q->execute([
            (int)$session['id'],(int)$session['professeur_id'],
            trim((string)($_POST['titre']??'Feuille émargement')),
            $stored['original'],str_replace(BASE_PATH.'/','',$target),
            $mime,(int)$stored['size'],(int)(Auth::user()['id']??0)?:null,$token,
        ]);
        $this->redirect($this->sheetUrl($session));
    }

    public function download(): void
    {
        Auth::requireLogin();
        Permission::require('emargements.view');
        if(isset($_GET['id'])) $this->notFound();
        $d=$this->document((string)($_GET['document']??''));
        $p=BASE_PATH.'/'.$d['chemin_stockage'];
        if(!is_file($p)) $this->notFound();
        $this->audit('attendance_document','emargements_document',(int)$d['id']);
        $this->sendFile($p,(string)$d['mime_type'],'emargement-'.date('Y-m-d',strtotime((string)$d['date_seance'])).'.'.self::TYPES[$d['mime_type']]);
    }

    public function validate(): void
    {
        Auth::requireLogin();
        Permission::require('emargements.validate');
        Csrf::verify($_POST['_csrf']??null);
        $d=$this->document((string)($_POST['document']??''));
        Database::connection()->prepare(
            "UPDATE emargements_documents SET valide=1,valide_par=?,valide_at=NOW()
             WHERE id=? AND deleted_at IS NULL"
        )->execute([(int)(Auth::user()['id']??0)?:null,(int)$d['id']]);
        $this->redirect('/presences/feuille?seance='.rawurlencode((string)$d['session_token']));
    }

    public function page(): void
    {
        Auth::requireLogin();
        Permission::require('emargements.view');
        $session=$this->session();
        $this->view('attendance/documents',['pageTitle'=>'Documents d’émargement']+Attendance::sheet($session));
    }

    private function session(?string $token=null): array
    {
        if(isset($_GET['id'])||isset($_POST['seance_id'])) $this->notFound();
        $row=Attendance::resolveSession(
            (string)($token??($_GET['seance']??'')),
            $this->organisationId(),
            Attendance::professorForUser((int)Auth::id())
        );
        if(!$row) $this->notFound();
        return $row;
    }

    private function document(string $token): array
    {
        if(!preg_match('/\A[a-f0-9]{64}\z/',strtolower($token))) $this->notFound();
        $sql=
            "SELECT d.*,se.public_token session_token,se.date_seance
             FROM emargements_documents d
             JOIN seances se ON se.id=d.seance_id AND se.deleted_at IS NULL
             JOIN groupes_cours g ON g.id=se.groupe_id
             JOIN ateliers a ON a.id=g.atelier_id
             WHERE d.public_token=? AND d.deleted_at IS NULL AND a.organisation_id=?";
        $params=[strtolower($token),$this->organisationId()];
        $own=Attendance::professorForUser((int)Auth::id());
        if($own>0){$sql.=" AND se.professeur_id=?";$params[]=$own;}
        $sql.=" LIMIT 1";
        $q=Database::connection()->prepare($sql);$q->execute($params);
        $row=$q->fetch();
        if(!$row) $this->notFound();
        return $row;
    }

    private function sendFile(string $path,string $mime,string $name): never
    {
        header('Content-Type: '.$mime);
        header('Content-Disposition: attachment; filename="'.$name.'"');
        header('Content-Length: '.filesize($path));
        header('Cache-Control: private, no-store, max-age=0');
        header('Pragma: no-cache');
        header('X-Content-Type-Options: nosniff');
        readfile($path);
        exit;
    }

    private function audit(string $module,string $type,int $id): void
    {
        Database::connection()->prepare(
            "INSERT INTO audit_logs(organisation_id,utilisateur_id,action,module,entite_type,entite_id,description)
             VALUES(?,?,'download',?,?,?,'Téléchargement sécurisé')"
        )->execute([$this->organisationId(),(int)(Auth::id()?:0)?:null,$module,$type,$id]);
    }

    private function sheetUrl(array $session): string
    {
        return '/presences/feuille?seance='.rawurlencode((string)$session['public_token']);
    }
    private function organisationId(): int{return (int)(Auth::user()['organisation_id']??1);}
    private function notFound(): never{http_response_code(404);exit('Ressource introuvable.');}
}
