<?php
/**
 * NEXUS IT - Mantenimiento Controller
 * Preventivos, Correctivos, Calendario cíclico
 */

class MantenimientoController {
    
    /**
     * GET /mantenimientos - Listar mantenimientos
     */
    public static function index(): void {
        $auth = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($auth);
        $db = getDB();
        
        $page    = max(1, intval($_GET['page'] ?? 1));
        $perPage = min(MAX_PAGE_SIZE, max(1, intval($_GET['per_page'] ?? DEFAULT_PAGE_SIZE)));
        $offset  = ($page - 1) * $perPage;
        
        $where = [];
        $params = [];
        
        if (!empty($_GET['tipo'])) {
            $where[] = 'm.tipo = ?';
            $params[] = $_GET['tipo'];
        }
        if (!empty($_GET['estado'])) {
            $where[] = 'm.estado = ?';
            $params[] = $_GET['estado'];
        }
        if (!empty($_GET['tecnico_id'])) {
            $where[] = 'm.tecnico_id = ?';
            $params[] = intval($_GET['tecnico_id']);
        }
        if (!empty($_GET['activo_id'])) {
            $where[] = 'm.activo_id = ?';
            $params[] = intval($_GET['activo_id']);
        }
        if (!empty($_GET['fecha_desde'])) {
            $where[] = 'm.fecha_programada >= ?';
            $params[] = $_GET['fecha_desde'];
        }
        if (!empty($_GET['fecha_hasta'])) {
            $where[] = 'm.fecha_programada <= ?';
            $params[] = $_GET['fecha_hasta'];
        }
        if (!empty($_GET['buscar'])) {
            $where[] = '(m.titulo LIKE ? OR a.codigo_activo LIKE ?)';
            $b = '%' . $_GET['buscar'] . '%';
            $params[] = $b;
            $params[] = $b;
        }
        
        $whereSQL = $where ? 'WHERE ' . implode(' AND ', $where) : '';
        
        $stmt = $db->prepare("SELECT COUNT(*) FROM mantenimientos m LEFT JOIN activos a ON m.activo_id = a.id $whereSQL");
        $stmt->execute($params);
        $total = (int)$stmt->fetchColumn();
        
        $sql = "
            SELECT m.*, 
                a.codigo_activo, a.marca AS activo_marca, a.modelo AS activo_modelo, a.tipo AS activo_tipo, a.hostname AS activo_hostname,
                u.nombre_completo AS tecnico_nombre
            FROM mantenimientos m
            LEFT JOIN activos a ON m.activo_id = a.id
            LEFT JOIN usuarios u ON m.tecnico_id = u.id
            $whereSQL
            ORDER BY m.fecha_programada ASC
            LIMIT $perPage OFFSET $offset
        ";
        
        $stmt = $db->prepare($sql);
        $stmt->execute($params);
        
        Response::paginated($stmt->fetchAll(), $total, $page, $perPage);
    }
    
