<?php

declare(strict_types=1);

namespace App\Controllers;

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

class StructureController
{
    private Connection $db;

    public function __construct()
    {
        // Ottieni la connessione al database
        // In un'applicazione reale, useresti Dependency Injection
        try {
            $this->db = Database::getConnection();
        } catch (\Throwable $e) {
            // Gestisci l'errore di connessione iniziale se necessario
            error_log("Failed to get DB connection in StructureController: " . $e->getMessage());
            // Potresti voler lanciare un'eccezione o impostare uno stato di errore
            // Per ora, usciamo o lanciamo un errore HTTP 500 se la connessione fallisce qui
            http_response_code(500);
            echo json_encode(['error' => 'Internal Server Error - DB Connection']);
            exit;
        }
    }

    /**
     * Mostra un elenco di strutture.
     * GET /api/structures
     */
    public function index(): void
    {
        try {
            $queryBuilder = $this->db->createQueryBuilder();
            $structures = $queryBuilder
                ->select('*')
                ->from('structures')
                ->orderBy('name', 'ASC') // Ordina per nome
                ->fetchAllAssociative(); // Recupera tutti i risultati come array associativi

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

    /**
     * Mostra una struttura specifica.
     * GET /api/structures/{id}
     * @param array $vars Variabili dalla route (es. ['id' => '1'])
     */
    public function show(array $vars): void
    {
        $id = $vars['id'] ?? null;
        if ($id === null) {
             http_response_code(400); // Bad Request
             echo json_encode(['error' => 'Missing structure ID']);
             return;
        }

        try {
            // Usa fetchAssociative per recuperare una singola riga
            $structure = $this->db->fetchAssociative('SELECT * FROM structures WHERE id = ?', [$id]);

            if ($structure === false) {
                // Nessuna struttura trovata con quell'ID
                http_response_code(404); // Not Found
                echo json_encode(['error' => "Structure with ID {$id} not found"]);
            } else {
                // Struttura trovata, restituiscila
                echo json_encode($structure);
            }
        } catch (\Throwable $e) {
            http_response_code(500);
            error_log("Error fetching structure {$id}: " . $e->getMessage());
            echo json_encode(['error' => 'Failed to fetch structure']);
        }
    }

    /**
     * Crea una nuova struttura.
     * POST /api/structures
     */
    public function store(): void
    {
        // Prova a leggere da php://input (per application/json)
        $inputJson = file_get_contents('php://input');
        $input = $inputJson ? (array) json_decode($inputJson, true) : [];

        // Se php://input è vuoto o non è JSON valido, prova a leggere da $_POST (per form-data)
        if (empty($input) && !empty($_POST)) {
            $input = $_POST;
        }

        // Validazione semplice (solo il nome è obbligatorio per ora)
        if (empty($input['name'])) {
            http_response_code(400); // Bad Request
            echo json_encode(['error' => 'Missing required field: name']);
            return;
        }

        // Prepara i dati per l'inserimento (includi solo i campi validi per la tabella)
        $dataToInsert = [
            'name' => $input['name'],
            'address' => $input['address'] ?? null,
            'city' => $input['city'] ?? null,
            'province' => $input['province'] ?? null,
            'zip_code' => $input['zip_code'] ?? null,
            'phone' => $input['phone'] ?? null,
            'email' => $input['email'] ?? null,
            'notes' => $input['notes'] ?? null,
            // created_at e updated_at sono gestiti dal DB
        ];

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

            if ($result === false || $result === 0) {
                 // Doctrine DBAL < 3.3 restituisce false, >= 3.3 restituisce 0 in caso di fallimento senza eccezione
                 throw new \Exception("Failed to insert structure, insert returned non-true value.");
            }

            $newId = $this->db->lastInsertId();
            http_response_code(201); // Created
            // Recupera e restituisci la risorsa appena creata
            $newStructure = $this->db->fetchAssociative('SELECT * FROM structures WHERE id = ?', [$newId]);
            echo json_encode($newStructure);

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

    /**
     * Aggiorna una struttura esistente.
     * PUT /api/structures/{id}
     * @param array $vars Variabili dalla route (es. ['id' => '1'])
     */
    public function update(array $vars): void
    {
        $id = $vars['id'] ?? null;
        if ($id === null) {
             http_response_code(400);
             echo json_encode(['error' => 'Missing structure ID']);
             return;
        }

        // Leggi i dati (prova JSON e poi POST/form-urlencoded)
        $inputJson = file_get_contents('php://input');
        $input = $inputJson ? (array) json_decode($inputJson, true) : [];
        // Per PUT con form-urlencoded, php://input contiene la stringa query
        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;
        }

        // Prepara i dati per l'aggiornamento (solo i campi validi e presenti nell'input)
        $dataToUpdate = [];
        $allowedFields = ['name', 'address', 'city', 'province', 'zip_code', 'phone', 'email', 'notes'];
        foreach ($allowedFields as $field) {
            if (array_key_exists($field, $input)) {
                // Potresti aggiungere qui ulteriore validazione per tipo/formato
                $dataToUpdate[$field] = $input[$field];
            }
        }

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

        try {
            // Verifica prima se la risorsa esiste
            $existing = $this->db->fetchOne('SELECT 1 FROM structures WHERE id = ?', [$id]);
            if ($existing === false) {
                 http_response_code(404);
                 echo json_encode(['error' => "Structure with ID {$id} not found"]);
                 return;
            }

            // Esegui l'aggiornamento
            $this->db->update('structures', $dataToUpdate, ['id' => $id]);

            // Recupera e restituisci la risorsa aggiornata
            $updatedStructure = $this->db->fetchAssociative('SELECT * FROM structures WHERE id = ?', [$id]);
            echo json_encode($updatedStructure);

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

    /**
     * Elimina una struttura.
     * DELETE /api/structures/{id}
     * @param array $vars Variabili dalla route (es. ['id' => '1'])
     */
    public function delete(array $vars): void
    {
        $id = $vars['id'] ?? null;
        if ($id === null) {
             http_response_code(400);
             echo json_encode(['error' => 'Missing structure ID']);
             return;
        }

        try {
            // Verifica prima se la risorsa esiste
            $existing = $this->db->fetchOne('SELECT 1 FROM structures WHERE id = ?', [$id]);
            if ($existing === false) {
                 http_response_code(404);
                 echo json_encode(['error' => "Structure with ID {$id} not found"]);
                 return;
            }

            // Esegui l'eliminazione
            $deletedRows = $this->db->delete('structures', ['id' => $id]);

            if ($deletedRows > 0) {
                http_response_code(204); // No Content - Successo
                // Non c'è corpo della risposta per 204
            } else {
                 // Questo non dovrebbe accadere se la verifica precedente ha funzionato
                 http_response_code(500);
                 error_log("Failed to delete structure {$id}, delete returned 0 rows affected.");
                 echo json_encode(['error' => 'Failed to delete structure']);
            }

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