<?php

declare(strict_types=1);

namespace App\Controllers;

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

class TeacherController
{
    private Connection $db;

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

    /**
     * Mostra un elenco di insegnanti.
     * GET /api/teachers
     */
    public function index(): void
    {
        try {
            $queryBuilder = $this->db->createQueryBuilder();
            $teachers = $queryBuilder
                ->select('id', 'first_name', 'last_name', 'email', 'phone', 'is_active') // Seleziona solo alcuni campi per la lista
                ->from('teachers')
                ->orderBy('last_name', 'ASC')
                ->addOrderBy('first_name', 'ASC')
                ->fetchAllAssociative();

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

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

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

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

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

        // Validazione di base
        if (empty($input['first_name']) || empty($input['last_name'])) {
            http_response_code(400);
            echo json_encode(['error' => 'Missing required fields: first_name, last_name']);
            return;
        }

        $dataToInsert = [
            'first_name' => $input['first_name'],
            'last_name' => $input['last_name'],
            'email' => $input['email'] ?? null,
            'phone' => $input['phone'] ?? null,
            'date_of_birth' => !empty($input['date_of_birth']) ? $input['date_of_birth'] : null,
            'hire_date' => !empty($input['hire_date']) ? $input['hire_date'] : null,
            'qualifications' => $input['qualifications'] ?? null,
            'is_active' => isset($input['is_active']) ? (bool)$input['is_active'] : true,
        ];

        try {
            $result = $this->db->insert('teachers', $dataToInsert);

             if ($result === false || $result === 0) {
                 throw new \Exception("Failed to insert teacher, insert returned non-true value.");
            }

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

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

    /**
     * Aggiorna un insegnante esistente.
     * PUT /api/teachers/{id}
     */
    public function update(array $vars): void
    {
        $id = $vars['id'] ?? null;
         if ($id === null) {
             http_response_code(400);
             echo json_encode(['error' => 'Missing teacher 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;
        }

        $dataToUpdate = [];
        $allowedFields = ['first_name', 'last_name', 'email', 'phone', 'date_of_birth', 'hire_date', 'qualifications', 'is_active'];
        foreach ($allowedFields as $field) {
            if (array_key_exists($field, $input)) {
                 // Gestione specifica per booleano e date nulle
                 if ($field === 'is_active') {
                     $dataToUpdate[$field] = (bool)$input[$field];
                 } elseif (($field === 'date_of_birth' || $field === 'hire_date') && empty($input[$field])) {
                     $dataToUpdate[$field] = null;
                 } 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 teachers WHERE id = ?', [$id]);
            if ($existing === false) {
                 http_response_code(404);
                 echo json_encode(['error' => "Teacher with ID {$id} not found"]);
                 return;
            }

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

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

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

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

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

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

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

        } catch (\Throwable $e) {
            // Considera gestione Foreign Key Constraints se l'insegnante è referenziato altrove
            http_response_code(500);
            error_log("Error deleting teacher {$id}: " . $e->getMessage());
            echo json_encode(['error' => 'Failed to delete teacher']);
        }
    }
}