<?php

namespace App\Controllers;

use App\Services\Database;
use App\Middleware\AuthMiddleware;

/**
 * Controlador de Documentos de Proceso (AS-IS / TO-BE)
 * Gestiona documentación técnica y de procesos
 */
class DocumentsController extends BaseController
{
    protected $db;
    protected $authMiddleware;
    protected $uploadPath;

    public function __construct()
    {
        parent::__construct();
        $this->db = Database::getInstance();
        $this->authMiddleware = new AuthMiddleware();
        $this->uploadPath = __DIR__ . '/../../storage/documents/';
        
        // Crear directorio si no existe
        if (!is_dir($this->uploadPath)) {
            mkdir($this->uploadPath, 0755, true);
        }
    }

    /**
     * Subir nuevo documento
     */
    public function upload(): void
    {
        $this->authMiddleware->requireRole();

        try {
            error_log("DocumentsController::upload() - Inicio");
            error_log("POST data: " . json_encode($_POST));
            error_log("FILES data: " . json_encode(array_keys($_FILES)));
            
            // Validar CSRF token
            $token = $_POST['csrf_token'] ?? '';
            if (!$this->validateCsrfToken($token)) {
                throw new \Exception('Token CSRF inválido');
            }

            // Validar datos
            $requirementId = $_POST['requirement_id'] ?? null;
            $projectId = $_POST['project_id'] ?? null;
            $documentType = $_POST['document_type'] ?? null;
            $title = $_POST['title'] ?? null;
            $description = $_POST['description'] ?? null;
            $version = $_POST['version'] ?? '1.0';

            error_log("Requirement ID: $requirementId, Project ID: $projectId, Type: $documentType, Title: $title");

            // Validar que tenga al menos requirement_id O project_id
            if ((!$requirementId && !$projectId) || !$documentType || !$title) {
                throw new \Exception('Faltan campos requeridos (se necesita requirement_id o project_id, document_type y title)');
            }

            error_log("FILES document exists: " . (isset($_FILES['document']) ? 'yes' : 'no'));
            if (isset($_FILES['document'])) {
                error_log("File error code: " . $_FILES['document']['error']);
            }

            if (!isset($_FILES['document']) || $_FILES['document']['error'] !== UPLOAD_ERR_OK) {
                $errorMsg = 'Error al subir el archivo';
                if (isset($_FILES['document']['error'])) {
                    $errorMsg .= ' (código: ' . $_FILES['document']['error'] . ')';
                }
                throw new \Exception($errorMsg);
            }

            $file = $_FILES['document'];

            // Validar tipo de archivo
            $allowedTypes = [
                'application/pdf',
                'application/msword',
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                'application/vnd.ms-powerpoint',
                'application/vnd.openxmlformats-officedocument.presentationml.presentation',
                'image/png',
                'image/jpeg',
                'application/vnd.ms-visio',
                'application/vnd.visio'
            ];

            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            $mimeType = finfo_file($finfo, $file['tmp_name']);
            finfo_close($finfo);

            if (!in_array($mimeType, $allowedTypes)) {
                throw new \Exception('Tipo de archivo no permitido. Permitidos: PDF, Word, PowerPoint, Visio, PNG, JPG');
            }

            // Validar tamaño (máximo 10MB)
            if ($file['size'] > 10 * 1024 * 1024) {
                throw new \Exception('El archivo no debe superar 10MB');
            }

            // Generar nombre único
            $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
            $filename = uniqid('doc_') . '_' . time() . '.' . $extension;
            $filePath = $this->uploadPath . $filename;

            error_log("Attempting to save file to: $filePath");
            error_log("Upload path exists: " . (is_dir($this->uploadPath) ? 'yes' : 'no'));
            error_log("Upload path writable: " . (is_writable($this->uploadPath) ? 'yes' : 'no'));

            // Mover archivo
            if (!move_uploaded_file($file['tmp_name'], $filePath)) {
                throw new \Exception('Error al guardar el archivo en el servidor');
            }

            error_log("File saved successfully: $filePath");

            // Guardar en base de datos
            $sql = "INSERT INTO process_documents 
                    (requirement_id, project_id, document_type, version, title, description,
                     file_path, file_original_name, file_size, file_mime_type, uploaded_by)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

            $params = [
                $requirementId,
                $projectId,
                $documentType,
                $version,
                $title,
                $description,
                $filename,
                $file['name'],
                $file['size'],
                $mimeType,
                $_SESSION['user']['id']
            ];

            error_log("Inserting into database with params: " . json_encode($params));

            $documentId = $this->db->insert($sql, $params);

            error_log("Document inserted with ID: $documentId");

            // Registrar en historial del proyecto (opcional - puede no existir la tabla aún)
            if ($projectId) {
                try {
                    $this->db->query(
                        "INSERT INTO project_history (project_id, user_id, action, field_name, new_value)
                         VALUES (?, ?, ?, ?, ?)",
                        [$projectId, $_SESSION['user']['id'], 'subió documento', $documentType, $title]
                    );
                } catch (\Exception $e) {
                    error_log("Warning: Could not insert into project_history: " . $e->getMessage());
                    // No lanzar error, continuar con el flujo
                }
            }

            // Actualizar estado del requerimiento si es AS-IS
            $statusChanged = false;
            if ($documentType === 'as_is' && $requirementId) {
                $result = $this->db->query(
                    "UPDATE requirements SET status = 'in_analysis' WHERE id = ? AND status = 'classified'",
                    [$requirementId]
                );
                $statusChanged = ($result > 0);
                error_log("Status changed: " . ($statusChanged ? 'yes' : 'no'));
            }

            error_log("Returning success response");

            // Devolver JSON
            header('Content-Type: application/json');
            echo json_encode([
                'success' => true,
                'message' => 'Documento subido exitosamente',
                'document_id' => $documentId,
                'status_changed' => $statusChanged
            ]);
            exit;

        } catch (\Exception $e) {
            error_log("Error uploading document: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());
            header('Content-Type: application/json');
            http_response_code(400);
            echo json_encode([
                'success' => false,
                'message' => $e->getMessage()
            ]);
            exit;
        }
    }

    /**
     * Descargar documento
     */
    public function download($id): void
    {
        $this->authMiddleware->requireRole();

        try {
            $document = $this->db->fetchOne(
                "SELECT * FROM process_documents WHERE id = ?",
                [$id]
            );

            if (!$document) {
                http_response_code(404);
                echo "Documento no encontrado";
                return;
            }

            $filePath = $this->uploadPath . $document['file_path'];

            if (!file_exists($filePath)) {
                http_response_code(404);
                echo "Archivo no encontrado";
                return;
            }

            // Headers para descarga
            header('Content-Type: ' . $document['file_mime_type']);
            header('Content-Disposition: attachment; filename="' . $document['file_original_name'] . '"');
            header('Content-Length: ' . filesize($filePath));
            header('Cache-Control: must-revalidate');
            header('Pragma: public');

            readfile($filePath);
            exit;

        } catch (\Exception $e) {
            error_log("Error downloading document: " . $e->getMessage());
            http_response_code(500);
            echo "Error al descargar el documento";
        }
    }

    /**
     * Revisar documento (Gestión de Calidad)
     */
    public function review(): void
    {
        $this->authMiddleware->requireRole(['admin', 'quality']);

        try {
            // Validar CSRF token
            $token = $_POST['csrf_token'] ?? '';
            if (!$this->validateCsrfToken($token)) {
                throw new \Exception('Token CSRF inválido');
            }

            $documentId = $_POST['document_id'] ?? null;
            $status = $_POST['status'] ?? null;
            $notes = $_POST['review_notes'] ?? null;

            if (!$documentId || !$status) {
                throw new \Exception('Faltan campos requeridos');
            }

            if (!in_array($status, ['approved', 'rejected'])) {
                throw new \Exception('Estado no válido');
            }

            // Obtener documento
            $document = $this->db->fetchOne(
                "SELECT * FROM process_documents WHERE id = ?",
                [$documentId]
            );

            if (!$document) {
                throw new \Exception('Documento no encontrado');
            }

            // Actualizar estado
            $this->db->query(
                "UPDATE process_documents 
                 SET status = ?, reviewed_by = ?, review_date = NOW(), review_notes = ?
                 WHERE id = ?",
                [$status, $_SESSION['user']['id'], $notes, $documentId]
            );

            // Si es aprobado y es TO-BE, actualizar estado del requerimiento
            $statusChanged = false;
            if ($status === 'approved' && $document['document_type'] === 'to_be') {
                $result = $this->db->query(
                    "UPDATE requirements SET status = 'approved' WHERE id = ?",
                    [$document['requirement_id']]
                );
                $statusChanged = ($result > 0);
            }

            // Registrar en historial del proyecto (opcional)
            if ($document['project_id']) {
                try {
                    $this->db->query(
                        "INSERT INTO project_history (project_id, user_id, action, field_name, new_value)
                         VALUES (?, ?, ?, ?, ?)",
                        [
                            $document['project_id'],
                            $_SESSION['user']['id'],
                            $status === 'approved' ? 'aprobó documento' : 'rechazó documento',
                            $document['document_type'],
                            $document['title']
                        ]
                    );
                } catch (\Exception $e) {
                    error_log("Warning: Could not insert into project_history: " . $e->getMessage());
                }
            }

            // Devolver JSON
            header('Content-Type: application/json');
            echo json_encode([
                'success' => true,
                'message' => 'Documento ' . ($status === 'approved' ? 'aprobado' : 'rechazado'),
                'status_changed' => $statusChanged
            ]);
            exit;

        } catch (\Exception $e) {
            error_log("Error reviewing document: " . $e->getMessage());
            header('Content-Type: application/json');
            http_response_code(400);
            echo json_encode([
                'success' => false,
                'message' => $e->getMessage()
            ]);
            exit;
        }
    }

    /**
     * Eliminar documento
     */
    public function delete($id): void
    {
        $this->authMiddleware->requireRole(['admin']);

        try {
            // Validar CSRF token
            $token = $_POST['csrf_token'] ?? '';
            if (!$this->validateCsrfToken($token)) {
                throw new \Exception('Token CSRF inválido');
            }

            $document = $this->db->fetchOne(
                "SELECT * FROM process_documents WHERE id = ?",
                [$id]
            );

            if (!$document) {
                throw new \Exception('Documento no encontrado');
            }

            // Eliminar archivo físico
            $filePath = $this->uploadPath . $document['file_path'];
            if (file_exists($filePath)) {
                unlink($filePath);
            }

            // Eliminar de BD
            $this->db->query("DELETE FROM process_documents WHERE id = ?", [$id]);

            // Registrar en historial del proyecto (opcional)
            if ($document['project_id']) {
                try {
                    $this->db->query(
                        "INSERT INTO project_history (project_id, user_id, action, field_name, old_value)
                         VALUES (?, ?, ?, ?, ?)",
                        [
                            $document['project_id'],
                            $_SESSION['user']['id'],
                            'eliminó documento',
                            $document['document_type'],
                            $document['title']
                        ]
                    );
                } catch (\Exception $e) {
                    error_log("Warning: Could not insert into project_history: " . $e->getMessage());
                }
            }

            header('Content-Type: application/json');
            echo json_encode(['success' => true, 'message' => 'Documento eliminado']);
            exit;

        } catch (\Exception $e) {
            error_log("Error deleting document: " . $e->getMessage());
            header('Content-Type: application/json');
            http_response_code(400);
            echo json_encode(['success' => false, 'message' => $e->getMessage()]);
            exit;
        }
    }

    /**
     * Listar documentos de un requerimiento/proyecto
     */
    public function list(): void
    {
        $this->authMiddleware->requireRole();
        header('Content-Type: application/json');

        try {
            $requirementId = $_GET['requirement_id'] ?? null;
            $projectId = $_GET['project_id'] ?? null;

            if (!$requirementId && !$projectId) {
                throw new \Exception('Se requiere requirement_id o project_id');
            }

            $sql = "SELECT pd.*, 
                           CONCAT(u1.first_name, ' ', u1.last_name) as uploader_name,
                           CONCAT(u2.first_name, ' ', u2.last_name) as reviewer_name
                    FROM process_documents pd
                    LEFT JOIN users u1 ON pd.uploaded_by = u1.id
                    LEFT JOIN users u2 ON pd.reviewed_by = u2.id
                    WHERE ";

            $params = [];
            if ($requirementId) {
                $sql .= "pd.requirement_id = ?";
                $params[] = $requirementId;
            } else {
                $sql .= "pd.project_id = ?";
                $params[] = $projectId;
            }

            $sql .= " ORDER BY pd.created_at DESC";

            $documents = $this->db->fetchAll($sql, $params);

            echo json_encode(['success' => true, 'documents' => $documents]);

        } catch (\Exception $e) {
            error_log("Error listing documents: " . $e->getMessage());
            http_response_code(400);
            echo json_encode(['success' => false, 'message' => $e->getMessage()]);
        }
    }
}