    /**
     * POST /mantenimientos - Programar mantenimiento
     */
    public static function crear(): void {
        $auth = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($auth);
        
        $data = json_decode(file_get_contents('php://input'), true) ?? [];
        
        $v = new Validator($data);
        $v->required('activo_id', 'Activo')
          ->integer('activo_id')
          ->required('tipo', 'Tipo')
          ->inList('tipo', ['preventivo', 'correctivo'])
          ->required('titulo', 'Título')
          ->maxLength('titulo', 255)
          ->required('fecha_programada', 'Fecha programada')
          ->date('fecha_programada')
          ->inList('recurrencia', ['unica', 'semanal', 'mensual', 'trimestral', 'semestral', 'anual']);
        $v->validate();
        
        $db = getDB();
        
        // Verificar que el activo existe
        $stmt = $db->prepare("SELECT id, codigo_activo FROM activos WHERE id = ?");
        $stmt->execute([$data['activo_id']]);
        $activo = $stmt->fetch();
        if (!$activo) Response::notFound('Activo no encontrado');
        
        $stmt = $db->prepare("
            INSERT INTO mantenimientos (activo_id, tecnico_id, tipo, titulo, descripcion, estado, fecha_programada, costo, recurrencia)
            VALUES (?, ?, ?, ?, ?, 'programado', ?, ?, ?)
        ");
        $stmt->execute([
            $data['activo_id'],
            $data['tecnico_id'] ?? $auth['id'],
            $data['tipo'],
            trim($data['titulo']),
            $data['descripcion'] ?? null,
            $data['fecha_programada'],
            $data['costo'] ?? 0,
            $data['recurrencia'] ?? 'unica'
        ]);
        
        $mantId = $db->lastInsertId();
        
        // Agregar a timeline del activo
        $db->prepare("
            INSERT INTO activo_timeline (activo_id, usuario_id, tipo_evento, titulo, descripcion)
            VALUES (?, ?, 'mantenimiento', ?, ?)
        ")->execute([
            $data['activo_id'],
            $auth['id'],
            'Mantenimiento ' . $data['tipo'] . ' programado: ' . $data['titulo'],
            'Fecha: ' . $data['fecha_programada'] . ' | Recurrencia: ' . ($data['recurrencia'] ?? 'unica')
        ]);
        
        // Notificar al técnico si es otro
        if (!empty($data['tecnico_id']) && $data['tecnico_id'] != $auth['id']) {
            $db->prepare("
                INSERT INTO notificaciones (usuario_id, titulo, mensaje, tipo, referencia_tipo, referencia_id)
                VALUES (?, 'Mantenimiento asignado', ?, 'mantenimiento', 'mantenimiento', ?)
            ")->execute([
                $data['tecnico_id'],
                "Se te asignó: {$data['titulo']} para el equipo {$activo['codigo_activo']}",
                $mantId
            ]);
        }
        
