<?php
/**
 * API: Recibir archivos del cliente (público — sin auth de panel)
 * 
 * El cliente sube archivos desde la página upload.php usando un token.
 * Los archivos se validan, guardan en disco e insertan en la BD.
 * Además se crea un mensaje en la conversación y una notificación para el operador.
 * 
 * POST /api/file_request_upload.php
 * Body: multipart/form-data { token: string, file: File }
 * 
 * Respuesta: { success: bool, file_id: int }
 */

error_reporting(E_ERROR | E_PARSE);
ini_set('display_errors', 0);

// Permitir uploads grandes
ini_set('upload_max_filesize', '55M');
ini_set('post_max_size', '60M');
ini_set('max_execution_time', 120);

require_once __DIR__ . '/../config/config.php';

header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['success' => false, 'error' => 'Método no permitido']);
    exit;
}

try {
    $token = $_POST['token'] ?? '';

    // Validar token
    if (empty($token) || !preg_match('/^[a-zA-Z0-9]{32,64}$/', $token)) {
        http_response_code(400);
        echo json_encode(['success' => false, 'error' => 'Token no válido']);
        exit;
    }

    // Validar archivo
    if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
        $errorMsg = 'No se recibió el archivo';
        if (isset($_FILES['file'])) {
            $uploadErrors = [
                UPLOAD_ERR_INI_SIZE => 'El archivo excede el tamaño máximo del servidor',
                UPLOAD_ERR_FORM_SIZE => 'El archivo excede el tamaño máximo del formulario',
                UPLOAD_ERR_PARTIAL => 'El archivo se subió parcialmente',
                UPLOAD_ERR_NO_FILE => 'No se envió ningún archivo',
                UPLOAD_ERR_NO_TMP_DIR => 'Falta la carpeta temporal del servidor',
                UPLOAD_ERR_CANT_WRITE => 'No se pudo escribir el archivo en disco',
            ];
            $errorMsg = $uploadErrors[$_FILES['file']['error']] ?? 'Error de subida desconocido';
        }
        http_response_code(400);
        echo json_encode(['success' => false, 'error' => $errorMsg]);
        exit;
    }

    $db = Database::getInstance();

    // Buscar solicitud por token
    $request = $db->fetch(
        "SELECT fr.*, u.name as user_name, u.phone_number as user_phone 
         FROM file_requests fr 
         LEFT JOIN users u ON fr.user_id = u.id 
         WHERE fr.token = ?",
        [$token]
    );

    if (!$request) {
        http_response_code(404);
        echo json_encode(['success' => false, 'error' => 'Solicitud no encontrada']);
        exit;
    }

    // Verificar expiración
    if (strtotime($request['expires_at']) < time()) {
        http_response_code(410);
        echo json_encode(['success' => false, 'error' => 'El enlace ha expirado']);
        exit;
    }

    // Verificar estado
    if ($request['status'] === 'cancelled') {
        http_response_code(410);
        echo json_encode(['success' => false, 'error' => 'La solicitud fue cancelada']);
        exit;
    }

    $file = $_FILES['file'];
    $maxSize = intval($request['max_file_size']);

    // Validar tamaño
    if ($file['size'] > $maxSize) {
        $maxMB = round($maxSize / (1024 * 1024));
        http_response_code(413);
        echo json_encode(['success' => false, 'error' => "El archivo excede el límite de {$maxMB} MB"]);
        exit;
    }

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

    if (!$mimeType) {
        $mimeType = $file['type'] ?: 'application/octet-stream';
    }

    // Clasificar tipo de media
    $mediaType = 'other';
    if (strpos($mimeType, 'image/') === 0) $mediaType = 'image';
    elseif (strpos($mimeType, 'video/') === 0) $mediaType = 'video';
    elseif (strpos($mimeType, 'audio/') === 0) $mediaType = 'audio';
    elseif (strpos($mimeType, 'application/') === 0 || strpos($mimeType, 'text/') === 0) $mediaType = 'document';

    // Validar tipo permitido
    $allowedTypes = explode(',', $request['allowed_types']);
    $typeAllowed = in_array($mediaType, $allowedTypes) || in_array('other', $allowedTypes);
    if (!$typeAllowed && $mediaType === 'other') {
        // Dar paso a "other" si document está permitido
        $typeAllowed = in_array('document', $allowedTypes);
    }
    if (!$typeAllowed) {
        http_response_code(400);
        echo json_encode(['success' => false, 'error' => 'Tipo de archivo no permitido']);
        exit;
    }

    // Crear directorio de destino
    $uploadDir = __DIR__ . '/../uploads/file_requests/' . date('Y') . '/' . date('m');
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0755, true);
    }

    // Generar nombre único
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION) ?: 'bin';
    $ext = strtolower(preg_replace('/[^a-zA-Z0-9]/', '', $ext));
    $storedName = 'fr_' . $request['id'] . '_' . uniqid() . '.' . $ext;
    $destPath = $uploadDir . '/' . $storedName;
    $relativePath = 'uploads/file_requests/' . date('Y') . '/' . date('m') . '/' . $storedName;

    // Mover archivo
    if (!move_uploaded_file($file['tmp_name'], $destPath)) {
        http_response_code(500);
        echo json_encode(['success' => false, 'error' => 'No se pudo guardar el archivo en disco']);
        exit;
    }

    // Generar thumbnail para imágenes
    $thumbnailPath = null;
    if ($mediaType === 'image' && class_exists('GdImage') || function_exists('imagecreatefromjpeg')) {
        try {
            $thumbName = 'thumb_' . $storedName;
            $thumbDest = $uploadDir . '/' . $thumbName;
            if (createThumbnail($destPath, $thumbDest, 200, 200)) {
                $thumbnailPath = 'uploads/file_requests/' . date('Y') . '/' . date('m') . '/' . $thumbName;
            }
        } catch (Exception $e) {
            // Thumbnail falla silenciosamente
            error_log('Thumbnail error: ' . $e->getMessage());
        }
    }

    // Guardar en BD - tabla file_request_uploads
    $uploadId = $db->insert('file_request_uploads', [
        'request_id' => $request['id'],
        'original_filename' => $file['name'],
        'stored_filename' => $storedName,
        'file_path' => $relativePath,
        'file_size' => $file['size'],
        'mime_type' => $mimeType,
        'media_type' => $mediaType,
        'thumbnail_path' => $thumbnailPath,
    ]);

    // Actualizar estado de la solicitud a "uploaded"
    $db->update('file_requests', ['status' => 'uploaded'], 'id = ?', [$request['id']]);

    // Generar URL pública del archivo
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    $appUrl = $protocol . '://' . $_SERVER['HTTP_HOST'];
    $fileUrl = $appUrl . '/' . $relativePath;
    $thumbUrl = $thumbnailPath ? ($appUrl . '/' . $thumbnailPath) : null;

    // Insertar como mensaje en la conversación (para que el operador lo vea en el chat)
    $db->insert('conversations', [
        'user_id' => $request['user_id'],
        'direction' => 'incoming',
        'message_type' => $mediaType === 'other' ? 'document' : $mediaType,
        'content' => '📎 Archivo recibido via enlace: ' . $file['name'],
        'media_url' => $fileUrl,
        'local_file' => $relativePath,
        'local_thumb' => $thumbnailPath,
        'status' => 'received',
        'is_read' => 0,
        'filename' => $file['name'],
        'mime_type' => $mimeType,
        'created_at' => date('Y-m-d H:i:s'),
    ]);

    // Crear notificación para el operador
    $userName = $request['user_name'] ?: $request['phone_number'];
    $db->insert('notifications', [
        'user_id' => $request['user_id'],
        'type' => 'file_uploaded',
        'message' => "📎 {$userName} subió un archivo: {$file['name']}",
        'data' => json_encode([
            'request_id' => $request['id'],
            'upload_id' => $uploadId,
            'filename' => $file['name'],
            'file_url' => $fileUrl,
            'media_type' => $mediaType,
            'file_size' => $file['size'],
        ]),
        'is_read' => 0,
    ]);

    // Escribir evento SSE para actualización en tiempo real
    try {
        $eventsFile = __DIR__ . '/../uploads/events_global.json';
        $events = [];
        if (file_exists($eventsFile)) {
            $raw = file_get_contents($eventsFile);
            $events = json_decode($raw, true) ?: [];
        }
        $events[] = [
            'type' => 'file_uploaded',
            'user_id' => $request['user_id'],
            'data' => [
                'request_id' => $request['id'],
                'upload_id' => $uploadId,
                'filename' => $file['name'],
                'file_url' => $fileUrl,
                'thumb_url' => $thumbUrl,
                'media_type' => $mediaType,
                'file_size' => $file['size'],
                'user_name' => $userName,
            ],
            'timestamp' => time(),
        ];
        file_put_contents($eventsFile, json_encode($events));
    } catch (Exception $e) {
        error_log('Error escribiendo evento SSE: ' . $e->getMessage());
    }

    echo json_encode([
        'success' => true,
        'file_id' => $uploadId,
        'filename' => $file['name'],
        'file_url' => $fileUrl,
        'media_type' => $mediaType,
        'file_size' => $file['size'],
    ]);

} catch (Exception $e) {
    $errorDetail = date('[Y-m-d H:i:s] ') . 'file_request_upload ERROR: ' . $e->getMessage() . "\n" . $e->getTraceAsString() . "\n\n";
    error_log('Error en file_request_upload: ' . $e->getMessage() . ' | Trace: ' . $e->getTraceAsString());
    @file_put_contents(__DIR__ . '/../logs/app_errors.log', $errorDetail, FILE_APPEND);
    http_response_code(500);
    echo json_encode(['success' => false, 'error' => 'Error interno del servidor']);
}


