<?php
namespace Modules\Locadora\Controllers;

use Gestoreasy\Core\Http\Request;
use Gestoreasy\Core\Http\Response;
use Gestoreasy\Core\Tenant\ConnectionManager;
use Gestoreasy\Core\Audit\AuditLogger;
use Gestoreasy\Core\View\View;
use PDO;
use Exception;

class FrotaController {
    private PDO $pdo;
    
    public function __construct() {
        $this->pdo = ConnectionManager::forTenant();
    }
    
    // ==== Views ====
    public function viewIndex(Request $r): Response {
        return View::renderWithLayout('locadora/frota/index', ['title' => 'Frota de Veículos']);
    }
    
    public function viewCreate(Request $r): Response {
        return View::renderWithLayout('locadora/frota/create', ['title' => 'Novo Veículo']);
    }
    
    // ==== API ====
    public function list(Request $r): Response {
        try {
            $page = max(1, (int)($r->query['page'] ?? 1));
            $perPage = min(100, max(1, (int)($r->query['per_page'] ?? 20)));
            $offset = ($page - 1) * $perPage;
            
            $where = [];
            $params = [];
            
            if (!empty($r->query['status'])) {
                $where[] = 'status = ?';
                $params[] = $r->query['status'];
            }
            
            if (!empty($r->query['categoria'])) {
                $where[] = 'categoria = ?';
                $params[] = $r->query['categoria'];
            }
            
            if (!empty($r->query['busca'])) {
                $where[] = '(placa LIKE ? OR marca LIKE ? OR modelo LIKE ?)';
                $like = '%' . $r->query['busca'] . '%';
                $params[] = $like;
                $params[] = $like;
                $params[] = $like;
            }
            
            $whereSql = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';
            
            $countStmt = $this->pdo->prepare("SELECT COUNT(*) FROM locadora_frota $whereSql");
            $countStmt->execute($params);
            $total = (int)$countStmt->fetchColumn();
            
            $stmt = $this->pdo->prepare("
                SELECT * FROM locadora_frota 
                $whereSql 
                ORDER BY marca, modelo, placa 
                LIMIT $perPage OFFSET $offset
            ");
            $stmt->execute($params);
            $veiculos = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            return Response::json([
                'data' => $veiculos,
                'pagination' => [
                    'page' => $page,
                    'per_page' => $perPage,
                    'total' => $total,
                    'pages' => (int)ceil($total / $perPage)
                ]
            ]);
        } catch (Exception $e) {
            return Response::json(['error' => $e->getMessage()], 500);
        }
    }
    
    public function getById(Request $r): Response {
        try {
            $id = (int)($r->params['id'] ?? 0);
            if ($id <= 0) {
                return Response::json(['error' => 'ID inválido'], 400);
            }
            
            $stmt = $this->pdo->prepare("SELECT * FROM locadora_frota WHERE id = ?");
            $stmt->execute([$id]);
            $veiculo = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$veiculo) {
                return Response::json(['error' => 'Veículo não encontrado'], 404);
            }
            
            return Response::json(['data' => $veiculo]);
        } catch (Exception $e) {
            return Response::json(['error' => $e->getMessage()], 500);
        }
    }
    
