<?php
/**
 * Fichier  : api/archive.php
 * Auteur   : KREMER Régis
 * Version  : 2.6.84
 * Date     : 2026-07-20
 * Description : API REST — Archivage et lecture d'archives annuelles
 *
 * Entités archivables : products, stock, movements, inventories,
 *                       orders, alerts, product_versions
 * Entités exclues     : users, warehouses, suppliers, brands,
 *                       categories, settings, permissions
 *
 * Routes :
 *   GET  ?action=list          — liste des archives disponibles
 *   GET  ?action=status        — statut (date dernier archivage, rappel annuel)
 *   GET  ?action=read&file=X   — lire le contenu d'une archive
 *   POST action=create         — créer une archive (admin)
 *   POST action=restore&file=X — restaurer une archive (admin, dangereux)
 *   POST action=delete&file=X  — supprimer une archive (admin)
 *   v2.6.84 (2026-07-20) — Confirmation serveur obligatoire pour restauration et suppression.
 */
require_once dirname(__DIR__).'/config.php';
startSession(); requireAuth(); requireAdmin(); requirePerm('archive.manage');

$method = $_SERVER['REQUEST_METHOD'];
$body   = json_decode(file_get_contents('php://input'), true) ?? [];
$action = $_GET['action'] ?? ($body['action'] ?? '');

// Dossier archives
$ARCHIVE_DIR = DATA_DIR . '/archives';
if (!is_dir($ARCHIVE_DIR)) mkdir($ARCHIVE_DIR, 0775, true);

// Entités archivables (dans l'ordre logique)
const ARCHIVABLE = ['products', 'stock', 'movements', 'inventories', 'orders', 'alerts', 'product_versions'];

// ════════════════════════════════════════════════════════════════
// HELPERS
// ════════════════════════════════════════════════════════════════
function listArchives(string $dir): array {
    $files = glob($dir . '/archive_*.json') ?: [];
    $result = [];
    foreach ($files as $f) {
        $name = basename($f);
        $size = filesize($f);
        $content = json_decode(file_get_contents($f), true);
        $result[] = [
            'file'      => $name,
            'size'      => $size,
            'sizeHuman' => formatBytes($size),
            'createdAt' => $content['createdAt']  ?? '',
            'label'     => $content['label']       ?? $name,
            'year'      => $content['year']        ?? '',
            'entities'  => array_keys($content['data'] ?? []),
            'counts'    => $content['counts']      ?? [],
        ];
    }
    // Tri décroissant par date
    usort($result, fn($a, $b) => strcmp($b['createdAt'], $a['createdAt']));
    return $result;
}

function formatBytes(int $bytes): string {
    if ($bytes < 1024)        return $bytes . ' o';
    if ($bytes < 1048576)     return round($bytes / 1024, 1) . ' Ko';
    return round($bytes / 1048576, 1) . ' Mo';
}

function getArchiveStatus(): array {
    $s = getSettings();
    $lastArchive = $s['lastArchiveAt'] ?? null;
    $now         = time();
    $needsReminder = false;

    if ($lastArchive) {
        $lastYear  = (int)date('Y', strtotime($lastArchive));
        $thisYear  = (int)date('Y');
        $dayOfYear = (int)date('z') + 1; // 1 = 1er jan
        // Rappel : nouvelle année ET pas encore archivé cette année ET dans les 60 premiers jours
        $needsReminder = ($thisYear > $lastYear) && ($dayOfYear <= 60);
    } else {
        // Jamais archivé et on a au moins des données
        $needsReminder = !empty(loadData('movements'));
    }

    return [
        'lastArchiveAt' => $lastArchive,
        'needsReminder' => $needsReminder,
        'currentYear'   => date('Y'),
    ];
}

// ════════════════════════════════════════════════════════════════
// ROUTES GET
// ════════════════════════════════════════════════════════════════
if ($method === 'GET') {

    if ($action === 'status') {
        jsonResponse(getArchiveStatus());
    }

    if ($action === 'list') {
        jsonResponse(listArchives($ARCHIVE_DIR));
    }

    if ($action === 'read') {
        requireAdmin();
        $file = basename($_GET['file'] ?? '');
        if (!$file || !preg_match('/^archive_[\w\-]+\.json$/', $file)) {
            jsonError('Nom de fichier invalide.');
        }
        $path = $ARCHIVE_DIR . '/' . $file;
        if (!file_exists($path)) jsonError('Archive introuvable.', 404);
        $content = json_decode(file_get_contents($path), true);
        jsonResponse($content);
    }

    jsonError('Action inconnue.', 400);
}

