<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Database;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;

class SchoolYearController
{
    private Connection $db;

    public function __construct()
    {
        try {
            $this->db = Database::getConnection();
        } catch (\Throwable $e) {
            error_log("Failed to get DB connection in SchoolYearController: " . $e->getMessage());
            http_response_code(500);
            echo json_encode(['error' => 'Internal Server Error - DB Connection']);
            exit;
        }
    }

    /**
     * Mostra un elenco di anni scolastici.
     * GET /api/school-years
     */
    public function index(): void
    {
        try {
            $queryBuilder = $this->db->createQueryBuilder();
            // Ordina per data di inizio decrescente per vedere i più recenti prima
            $schoolYears = $queryBuilder
                ->select('*')
                ->from('school_years')
                ->orderBy('start_date', 'ASC')
                ->fetchAllAssociative();

            echo json_encode($schoolYears);
        } catch (\Throwable $e) {
            http_response_code(500);
            error_log("Error fetching school years: " . $e->getMessage());
            echo json_encode(['error' => 'Failed to fetch school years']);
        }
    }

    /**
     * Mostra un anno scolastico specifico.
     * GET /api/school-years/{id}
     */
    public function show(array $vars): void
    {
        $id = $vars['id'] ?? null;
        if ($id === null) {
             http_response_code(400);
             echo json_encode(['error' => 'Missing school year ID']);
             return;
        }

        try {
            $schoolYear = $this->db->fetchAssociative('SELECT * FROM school_years WHERE id = ?', [$id]);

            if ($schoolYear === false) {
                http_response_code(404);
                echo json_encode(['error' => "School year with ID {$id} not found"]);
            } else {
                echo json_encode($schoolYear);
            }
        } catch (\Throwable $e) {
            http_response_code(500);
            error_log("Error fetching school year {$id}: " . $e->getMessage());
            echo json_encode(['error' => 'Failed to fetch school year']);
        }
    }

    /**
     * Crea un nuovo anno scolastico.
     * POST /api/school-years
     */
    public function store(): void
    {
        $input = (array) json_decode(file_get_contents('php://input'), true);
        if (empty($input) && !empty($_POST)) { $input = $_POST; }

        // Validazione
        if (empty($input['name']) || empty($input['start_date']) || empty($input['end_date'])) {
            http_response_code(400);
            echo json_encode(['error' => 'Missing required fields: name, start_date, end_date']);
            return;
        }
        if (strtotime($input['end_date']) <= strtotime($input['start_date'])) {
             http_response_code(400);
             echo json_encode(['error' => 'End date must be after start date']);
             return;
        }

        $dataToInsert = [
            'name' => $input['name'],
            'start_date' => $input['start_date'], // Assumiamo formato YYYY-MM-DD
            'end_date' => $input['end_date'],     // Assumiamo formato YYYY-MM-DD
            'is_active' => isset($input['is_active']) ? (bool)$input['is_active'] : false, // Default a false
        ];

        try {
            // Se is_active è true, assicurati che nessun altro anno sia attivo
            if ($dataToInsert['is_active']) {
                $this->db->executeStatement('UPDATE school_years SET is_active = false WHERE is_active = true');
            }

            $result = $this->db->insert('school_years', $dataToInsert);

             if ($result === false || $result === 0) {
                 throw new \Exception("Failed to insert school year.");
            }

            $newId = $this->db->lastInsertId();
            http_response_code(201);
            $newSchoolYear = $this->db->fetchAssociative('SELECT * FROM school_years WHERE id = ?', [$newId]);
            echo json_encode($newSchoolYear);

        } catch (UniqueConstraintViolationException $e) {
             http_response_code(409); // Conflict
             error_log("Error creating school year (duplicate name?): " . $e->getMessage());
             echo json_encode(['error' => 'Failed to create school year. Name might already exist.']);
        } catch (\Throwable $e) {
            http_response_code(500);
            error_log("Error creating school year: " . $e->getMessage());
            echo json_encode(['error' => 'Failed to create school year']);
        }
    }

