<?php

declare(strict_types=1);

namespace App\Controllers;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Illuminate\Database\Capsule\Manager as DB;

class AgentController
{
    use ControllerTrait;

    private function requireAgent(Request $request, Response $response): ?Response
    {
        $apiKey = $request->getHeaderLine('X-Agent-Key');
        if (!$apiKey) return $this->error($response, 'UNAUTHORIZED', 'Clé API agent requise', 401);

        $user = DB::table('users')->where('agent_api_key', $apiKey)->where('actif', 1)->first();
        if (!$user) return $this->error($response, 'UNAUTHORIZED', 'Clé API agent invalide', 401);

        return null;
    }

    private function getAgentUser(Request $request): ?object
    {
        $apiKey = $request->getHeaderLine('X-Agent-Key');
        if (!$apiKey) return null;
        return DB::table('users')->where('agent_api_key', $apiKey)->first();
    }

    // GET /api/agent/lots-en-attente
    public function lotsEnAttente(Request $request, Response $response): Response
    {
        $guard = $this->requireAgent($request, $response);
        if ($guard) return $guard;

        $agent     = $this->getAgentUser($request);
        $atelierId = $agent->atelier_id ?? null;

        $lots = DB::table('lots')
            ->where('statut', 'en_attente_generation')
            ->where('atelier_id', $atelierId)
            ->get();

        $result = $lots->map(function ($lot) {
            // Trouver le template actif pour ce produit
            $template = DB::table('templates_gravure')
                ->where('produit_id', $lot->produit_id)
                ->where('actif', 1)
                ->first();

            // Commandes du lot
            $commandes = DB::table('commande_lot')
                ->join('commandes', 'commandes.id', '=', 'commande_lot.commande_id')
                ->leftJoin('users', 'users.id', '=', 'commandes.user_id')
                ->where('commande_lot.lot_id', $lot->id)
                ->select([
                    'commandes.id',
                    'commandes.texte_gravure',
                    'commandes.presta_order_ref as numero',
                    'commandes.type_commande',
                    'commandes.b2b_client_nom',
                    'users.prenom',
                    'users.nom',
                    'commandes.date_validation',
                ])
                ->get()
                ->map(function ($c) {
                    // Parser le texte_gravure pour extraire les placeholders
                    $parts   = explode(' / ', $c->texte_gravure ?? '');
                    $chrono  = $c->type_commande === 'b2b_vierge' ? '' : ($parts[3] ?? '');
                    $dateStr = $parts[2] ?? '';

                    return [
                        'id'             => $c->id,
                        'texte_gravure'  => $c->texte_gravure,
                        'numero'         => $c->numero,
                        'nom'            => $parts[0] ?? ($c->nom ?? ''),
                        'prenom'         => $c->prenom ?? '',
                        'chrono_formate' => $chrono,
                        'date_formate'   => $dateStr,
                    ];
                })->toArray();

            return [
                'id'                => $lot->id,
                'produit_id'        => $lot->produit_id,
                'template_gravure_id'=> $template->id ?? null,
                'commandes'         => $commandes,
            ];
        })->toArray();

        return $this->success($response, $result);
    }

    // GET /api/agent/template-gravure/:id/fichier
    public function templateFichier(Request $request, Response $response, array $args): Response
    {
        $guard = $this->requireAgent($request, $response);
        if ($guard) return $guard;

        $template = DB::table('templates_gravure')->find((int)$args['id']);
        if (!$template) return $this->error($response, 'NOT_FOUND', 'Template introuvable', 404);

        $storagePath = rtrim($_ENV['STORAGE_PATH'] ?? dirname(__DIR__, 4) . '/storage', '/');
        $filepath    = $storagePath . '/templates_dxf/' . basename($template->fichier);

        if (!file_exists($filepath)) {
            return $this->error($response, 'NOT_FOUND', 'Fichier DXF introuvable sur le serveur', 404);
        }

        $response->getBody()->write(file_get_contents($filepath));
        return $response
            ->withHeader('Content-Type', 'application/dxf')
            ->withHeader('Content-Disposition', 'attachment; filename="' . basename($filepath) . '"');
    }

    // POST /api/agent/lot/:id/rapport
    public function rapport(Request $request, Response $response, array $args): Response
    {
        $guard = $this->requireAgent($request, $response);
        if ($guard) return $guard;

        $lotId = (int)$args['id'];
        $body  = (array)$request->getParsedBody();
        $statut = $body['statut'] ?? 'succes';
        $details = $body['details'] ?? [];
        $nbFichiers = (int)($body['nb_fichiers'] ?? 0);

        // Insérer rapport
        DB::table('rapports')->insert([
            'lot_id'    => $lotId,
            'statut'    => $statut,
            'details'   => json_encode($details),
            'created_at'=> date('Y-m-d H:i:s'),
        ]);

        // Mettre à jour statut lot
        $newStatut = $statut === 'succes' ? 'genere' : 'generation_en_cours';
        DB::table('lots')->where('id', $lotId)->update(['statut' => $newStatut]);

        // Traiter les erreurs individuelles
        foreach ($details as $detail) {
            if (($detail['statut'] ?? '') === 'erreur') {
                error_log('[AgentController] DXF erreur commande ' . $detail['commande_id'] . ': ' . ($detail['message'] ?? ''));
            } elseif (($detail['statut'] ?? '') === 'ok' && isset($detail['fichier'])) {
                DB::table('fichiers_gravure')->insert([
                    'lot_id'      => $lotId,
                    'nom_fichier' => $detail['fichier'],
                    'chemin'      => $detail['fichier'],
                    'statut'      => 'genere',
                    'created_at'  => date('Y-m-d H:i:s'),
                ]);
            }
        }

        return $this->success($response, ['lot_id' => $lotId, 'statut' => $newStatut]);
    }