// ════════════════════════════════════════════════════════════════
// ROUTES POST — admin requis
// ════════════════════════════════════════════════════════════════
if ($method === 'POST') {
    requireAdmin();
    csrfCheck();

    // ── CRÉER une archive ──
    if ($action === 'create') {
        $label    = trim($body['label'] ?? '');
        $year     = $body['year'] ?? date('Y');
        $entities = $body['entities'] ?? ARCHIVABLE; // quoi archiver

        // Valider les entités
        $entities = array_filter($entities, fn($e) => in_array($e, ARCHIVABLE));
        if (empty($entities)) jsonError('Aucune entité valide à archiver.');

        $data   = [];
        $counts = [];
        foreach ($entities as $entity) {
            // product_versions : agréger les fichiers par produit + l'ancien global
            $items          = ($entity === 'product_versions') ? pvReadAll() : loadData($entity);
            $data[$entity]  = $items;
            $counts[$entity] = count($items);
        }

        $archive = [
            'label'     => $label ?: 'Archive ' . date('d/m/Y H:i'),
            'year'      => $year,
            'createdAt' => date('c'),
            'createdBy' => (currentUser()['username'] ?? 'admin'),
            'entities'  => array_values($entities),
            'counts'    => $counts,
            'data'      => $data,
        ];

        $filename = 'archive_' . date('Y-m-d_H-i-s') . '_' . preg_replace('/[^a-z0-9]/i', '-', $label ?: $year) . '.json';
        $path     = $ARCHIVE_DIR . '/' . $filename;

        if (file_put_contents($path, json_encode($archive, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)) === false) {
            jsonError('Impossible d\'écrire l\'archive.');
        }

        // Mettre à jour lastArchiveAt dans les settings
        $s = getSettings();
        $s['lastArchiveAt'] = date('c');
        saveSettings($s);

        jsonResponse([
            'ok'       => true,
            'file'     => $filename,
            'counts'   => $counts,
            'sizeHuman'=> formatBytes(filesize($path)),
        ], 201);
    }

    // ── SUPPRIMER une archive ──
    if ($action === 'delete') {
        if (!hash_equals('SUPPRIMER', (string)($body['confirmation'] ?? ''))) {
            jsonError('Confirmation de suppression invalide.', 409);
        }
        $file = basename($body['file'] ?? '');
        if (!$file || !preg_match('/^archive_[\w\-]+\.json$/', $file)) {
            jsonError('Nom de fichier invalide.');
        }
        $path = $ARCHIVE_DIR . '/' . $file;
        if (!file_exists($path)) jsonError('Archive introuvable.', 404);
        unlink($path);
        jsonResponse(['ok' => true]);
    }

    // ── RESTAURER une archive (DANGEREUX) ──
    if ($action === 'restore') {
        if (!hash_equals('RESTAURER', (string)($body['confirmation'] ?? ''))) {
            jsonError('Confirmation de restauration invalide.', 409);
        }
        $file = basename($body['file'] ?? '');
        if (!$file || !preg_match('/^archive_[\w\-]+\.json$/', $file)) {
            jsonError('Nom de fichier invalide.');
        }
        $path = $ARCHIVE_DIR . '/' . $file;
        if (!file_exists($path)) jsonError('Archive introuvable.', 404);

        $archive = json_decode(file_get_contents($path), true);
        if (!$archive || !isset($archive['data'])) jsonError('Archive corrompue.');

        $restored = [];
        foreach ($archive['data'] as $entity => $items) {
            if (!in_array($entity, ARCHIVABLE)) continue;
            $list = is_array($items) ? $items : [];
            if ($entity === 'product_versions') {
                // Vider les fichiers par produit + l'ancien global, puis redistribuer
                foreach (glob(pvDir().'/*.json') ?: [] as $f) { @unlink($f); }
                saveData('product_versions', []); // repli global remis à zéro
                pvSaveAll($list);                  // réécrit data/versions/{id}.json
            } else {
                saveData($entity, $list);
            }
            $restored[$entity] = count($list);
        }

        jsonResponse(['ok' => true, 'restored' => $restored]);
    }

    jsonError('Action inconnue.', 400);
}

jsonError('Méthode non supportée.', 405);