    /**
     * Aggiorna un anno scolastico esistente.
     * PUT /api/school-years/{id}
     */
    public function update(array $vars): void
    {
        $id = $vars['id'] ?? null;
         if ($id === null) {
             http_response_code(400);
             echo json_encode(['error' => 'Missing school year ID']);
             return;
        }

        $inputJson = file_get_contents('php://input');
        $input = $inputJson ? (array) json_decode($inputJson, true) : [];
        if (empty($input) && $inputJson && ($_SERVER['CONTENT_TYPE'] ?? '') === 'application/x-www-form-urlencoded') {
             parse_str($inputJson, $input);
        }
         if (empty($input)) {
             http_response_code(400);
             echo json_encode(['error' => 'Missing update data']);
             return;
        }

        // Validazione date se presenti
        $startDate = $input['start_date'] ?? null;
        $endDate = $input['end_date'] ?? null;
        // Se vengono fornite entrambe le date, valida la loro coerenza
        if ($startDate && $endDate && strtotime($endDate) <= strtotime($startDate)) {
             http_response_code(400);
             echo json_encode(['error' => 'End date must be after start date']);
             return;
        }
        // Se viene fornita solo una data, recupera l'altra dal DB per validare
        if (($startDate && !$endDate) || (!$startDate && $endDate)) {
             $currentDates = $this->db->fetchAssociative('SELECT start_date, end_date FROM school_years WHERE id = ?', [$id]);
             if ($currentDates) {
                 if ($startDate && strtotime($currentDates['end_date']) <= strtotime($startDate)) {
                     http_response_code(400); echo json_encode(['error' => 'Start date must be before existing end date']); return;
                 }
                 if ($endDate && strtotime($endDate) <= strtotime($currentDates['start_date'])) {
                      http_response_code(400); echo json_encode(['error' => 'End date must be after existing start date']); return;
                 }
             }
        }


        $dataToUpdate = [];
        $allowedFields = ['name', 'start_date', 'end_date', 'is_active'];
        foreach ($allowedFields as $field) {
            if (array_key_exists($field, $input)) {
                 if ($field === 'is_active') {
                     $dataToUpdate[$field] = (bool)$input[$field];
                 } else {
                    $dataToUpdate[$field] = $input[$field];
                 }
            }
        }

        if (empty($dataToUpdate)) {
             http_response_code(400);
             echo json_encode(['error' => 'No valid fields provided for update']);
             return;
        }

        try {
            $existing = $this->db->fetchOne('SELECT 1 FROM school_years WHERE id = ?', [$id]);
            if ($existing === false) {
                 http_response_code(404);
                 echo json_encode(['error' => "School year with ID {$id} not found"]);
                 return;
            }

            // Se si sta attivando questo anno, disattiva gli altri
            if (isset($dataToUpdate['is_active']) && $dataToUpdate['is_active']) {
                 $this->db->executeStatement('UPDATE school_years SET is_active = false WHERE is_active = true AND id != ?', [$id]);
            }

            $this->db->update('school_years', $dataToUpdate, ['id' => $id]);

            $updatedSchoolYear = $this->db->fetchAssociative('SELECT * FROM school_years WHERE id = ?', [$id]);
            echo json_encode($updatedSchoolYear);

        } catch (UniqueConstraintViolationException $e) {
             http_response_code(409); // Conflict
             error_log("Error updating school year {$id} (duplicate name?): " . $e->getMessage());
             echo json_encode(['error' => 'Failed to update school year. Name might already exist.']);
        } catch (\Throwable $e) {
            http_response_code(500);
            error_log("Error updating school year {$id}: " . $e->getMessage());
            echo json_encode(['error' => 'Failed to update school year']);
        }
    }

    /**
     * Elimina un anno scolastico.
     * DELETE /api/school-years/{id}
     */
    public function delete(array $vars): void
    {
        $id = $vars['id'] ?? null;
        if ($id === null) {
             http_response_code(400);
             echo json_encode(['error' => 'Missing school year ID']);
             return;
        }

        try {
            // Aggiungere qui controlli se l'anno scolastico è referenziato altrove (es. contratti)
            // prima di permettere l'eliminazione.
            // Esempio: $count = $this->db->fetchOne('SELECT COUNT(*) FROM contracts WHERE school_year_id = ?', [$id]);
            // if ($count > 0) { http_response_code(409); echo json_encode(...); return; }

            $existing = $this->db->fetchOne('SELECT 1 FROM school_years WHERE id = ?', [$id]);
            if ($existing === false) {
                 http_response_code(404);
                 echo json_encode(['error' => "School year with ID {$id} not found"]);
                 return;
            }

            $deletedRows = $this->db->delete('school_years', ['id' => $id]);

            if ($deletedRows > 0) {
                http_response_code(204); // No Content
            } else {
                 http_response_code(500);
                 error_log("Failed to delete school year {$id}, delete returned 0 rows affected.");
                 echo json_encode(['error' => 'Failed to delete school year']);
            }

        } catch (\Throwable $e) {
            http_response_code(500);
            error_log("Error deleting school year {$id}: " . $e->getMessage());
            echo json_encode(['error' => 'Failed to delete school year']);
        }
    }
}