    public function create(Request $r): Response {
        try {
            $data = $r->body;
            
            $stmt = $this->pdo->prepare("
                INSERT INTO locadora_frota (
                    placa, marca, modelo, ano_fabricacao, ano_modelo, cor, chassi, renavam,
                    km_atual, km_ultima_manutencao, km_proxima_manutencao, status,
                    categoria, combustivel, valor_diaria, valor_seguro, ncm, cest, observacoes
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ");
            
            $stmt->execute([
                strtoupper($data['placa'] ?? ''),
                $data['marca'] ?? '',
                $data['modelo'] ?? '',
                !empty($data['ano_fabricacao']) ? (int)$data['ano_fabricacao'] : null,
                !empty($data['ano_modelo']) ? (int)$data['ano_modelo'] : null,
                $data['cor'] ?? null,
                $data['chassi'] ?? null,
                $data['renavam'] ?? null,
                (float)($data['km_atual'] ?? 0),
                !empty($data['km_ultima_manutencao']) ? (float)$data['km_ultima_manutencao'] : null,
                !empty($data['km_proxima_manutencao']) ? (float)$data['km_proxima_manutencao'] : null,
                $data['status'] ?? 'disponivel',
                $data['categoria'] ?? null,
                $data['combustivel'] ?? null,
                (float)($data['valor_diaria'] ?? 0),
                (float)($data['valor_seguro'] ?? 0),
                $data['ncm'] ?? null,
                $data['cest'] ?? null,
                $data['observacoes'] ?? null
            ]);
            
            $id = (int)$this->pdo->lastInsertId();
            AuditLogger::logCreate('locadora_frota', $id, $data);
            
            // Registrar KM inicial
            try {
                $kmStmt = $this->pdo->prepare("
                    INSERT INTO locadora_km_historico (veiculo_id, km_anterior, km_atual, km_percorrido, tipo, data_registro)
                    VALUES (?, 0, ?, ?, 'manual', NOW())
                ");
                $kmAtual = (float)($data['km_atual'] ?? 0);
                $kmStmt->execute([$id, $kmAtual, $kmAtual]);
            } catch (Exception $e) {
                // Se falhar ao registrar KM histórico, apenas logar (não é crítico)
                error_log("Erro ao registrar KM inicial: " . $e->getMessage());
            }
            
            return Response::json(['data' => ['id' => $id]], 201);
        } catch (Exception $e) {
            return Response::json(['error' => $e->getMessage()], 500);
        }
    }
    
    public function update(Request $r): Response {
        try {
            $id = (int)($r->params['id'] ?? 0);
            if ($id <= 0) {
                return Response::json(['error' => 'ID inválido'], 400);
            }
            
            $data = $r->body;
            
            $updateFields = [];
            $params = [];
            
            $fields = [
                'placa', 'marca', 'modelo', 'ano_fabricacao', 'ano_modelo', 'cor', 'chassi', 'renavam',
                'km_atual', 'km_ultima_manutencao', 'km_proxima_manutencao', 'status',
                'categoria', 'combustivel', 'valor_diaria', 'valor_seguro', 'ncm', 'cest', 'observacoes'
            ];
            
            foreach ($fields as $field) {
                if (isset($data[$field])) {
                    $updateFields[] = "$field = ?";
                    if (in_array($field, ['ano_fabricacao', 'ano_modelo']) && !empty($data[$field])) {
                        $params[] = (int)$data[$field];
                    } elseif (in_array($field, ['km_atual', 'km_ultima_manutencao', 'km_proxima_manutencao', 'valor_diaria', 'valor_seguro']) && isset($data[$field])) {
                        $params[] = (float)$data[$field];
                    } elseif ($field === 'placa') {
                        $params[] = strtoupper($data[$field]);
                    } else {
                        $params[] = $data[$field];
                    }
                }
            }
            
            if (empty($updateFields)) {
                return Response::json(['error' => 'Nenhum campo para atualizar'], 400);
            }
            
            $updateFields[] = 'updated_at = CURRENT_TIMESTAMP';
            $params[] = $id;
            
            $sql = "UPDATE locadora_frota SET " . implode(', ', $updateFields) . " WHERE id = ?";
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute($params);
            
            AuditLogger::logUpdate('locadora_frota', $id, [], $data);
            
            return Response::json(['data' => ['id' => $id, 'updated' => true]]);
        } catch (Exception $e) {
            return Response::json(['error' => $e->getMessage()], 500);
        }
    }
    
    public function delete(Request $r): Response {
        try {
            $id = (int)($r->params['id'] ?? 0);
            if ($id <= 0) {
                return Response::json(['error' => 'ID inválido'], 400);
            }
            
            // Verificar se há contratos ativos
            $contratoStmt = $this->pdo->prepare("SELECT COUNT(*) FROM locadora_contratos WHERE veiculo_id = ? AND status IN ('aberto', 'em_andamento')");
            $contratoStmt->execute([$id]);
            $temContratos = (int)$contratoStmt->fetchColumn() > 0;
            
            if ($temContratos) {
                return Response::json(['error' => 'Não é possível excluir veículo com contratos ativos'], 400);
            }
            
            $stmt = $this->pdo->prepare("DELETE FROM locadora_frota WHERE id = ?");
            $stmt->execute([$id]);
            
            if ($stmt->rowCount() === 0) {
                return Response::json(['error' => 'Veículo não encontrado'], 404);
            }
            
            AuditLogger::logDelete('locadora_frota', $id);
            
            return Response::json(['data' => ['id' => $id, 'deleted' => true]]);
        } catch (Exception $e) {
            return Response::json(['error' => $e->getMessage()], 500);
        }
    }
    
    public function atualizarKm(Request $r): Response {
        try {
            $id = (int)($r->params['id'] ?? 0);
            if ($id <= 0) {
                return Response::json(['error' => 'ID inválido'], 400);
            }
            
            $data = $r->body;
            $kmNovo = (float)($data['km'] ?? 0);
            $tipo = $data['tipo'] ?? 'manual';
            
            if ($kmNovo <= 0) {
                return Response::json(['error' => 'KM inválido'], 400);
            }
            
            // Buscar KM atual
            $veiculoStmt = $this->pdo->prepare("SELECT km_atual FROM locadora_frota WHERE id = ?");
            $veiculoStmt->execute([$id]);
            $veiculo = $veiculoStmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$veiculo) {
                return Response::json(['error' => 'Veículo não encontrado'], 404);
            }
            
            $kmAnterior = (float)$veiculo['km_atual'];
            $kmPercorrido = $kmNovo - $kmAnterior;
            
            if ($kmPercorrido < 0) {
                return Response::json(['error' => 'KM novo deve ser maior que o atual'], 400);
            }
            
            $this->pdo->beginTransaction();
            
            // Atualizar KM do veículo
            $updateStmt = $this->pdo->prepare("UPDATE locadora_frota SET km_atual = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?");
            $updateStmt->execute([$kmNovo, $id]);
            
            // Registrar no histórico
            $histStmt = $this->pdo->prepare("
                INSERT INTO locadora_km_historico (veiculo_id, contrato_id, km_anterior, km_atual, km_percorrido, tipo, observacoes)
                VALUES (?, ?, ?, ?, ?, ?, ?)
            ");
            $histStmt->execute([
                $id,
                !empty($data['contrato_id']) ? (int)$data['contrato_id'] : null,
                $kmAnterior,
                $kmNovo,
                $kmPercorrido,
                $tipo,
                $data['observacoes'] ?? null
            ]);
            
            $this->pdo->commit();
            
            return Response::json(['data' => ['id' => $id, 'km_anterior' => $kmAnterior, 'km_atual' => $kmNovo, 'km_percorrido' => $kmPercorrido]]);
        } catch (Exception $e) {
            $this->pdo->rollBack();
            return Response::json(['error' => $e->getMessage()], 500);
        }
    }
    
    public function getHistoricoManutencao(Request $r): Response {
        try {
            $id = (int)($r->params['id'] ?? 0);
            if ($id <= 0) {
                return Response::json(['error' => 'ID inválido'], 400);
            }
            
            $stmt = $this->pdo->prepare("
                SELECT * FROM locadora_manutencao 
                WHERE veiculo_id = ? 
                ORDER BY data_manutencao DESC, km_manutencao DESC
            ");
            $stmt->execute([$id]);
            $historico = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            return Response::json(['data' => $historico]);
        } catch (Exception $e) {
            return Response::json(['error' => $e->getMessage()], 500);
        }
    }
    
    public function adicionarManutencao(Request $r): Response {
        try {
            $id = (int)($r->params['id'] ?? 0);
            if ($id <= 0) {
                return Response::json(['error' => 'ID inválido'], 400);
            }
            
            $data = $r->body;
            
            $this->pdo->beginTransaction();
            
            // Inserir manutenção
            $stmt = $this->pdo->prepare("
                INSERT INTO locadora_manutencao (
                    veiculo_id, tipo, descricao, km_manutencao, data_manutencao,
                    valor, fornecedor, ncm, cest, proxima_km, proxima_data, observacoes
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ");
            
            $stmt->execute([
                $id,
                $data['tipo'] ?? 'preventiva',
                $data['descricao'] ?? '',
                (float)($data['km_manutencao'] ?? 0),
                $data['data_manutencao'] ?? date('Y-m-d'),
                (float)($data['valor'] ?? 0),
                $data['fornecedor'] ?? null,
                $data['ncm'] ?? null,
                $data['cest'] ?? null,
                !empty($data['proxima_km']) ? (float)$data['proxima_km'] : null,
                $data['proxima_data'] ?? null,
                $data['observacoes'] ?? null
            ]);
            
            $manutencaoId = (int)$this->pdo->lastInsertId();
            
            // Atualizar veículo
            $updateStmt = $this->pdo->prepare("
                UPDATE locadora_frota SET
                    km_ultima_manutencao = ?,
                    km_proxima_manutencao = ?,
                    updated_at = CURRENT_TIMESTAMP
                WHERE id = ?
            ");
            $updateStmt->execute([
                (float)($data['km_manutencao'] ?? 0),
                !empty($data['proxima_km']) ? (float)$data['proxima_km'] : null,
                $id
            ]);
            
            $this->pdo->commit();
            
            return Response::json(['data' => ['id' => $manutencaoId]], 201);
        } catch (Exception $e) {
            $this->pdo->rollBack();
            return Response::json(['error' => $e->getMessage()], 500);
        }
    }
}