    // GET /api/agent/etiquettes-en-attente
    public function etiquettesEnAttente(Request $request, Response $response): Response
    {
        $guard     = $this->requireAgent($request, $response);
        if ($guard) return $guard;

        $agent     = $this->getAgentUser($request);
        $atelierId = $agent->atelier_id ?? null;

        $commandes = DB::table('commandes')
            ->join('lots', function($j) use ($atelierId) {
                $j->join('commande_lot', 'commande_lot.lot_id', '=', 'lots.id')
                  ->on('commande_lot.commande_id', '=', 'commandes.id')
                  ->where('lots.atelier_id', $atelierId);
            })
            ->leftJoin('users', 'users.id', '=', 'commandes.user_id')
            ->where('commandes.statut', 'grave')
            ->whereNotExists(function($q) {
                $q->select(DB::raw(1))
                  ->from('etiquettes_pdf')
                  ->whereColumn('etiquettes_pdf.commande_id', 'commandes.id');
            })
            ->select([
                'commandes.id as commande_id',
                'commandes.texte_gravure',
                'users.prenom', 'users.nom',
            ])
            ->get();

        $template = DB::table('templates_etiquettes')->where('actif', 1)->first();

        return $this->success($response, $commandes->map(fn($c) => [
            'commande_id'          => $c->commande_id,
            'template_etiquette_id'=> $template->id ?? 1,
            'destinataire'         => [
                'nom'    => $c->nom ?? '',
                'prenom' => $c->prenom ?? '',
            ],
        ])->toArray());
    }

    // GET /api/agent/etiquette/:id/pdf
    public function etiquettePdf(Request $request, Response $response, array $args): Response
    {
        $guard = $this->requireAgent($request, $response);
        if ($guard) return $guard;

        $commandeId  = (int)$args['id'];
        $storagePath = rtrim($_ENV['STORAGE_PATH'] ?? dirname(__DIR__, 4) . '/storage', '/');
        $filepath    = $storagePath . '/etiquettes_pdf/etiquette_' . $commandeId . '.pdf';

        if (!file_exists($filepath)) {
            // Générer le PDF avec dompdf côté serveur
            $pdf = $this->genererEtiquettePdf($commandeId);
            if (!$pdf) return $this->error($response, 'NOT_FOUND', 'Impossible de générer le PDF', 404);
            $filepath = $pdf;
        }

        $response->getBody()->write(file_get_contents($filepath));
        return $response
            ->withHeader('Content-Type', 'application/pdf')
            ->withHeader('Content-Disposition', 'attachment; filename="etiquette_' . $commandeId . '.pdf"');
    }

    private function genererEtiquettePdf(int $commandeId): ?string
    {
        // Génération PDF côté serveur via dompdf si disponible
        $commande = DB::table('commandes')
            ->join('users', 'users.id', '=', 'commandes.user_id')
            ->where('commandes.id', $commandeId)
            ->select(['commandes.*', 'users.prenom', 'users.nom'])
            ->first();

        if (!$commande) return null;

        $html = '<html><body style="font-family:Arial;font-size:14px;padding:20px;">'
            . '<h2>MyKollectOr®</h2>'
            . '<p><strong>' . htmlspecialchars($commande->prenom . ' ' . $commande->nom) . '</strong></p>'
            . '<p>Ref: ' . htmlspecialchars($commande->presta_order_ref ?? '') . '</p>'
            . '<p style="font-family:Courier New;border:1px solid #ccc;padding:8px;">'
            . htmlspecialchars($commande->texte_gravure ?? '') . '</p>'
            . '</body></html>';

        if (class_exists('Dompdf\Dompdf')) {
            $dompdf = new \Dompdf\Dompdf();
            $dompdf->loadHtml($html);
            $dompdf->setPaper('A6', 'portrait');
            $dompdf->render();

            $storagePath = rtrim($_ENV['STORAGE_PATH'] ?? dirname(__DIR__, 4) . '/storage', '/');
            $dir         = $storagePath . '/etiquettes_pdf';
            if (!is_dir($dir)) mkdir($dir, 0755, true);

            $filepath = $dir . '/etiquette_' . $commandeId . '.pdf';
            file_put_contents($filepath, $dompdf->output());
            return $filepath;
        }

        return null;
    }

    // POST /api/agent/commande/:id/etiquette-generee
    public function confirmerEtiquette(Request $request, Response $response, array $args): Response
    {
        $guard      = $this->requireAgent($request, $response);
        if ($guard) return $guard;

        $commandeId = (int)$args['id'];
        $body       = (array)$request->getParsedBody();

        DB::table('etiquettes_pdf')->insertOrIgnore([
            'commande_id' => $commandeId,
            'fichier'     => $body['fichier'] ?? '',
            'statut'      => $body['statut'] ?? 'ok',
            'created_at'  => date('Y-m-d H:i:s'),
        ]);

        return $this->success($response, ['commande_id' => $commandeId]);
    }

    // POST /api/agent/heartbeat
    public function heartbeat(Request $request, Response $response): Response
    {
        $guard = $this->requireAgent($request, $response);
        if ($guard) return $guard;

        $agent  = $this->getAgentUser($request);
        $body   = (array)$request->getParsedBody();

        // Mettre à jour le dernier heartbeat
        DB::table('users')->where('id', $agent->id)->update([
            'agent_last_heartbeat' => date('Y-m-d H:i:s'),
            'agent_version'        => $body['agent_version'] ?? null,
        ]);

        return $this->success($response, [
            'status'       => 'ok',
            'heure_serveur'=> date('Y-m-d\TH:i:s\Z'),
        ]);
    }
}
