<?php
namespace App\Controllers;

use App\Core\Auth;
use App\Core\Controller;
use App\Core\Database;

class PlanningController extends Controller
{
    private \PDO $db;

    public function __construct()
    {
    $this->db = Database::pdo();
        // Garde-fou: s'assurer que la table existe (dev friendly)
        $this->db->exec("CREATE TABLE IF NOT EXISTS planning_tasks (
            id INT AUTO_INCREMENT PRIMARY KEY,
            title VARCHAR(200) NOT NULL,
            type ENUM('préventive','corrective') NOT NULL DEFAULT 'corrective',
            start_datetime DATETIME NOT NULL,
            end_datetime DATETIME NULL,
            status ENUM('Planifié','En cours','Terminé','Annulé') NOT NULL DEFAULT 'Planifié',
            technician_id INT NULL,
            incident_id INT NULL,
            location_id INT NULL,
            notes TEXT NULL,
            color VARCHAR(7) NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
    }

    private function resolvePlanningScope(string $action): string
    {
        $scope = Auth::permissionScope('planning', $action);
        if ($scope !== 'none') {
            return $scope;
        }

        $user = Auth::user();
        $roleKey = (string)($user['role_key'] ?? '');

        if (in_array($roleKey, ['admin', 'agent', 'manager', 'superviseur', 'supervisor'], true)) {
            return 'all';
        }

        if (in_array($roleKey, ['technicien', 'technician'], true)) {
            return 'own';
        }

        return 'none';
    }

    private function denyPlanningAccess(bool $json = false): void
    {
        http_response_code(403);
        if ($json) {
            header('Content-Type: application/json; charset=utf-8');
            echo json_encode(['error' => 'forbidden']);
            return;
        }

        exit('Accès refusé.');
    }

    private function canAccessPlanningTask(array $task, array $user, string $scope): bool
    {
        if ($scope === 'all') {
            return true;
        }

        if ($scope !== 'own') {
            return false;
        }

        return (int)($task['technician_id'] ?? 0) === (int)($user['id'] ?? 0);
    }

    public function index(): void
    {
        if (!Auth::check()) { $this->redirect('/login'); }
        $currentUser = Auth::user() ?? [];
        $viewScope = $this->resolvePlanningScope('view');
        if ($viewScope === 'none') {
            $this->denyPlanningAccess();
            return;
        }

        // Récupérer listes utiles (techniciens, incidents, sites) de manière défensive
        try {
            if ($viewScope === 'own') {
                $stmt = $this->db->prepare("SELECT id, name, role_key FROM users WHERE active=1 AND id = ? ORDER BY name");
                $stmt->execute([(int)($currentUser['id'] ?? 0)]);
                $techs = $stmt->fetchAll(\PDO::FETCH_ASSOC);
            } else {
                $techs = $this->db->query("SELECT id, name, role_key FROM users WHERE active=1 ORDER BY name")->fetchAll(\PDO::FETCH_ASSOC);
            }
        } catch (\Throwable $e) { $techs = []; }

        // Vérifier si la colonne incidents.ticket_id existe avant de la référencer
        $hasTicketId = false;
        try {
            $db = $this->db->query('SELECT DATABASE()')->fetchColumn() ?: '';
            if ($db) {
                $chk = $this->db->prepare('SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=? AND TABLE_NAME=? AND COLUMN_NAME=?');
                $chk->execute([$db, 'incidents', 'ticket_id']);
                $hasTicketId = ((int)$chk->fetchColumn() > 0);
            }
        } catch (\Throwable $e) { $hasTicketId = false; }

        try {
            if ($hasTicketId) {
                $incidents = $this->db->query("SELECT id, ticket_id, title FROM incidents ORDER BY id DESC LIMIT 200")->fetchAll(\PDO::FETCH_ASSOC);
            } else {
                $incidents = $this->db->query("SELECT id, reference, title FROM incidents ORDER BY id DESC LIMIT 200")->fetchAll(\PDO::FETCH_ASSOC);
                foreach ($incidents as &$i) { $i['ticket_id'] = $i['reference'] ?? ('INC-' . (int)$i['id']); }
                unset($i);
            }
        } catch (\Throwable $e) { $incidents = []; }

        try {
            $locations = $this->db->query("SELECT id, name FROM locations WHERE active=1 ORDER BY name")->fetchAll(\PDO::FETCH_ASSOC);
        } catch (\Throwable $e) { $locations = []; }

        $this->view('planning.index', [
            'title' => 'Planning',
            'techs' => $techs,
            'incidents' => $incidents,
            'locations' => $locations,
            'planningScope' => $viewScope,
        ]);
    }

    public function events(): void
    {
        if (!Auth::check()) { http_response_code(401); echo json_encode(['error' => 'unauthorized']); return; }
        $user = Auth::user() ?? [];
        $viewScope = $this->resolvePlanningScope('view');
        if ($viewScope === 'none') {
            $this->denyPlanningAccess(true);
            return;
        }
        header('Content-Type: application/json; charset=utf-8');

        $sql = "SELECT t.*, u.name AS technician_name, i.id AS incident_id, i.reference AS incident_ref, l.name AS location_name
                  FROM planning_tasks t
                  LEFT JOIN users u ON u.id = t.technician_id
                  LEFT JOIN incidents i ON i.id = t.incident_id
                  LEFT JOIN locations l ON l.id = t.location_id";
        if ($viewScope === 'own') {
            $sql .= ' WHERE t.technician_id = :user_id';
        }
        $stmt = $this->db->prepare($sql);
        if ($viewScope === 'own') {
            $stmt->bindValue(':user_id', (int)($user['id'] ?? 0), \PDO::PARAM_INT);
        }
        $stmt->execute();
        $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $events = array_map(function($r){
            return [
                'id' => (int)$r['id'],
                'title' => $r['title'],
                'start' => str_replace(' ', 'T', $r['start_datetime']),
                'end' => $r['end_datetime'] ? str_replace(' ', 'T', $r['end_datetime']) : null,
                'backgroundColor' => $r['color'] ?: ($r['type'] === 'préventive' ? '#0d6efd' : '#dc3545'),
                'borderColor' => $r['color'] ?: ($r['type'] === 'préventive' ? '#0d6efd' : '#dc3545'),
                'extendedProps' => [
                    'type' => $r['type'],
                    'status' => $r['status'],
                    'technician' => $r['technician_name'] ?? null,
                    'incident' => ($r['incident_ref'] ?? (isset($r['incident_id']) ? ('INC-' . (int)$r['incident_id']) : null)),
                    'location' => $r['location_name'] ?? null,
                ]
            ];
        }, $rows);

        echo json_encode($events);
    }

    public function save(): void
    {
        if (!Auth::check()) { http_response_code(401); echo 'unauthorized'; return; }
        $user = Auth::user() ?? [];
        $editScope = $this->resolvePlanningScope('edit');
        if ($editScope === 'none') {
            $this->denyPlanningAccess(true);
            return;
        }
        $id = isset($_POST['id']) ? (int)$_POST['id'] : 0;
        $title = trim($_POST['title'] ?? '');
        $type = $_POST['type'] ?? 'corrective';
        $start = $_POST['start'] ?? null;
        $end = $_POST['end'] ?? null;
        $technician_id = !empty($_POST['technician_id']) ? (int)$_POST['technician_id'] : null;
        $incident_id = !empty($_POST['incident_id']) ? (int)$_POST['incident_id'] : null;
        $location_id = !empty($_POST['location_id']) ? (int)$_POST['location_id'] : null;
        $color = $_POST['color'] ?? null;

        if ($editScope === 'own') {
            $technician_id = (int)($user['id'] ?? 0);
        }

        if ($id > 0) {
            if ($editScope === 'own') {
                $existingStmt = $this->db->prepare('SELECT technician_id FROM planning_tasks WHERE id = :id');
                $existingStmt->execute([':id' => $id]);
                $existingTask = $existingStmt->fetch(\PDO::FETCH_ASSOC) ?: null;
                if (!$existingTask || !$this->canAccessPlanningTask($existingTask, $user, $editScope)) {
                    $this->denyPlanningAccess(true);
                    return;
                }
            }

            // Update dates (utilisé pour drag&drop / resize)
            $stmt = $this->db->prepare("UPDATE planning_tasks SET title = COALESCE(NULLIF(:title,''), title), type = :type, start_datetime = :start, end_datetime = :end, technician_id = :tech, incident_id = :incident, location_id = :loc, color = :color WHERE id = :id");
            $stmt->execute([
                ':title' => $title,
                ':type' => $type,
                ':start' => $start,
                ':end' => $end,
                ':tech' => $technician_id,
                ':incident' => $incident_id,
                ':loc' => $location_id,
                ':color' => $color,
                ':id' => $id
            ]);
        } else {
            if ($title === '' || !$start) {
                http_response_code(422); echo 'Titre et date début requis'; return; }
            $stmt = $this->db->prepare("INSERT INTO planning_tasks (title, type, start_datetime, end_datetime, technician_id, incident_id, location_id, color) VALUES (:title, :type, :start, :end, :tech, :incident, :loc, :color)");
            $stmt->execute([
                ':title' => $title,
                ':type' => $type,
                ':start' => $start,
                ':end' => $end,
                ':tech' => $technician_id,
                ':incident' => $incident_id,
                ':loc' => $location_id,
                ':color' => $color
            ]);
        }

        $this->jsonOk();
    }

    public function delete(): void
    {
        if (!Auth::check()) { http_response_code(401); echo 'unauthorized'; return; }
        $user = Auth::user() ?? [];
        $editScope = $this->resolvePlanningScope('edit');
        if ($editScope === 'none') {
            $this->denyPlanningAccess(true);
            return;
        }
        $id = isset($_POST['id']) ? (int)$_POST['id'] : 0;
        if ($id <= 0) { http_response_code(400); echo 'bad request'; return; }
        if ($editScope === 'own') {
            $existingStmt = $this->db->prepare('SELECT technician_id FROM planning_tasks WHERE id = :id');
            $existingStmt->execute([':id' => $id]);
            $existingTask = $existingStmt->fetch(\PDO::FETCH_ASSOC) ?: null;
            if (!$existingTask || !$this->canAccessPlanningTask($existingTask, $user, $editScope)) {
                $this->denyPlanningAccess(true);
                return;
            }
        }
        $stmt = $this->db->prepare("DELETE FROM planning_tasks WHERE id = :id");
        $stmt->execute([':id' => $id]);
        $this->jsonOk();
    }

    public function detail(): void
    {
        if (!Auth::check()) { $this->redirect('/login'); }
        $user = Auth::user() ?? [];
        $viewScope = $this->resolvePlanningScope('view');
        if ($viewScope === 'none') {
            $this->denyPlanningAccess();
            return;
        }
        $id = (int)($_GET['id'] ?? 0);
        if ($id <= 0) { $this->redirect('/planning'); }
        $stmt = $this->db->prepare("SELECT t.*, 
                u.name AS technician_name, u.email AS technician_email,
                i.reference AS incident_ref, i.title AS incident_title, i.id AS incident_id,
                l.name AS location_name
            FROM planning_tasks t
            LEFT JOIN users u ON u.id = t.technician_id
            LEFT JOIN incidents i ON i.id = t.incident_id
            LEFT JOIN locations l ON l.id = t.location_id
            WHERE t.id = :id");
        $stmt->execute([':id' => $id]);
        $task = $stmt->fetch(\PDO::FETCH_ASSOC);
        if (!$task) { $this->redirect('/planning'); }
        if (!$this->canAccessPlanningTask($task, $user, $viewScope)) {
            $this->redirect('/planning?err=forbidden');
            return;
        }
        // Composer une valeur d'affichage pour l'incident si nécessaire
        if (!isset($task['incident_ticket'])) {
            $task['incident_ticket'] = $task['incident_ref'] ?? ('INC-' . (int)($task['incident_id'] ?? 0));
        }
        $this->view('planning.detail', [ 'task' => $task, 'title' => 'Détail planification' ]);
    }

    private function jsonOk(): void
    {
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(['ok' => true]);
    }
}