/**
 * Crear thumbnail de una imagen usando GD
 */
function createThumbnail($source, $dest, $maxW = 200, $maxH = 200) {
    $info = @getimagesize($source);
    if (!$info) return false;

    $mime = $info['mime'];
    $origW = $info[0];
    $origH = $info[1];

    switch ($mime) {
        case 'image/jpeg': $img = @imagecreatefromjpeg($source); break;
        case 'image/png': $img = @imagecreatefrompng($source); break;
        case 'image/gif': $img = @imagecreatefromgif($source); break;
        case 'image/webp': $img = @imagecreatefromwebp($source); break;
        default: return false;
    }

    if (!$img) return false;

    // Calcular dimensiones
    $ratio = min($maxW / $origW, $maxH / $origH);
    if ($ratio >= 1) {
        // La imagen ya es más pequeña que el thumb
        imagedestroy($img);
        return copy($source, $dest);
    }

    $newW = intval($origW * $ratio);
    $newH = intval($origH * $ratio);

    $thumb = imagecreatetruecolor($newW, $newH);

    // Preservar transparencia para PNG/GIF
    if ($mime === 'image/png' || $mime === 'image/gif') {
        imagealphablending($thumb, false);
        imagesavealpha($thumb, true);
        $transparent = imagecolorallocatealpha($thumb, 0, 0, 0, 127);
        imagefilledrectangle($thumb, 0, 0, $newW, $newH, $transparent);
    }

    imagecopyresampled($thumb, $img, 0, 0, 0, 0, $newW, $newH, $origW, $origH);

    // Guardar como JPEG (más ligero para thumbs)
    $result = imagejpeg($thumb, $dest, 85);

    imagedestroy($img);
    imagedestroy($thumb);

    return $result;
}