        Response::created(self::obtener($db, $mantId), 'Mantenimiento programado exitosamente');
    }
    
    /**
     * GET /mantenimientos/{id}
     */
    public static function ver(int $id): void {
        $auth = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($auth);
        $db = getDB();
        
        $mant = self::obtener($db, $id);
        if (!$mant) Response::notFound('Mantenimiento no encontrado');
        
        Response::success($mant);
    }
    
    /**
     * PUT /mantenimientos/{id} - Actualizar estado, notas, etc.
     */
    public static function actualizar(int $id): void {
        $auth = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($auth);
        
        $data = json_decode(file_get_contents('php://input'), true) ?? [];
        $db = getDB();
        
        $mant = self::obtener($db, $id);
        if (!$mant) Response::notFound('Mantenimiento no encontrado');
        
        $campos = [];
        $valores = [];
        
        if (isset($data['estado'])) {
            $v = new Validator($data);
            $v->inList('estado', ['programado', 'en_curso', 'completado', 'cancelado']);
            $v->validate();
            
            $campos[] = 'estado = ?';
            $valores[] = $data['estado'];
            
            if ($data['estado'] === 'en_curso') {
                $campos[] = 'fecha_ejecucion = NOW()';
            }
            if ($data['estado'] === 'completado') {
                $campos[] = 'fecha_completado = NOW()';
                
                // Agregar a timeline
                $db->prepare("
                    INSERT INTO activo_timeline (activo_id, usuario_id, tipo_evento, titulo, costo)
                    VALUES (?, ?, 'mantenimiento', ?, ?)
                ")->execute([
                    $mant['activo_id'], $auth['id'],
                    'Mantenimiento completado: ' . $mant['titulo'],
                    $data['costo'] ?? $mant['costo']
                ]);
                
                // Si es recurrente, crear el siguiente
                if ($mant['recurrencia'] !== 'unica') {
                    self::crearSiguienteRecurrente($db, $mant, $auth['id']);
                }
            }
        }
        
        if (isset($data['tecnico_id'])) {
            $campos[] = 'tecnico_id = ?';
            $valores[] = $data['tecnico_id'] ?: null;
        }
        if (isset($data['titulo'])) {
            $campos[] = 'titulo = ?';
            $valores[] = trim($data['titulo']);
        }
        if (isset($data['descripcion'])) {
            $campos[] = 'descripcion = ?';
            $valores[] = trim($data['descripcion']);
        }
        if (isset($data['notas_tecnico'])) {
            $campos[] = 'notas_tecnico = ?';
            $valores[] = trim($data['notas_tecnico']);
        }
        if (isset($data['costo'])) {
            $campos[] = 'costo = ?';
            $valores[] = floatval($data['costo']);
        }
        if (isset($data['fecha_programada'])) {
            $campos[] = 'fecha_programada = ?';
            $valores[] = $data['fecha_programada'];
        }
        
        if (empty($campos)) Response::error('Sin campos para actualizar');
        
        $valores[] = $id;
        $db->prepare("UPDATE mantenimientos SET " . implode(', ', $campos) . " WHERE id = ?")->execute($valores);
        
        Response::success(self::obtener($db, $id), 'Mantenimiento actualizado');
    }
    
    /**
     * GET /mantenimientos/calendario - Vista de calendario
     */
    public static function calendario(): void {
        $auth = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($auth);
        $db = getDB();
        
        $mes = $_GET['mes'] ?? date('Y-m');
        $inicio = $mes . '-01';
        $fin = date('Y-m-t', strtotime($inicio));
        
        $stmt = $db->prepare("
            SELECT m.id, m.titulo, m.tipo, m.estado, m.fecha_programada, m.recurrencia,
                a.codigo_activo, a.marca AS activo_marca, a.modelo AS activo_modelo,
                u.nombre_completo AS tecnico_nombre
            FROM mantenimientos m
            LEFT JOIN activos a ON m.activo_id = a.id
            LEFT JOIN usuarios u ON m.tecnico_id = u.id
            WHERE m.fecha_programada BETWEEN ? AND ?
            ORDER BY m.fecha_programada ASC
        ");
        $stmt->execute([$inicio, $fin]);
        
        Response::success($stmt->fetchAll());
    }
    
    /**
     * GET /mantenimientos/proximos - Próximos 7 días
     */
    public static function proximos(): void {
        $auth = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($auth);
        $db = getDB();
        
        $stmt = $db->prepare("
            SELECT m.*, a.codigo_activo, a.marca AS activo_marca, a.modelo AS activo_modelo,
                u.nombre_completo AS tecnico_nombre
            FROM mantenimientos m
            LEFT JOIN activos a ON m.activo_id = a.id
            LEFT JOIN usuarios u ON m.tecnico_id = u.id
            WHERE m.estado IN ('programado') AND m.fecha_programada BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY)
            ORDER BY m.fecha_programada ASC
        ");
        $stmt->execute();
        
        Response::success($stmt->fetchAll());
    }
    
    // === HELPERS ===
    
    private static function obtener(PDO $db, int $id): ?array {
        $stmt = $db->prepare("
            SELECT m.*, a.codigo_activo, a.marca AS activo_marca, a.modelo AS activo_modelo, 
                a.tipo AS activo_tipo, a.hostname AS activo_hostname,
                u.nombre_completo AS tecnico_nombre
            FROM mantenimientos m
            LEFT JOIN activos a ON m.activo_id = a.id
            LEFT JOIN usuarios u ON m.tecnico_id = u.id
            WHERE m.id = ?
        ");
        $stmt->execute([$id]);
        return $stmt->fetch() ?: null;
    }
    
    private static function crearSiguienteRecurrente(PDO $db, array $mant, int $userId): void {
        $intervalos = [
            'semanal'    => '+1 week',
            'mensual'    => '+1 month',
            'trimestral' => '+3 months',
            'semestral'  => '+6 months',
            'anual'      => '+1 year'
        ];
        
        $intervalo = $intervalos[$mant['recurrencia']] ?? null;
        if (!$intervalo) return;
        
        $nuevaFecha = date('Y-m-d', strtotime($mant['fecha_programada'] . ' ' . $intervalo));
        
        $db->prepare("
            INSERT INTO mantenimientos (activo_id, tecnico_id, tipo, titulo, descripcion, estado, fecha_programada, costo, recurrencia)
            VALUES (?, ?, ?, ?, ?, 'programado', ?, ?, ?)
        ")->execute([
            $mant['activo_id'],
            $mant['tecnico_id'],
            $mant['tipo'],
            $mant['titulo'],
            $mant['descripcion'],
            $nuevaFecha,
            $mant['costo'],
            $mant['recurrencia']
        ]);
    }
}
