<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Helpers\UrlHelper;
use Exception;

/**
 * Controller de Tickets (Chamados)
 */
class TicketsController extends BaseController
{
    /**
     * Lista todos os tickets
     */
    public function index(): void
    {
        // Verificar permissão de visualização
        if (!$this->canView('tickets')) {
            $this->response->forbidden('Você não tem permissão para visualizar tickets.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();
            $status = $this->request->get('status', '');
            $prioridade = $this->request->get('prioridade', '');
            $categoria = $this->request->get('categoria', '');

            // Verificar se modulo_id existe na tabela
            $moduloIdExiste = false;
            $moduloJoin = '';
            $moduloSelect = '';
            try {
                $checkCol = $this->db->query("SHOW COLUMNS FROM tickets LIKE 'modulo_id'");
                if ($checkCol->fetch()) {
                    $moduloIdExiste = true;
                    $moduloJoin = 'LEFT JOIN modulos m ON t.modulo_id = m.id';
                    $moduloSelect = 'm.nome as modulo_nome,';
                }
            } catch (Exception $e) {
                // Coluna não existe
                $moduloIdExiste = false;
            }

            $query = "
                SELECT t.*,
                    p.name as cliente_nome,
                    e.razao_social as empresa_nome,
                    u1.name as atribuido_para_nome,
                    u2.name as criado_por_nome,
                    {$moduloSelect}
                    (SELECT COUNT(*) FROM ticket_comentarios WHERE ticket_id = t.id) as total_comentarios
                FROM tickets t
                LEFT JOIN pessoas p ON t.cliente_id = p.id
                LEFT JOIN empresas e ON t.empresa_id = e.id
                LEFT JOIN users u1 ON t.atribuido_para = u1.id
                LEFT JOIN users u2 ON t.criado_por = u2.id
                {$moduloJoin}
                WHERE t.company_id = :company_id
            ";

            $params = ['company_id' => $companyId];

            if ($status !== '') {
                $query .= " AND t.status = :status";
                $params['status'] = $status;
            }

            if ($prioridade !== '') {
                $query .= " AND t.prioridade = :prioridade";
                $params['prioridade'] = $prioridade;
            }

            if ($categoria !== '') {
                $query .= " AND t.categoria = :categoria";
                $params['categoria'] = $categoria;
            }

            $query .= " ORDER BY t.data_abertura DESC";

            $stmt = $this->db->prepare($query);
            $stmt->execute($params);
            $tickets = $stmt->fetchAll();

            // Agrupar tickets por status para layout Trello
            // Mapeamento de status do banco (enum) para colunas do Trello
            // Os valores do enum são exatamente: Aberto, Em Análise, Programação, Pendente, Retorno, Concluído
            $statusMap = [
                'Aberto' => 'Aberto',
                'Em Análise' => 'Em Análise',
                'Programação' => 'Programação',
                'Pendente' => 'Pendente',
                'Retorno' => 'Retorno',
                'Concluído' => 'Concluído'
            ];

            $ticketsPorStatus = [
                'Aberto' => [],
                'Em Análise' => [],
                'Programação' => [],
                'Pendente' => [],
                'Retorno' => [],
                'Concluído' => []
            ];

            foreach ($tickets as $ticket) {
                $statusTicket = $ticket['status'];
                // Mapear status do banco para coluna do Trello
                $coluna = $statusMap[$statusTicket] ?? 'Aberto';
                $ticketsPorStatus[$coluna][] = $ticket;
            }

            $this->view('tickets/index', [
                'tickets' => $tickets,
                'ticketsPorStatus' => $ticketsPorStatus,
                'filtros' => [
                    'status' => $status,
                    'prioridade' => $prioridade,
                    'categoria' => $categoria
                ],
                'pageTitle' => 'Tickets',
                'activeMenu' => 'tickets'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao listar tickets: " . $e->getMessage());
            $this->response->error('Erro ao carregar tickets');
        }
    }

    /**
     * Lista tickets do usuário logado para acompanhamento
     */
    public function acompanhar(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $user = $this->session->get('user');
            $userId = $user['id'] ?? null;

            if (!$userId) {
                $this->response->error('Usuário não identificado');
                return;
            }

            // Buscar tickets criados pelo usuário ou atribuídos a ele
            $stmt = $this->db->prepare("
                SELECT t.*,
                    p.name as cliente_nome,
                    e.razao_social as empresa_nome,
                    u1.name as atribuido_para_nome,
                    (SELECT COUNT(*) FROM ticket_comentarios WHERE ticket_id = t.id) as total_comentarios
                FROM tickets t
                LEFT JOIN pessoas p ON t.cliente_id = p.id
                LEFT JOIN empresas e ON t.empresa_id = e.id
                LEFT JOIN users u1 ON t.atribuido_para = u1.id
                WHERE t.company_id = :company_id
                AND (t.criado_por = :user_id1 OR t.atribuido_para = :user_id2)
                ORDER BY t.data_abertura DESC
            ");
            $stmt->bindValue(':company_id', $companyId, \PDO::PARAM_INT);
            $stmt->bindValue(':user_id1', $userId, \PDO::PARAM_INT);
            $stmt->bindValue(':user_id2', $userId, \PDO::PARAM_INT);
            $stmt->execute();
            $tickets = $stmt->fetchAll();

            // Agrupar por status
            $statusMap = [
                'Aberto' => 'Aberto',
                'Em Análise' => 'Em Análise',
                'Programação' => 'Programação',
                'Pendente' => 'Pendente',
                'Retorno' => 'Retorno',
                'Concluído' => 'Concluído'
            ];

            $ticketsPorStatus = [
                'Aberto' => [],
                'Em Análise' => [],
                'Programação' => [],
                'Pendente' => [],
                'Retorno' => [],
                'Concluído' => []
            ];

            foreach ($tickets as $ticket) {
                $statusTicket = $ticket['status'];
                $coluna = $statusMap[$statusTicket] ?? 'Aberto';
                $ticketsPorStatus[$coluna][] = $ticket;
            }

            $this->view('tickets/acompanhar', [
                'tickets' => $tickets,
                'ticketsPorStatus' => $ticketsPorStatus,
                'pageTitle' => 'Acompanhar Tickets',
                'activeMenu' => 'acompanhar-tickets'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao listar tickets para acompanhamento: " . $e->getMessage());
            $this->response->error('Erro ao carregar tickets');
        }
    }

    /**
     * Visualiza ticket para acompanhamento (versão simplificada para clientes)
     */
    public function acompanharShow(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $user = $this->session->get('user');
            $userId = $user['id'] ?? null;
            $id = (int) $this->request->get('id');

            if (!$id) {
                $this->response->error('ID do ticket não informado');
                return;
            }

            if (!$userId) {
                $this->response->error('Usuário não identificado');
                return;
            }

            // Buscar ticket - apenas se foi criado pelo usuário ou atribuído a ele
            $stmt = $this->db->prepare("
                SELECT t.*,
                    p.name as cliente_nome,
                    p.document as cliente_document,
                    p.phone as cliente_phone,
                    p.mobile as cliente_mobile,
                    p.email as cliente_email,
                    e.razao_social as empresa_nome,
                    e.cnpj as empresa_cnpj,
                    e.telefone as empresa_telefone,
                    e.email as empresa_email,
                    u1.name as atribuido_para_nome,
                    u2.name as criado_por_nome
                FROM tickets t
                LEFT JOIN pessoas p ON t.cliente_id = p.id
                LEFT JOIN empresas e ON t.empresa_id = e.id
                LEFT JOIN users u1 ON t.atribuido_para = u1.id
                LEFT JOIN users u2 ON t.criado_por = u2.id
                WHERE t.id = :id
                AND t.company_id = :company_id
                AND (t.criado_por = :user_id1 OR t.atribuido_para = :user_id2)
                LIMIT 1
            ");
            $stmt->bindValue(':id', $id, \PDO::PARAM_INT);
            $stmt->bindValue(':company_id', $companyId, \PDO::PARAM_INT);
            $stmt->bindValue(':user_id1', $userId, \PDO::PARAM_INT);
            $stmt->bindValue(':user_id2', $userId, \PDO::PARAM_INT);
            $stmt->execute();
            $ticket = $stmt->fetch();

            if (!$ticket) {
                $this->response->error('Ticket não encontrado ou você não tem permissão para visualizá-lo');
                return;
            }

            $comentarios = $this->getComentarios((int) $id);
            $anexos = $this->getAnexos((int) $id);

            $this->view('tickets/acompanhar-show', [
                'ticket' => $ticket,
                'comentarios' => $comentarios,
                'anexos' => $anexos,
                'pageTitle' => 'Visualizar Ticket',
                'activeMenu' => 'acompanhar-tickets'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao visualizar ticket para acompanhamento: " . $e->getMessage());
            $this->response->error('Erro ao visualizar ticket');
        }
    }

    /**
     * Exibe formulário simplificado para abrir ticket (público)
     */
    public function abrir(): void
    {
        $companyId = $this->getCompanyId();
        $modulos = $this->getModulosAtivos();
        $numeroTicket = $this->gerarProximoNumeroTicket($companyId);

        $this->view('tickets/abrir', [
            'modulos' => $modulos,
            'numeroTicket' => $numeroTicket,
            'pageTitle' => 'Abrir Ticket',
            'activeMenu' => 'abrir-ticket'
        ]);
    }

    /**
     * Salva ticket aberto pelo formulário simplificado
     */
    public function storeAbrir(): void
    {
        try {
            error_log("=== TICKETS STORE ABRIR CHAMADO ===");
            error_log("POST recebido: " . json_encode($_POST));
            error_log("Content-Type: " . ($_SERVER['HTTP_CONTENT_TYPE'] ?? 'N/A'));
            error_log("Request Method: " . ($_SERVER['REQUEST_METHOD'] ?? 'N/A'));

            $companyId = $this->getCompanyId();
            $user = $this->session->get('user');

            // Verificar se $_POST está vazio e tentar ler de php://input se necessário
            if (empty($_POST) && $this->request->method() === 'POST') {
                $contentType = $_SERVER['HTTP_CONTENT_TYPE'] ?? '';
                if (strpos($contentType, 'multipart/form-data') === false) {
                    $input = file_get_contents('php://input');
                    if (!empty($input)) {
                        parse_str($input, $parsed);
                        error_log("Dados parseados de php://input: " . json_encode($parsed));
                        $_POST = array_merge($_POST, $parsed);
                    }
                }
            }

            $moduloId = $this->request->post('modulo_id') ?: null;
            $tipo = $this->request->post('tipo', 'normal');
            $outrosTipo = $this->request->post('outros_tipo');

            error_log("Dados recebidos - Modulo ID: " . ($moduloId ?: 'VAZIO') . ", Tipo: " . ($tipo ?: 'VAZIO'));

            // Se tipo for "outros" e tiver texto, usar o texto como tipo
            if ($tipo === 'outros' && !empty($outrosTipo)) {
                $tipo = 'outros: ' . trim($outrosTipo);
            }

            $data = [
                'company_id' => $companyId,
                'numero_ticket' => $this->request->post('numero_ticket'),
                'titulo' => $this->request->post('titulo'),
                'descricao' => $this->request->post('descricao'),
                'modulo_id' => $moduloId,
                'categoria' => $tipo,
                'prioridade' => $this->request->post('prioridade', 'normal'),
                'status' => 'Aberto',
                'cliente_id' => $this->request->post('cliente_id') ?: null,
                'empresa_id' => $this->request->post('empresa_id') ?: null,
                'atribuido_para' => null,
                'criado_por' => $user['id'] ?? null
            ];

            error_log("Dados validados - Numero: " . ($data['numero_ticket'] ?: 'VAZIO') . ", Titulo: " . ($data['titulo'] ?: 'VAZIO') . ", Descricao: " . (strlen($data['descricao'] ?? '') . ' chars'));

            // Validar campos obrigatórios
            if (empty($data['numero_ticket']) || empty($data['titulo']) || empty($data['descricao'])) {
                error_log("ERRO: Campos obrigatórios vazios");
                $this->response->error('Número do ticket, título e descrição são obrigatórios');
                return;
            }

            // Verificar se número já existe
            $check = $this->db->prepare("SELECT id FROM tickets WHERE company_id = :company_id AND numero_ticket = :numero LIMIT 1");
            $check->execute(['company_id' => $companyId, 'numero' => $data['numero_ticket']]);
            if ($check->fetch()) {
                $this->response->error('Número de ticket já existe');
                return;
            }

            // Verificar se modulo_id existe na tabela
            $moduloIdField = '';
            $moduloIdValue = '';
            $moduloIdExiste = false;
            try {
                $checkCol = $this->db->query("SHOW COLUMNS FROM tickets LIKE 'modulo_id'");
                if ($checkCol->fetch()) {
                    $moduloIdField = ', modulo_id';
                    $moduloIdValue = ', :modulo_id';
                    $moduloIdExiste = true;
                }
            } catch (Exception $e) {
                $moduloIdExiste = false;
            }

            // Validar modulo_id APENAS se a coluna existe na tabela
            if ($moduloIdExiste) {
                if (empty($moduloId)) {
                    error_log("ERRO: Modulo ID vazio (coluna existe)");
                    $this->response->error('Por favor, selecione um módulo');
                    return;
                }
            } else {
                // Coluna não existe, remover modulo_id do array de dados
                unset($data['modulo_id']);
                error_log("modulo_id não existe na tabela, removendo do INSERT");
            }

            $sql = "INSERT INTO tickets (
                company_id, numero_ticket, titulo, descricao, categoria, prioridade, status{$moduloIdField},
                cliente_id, empresa_id, atribuido_para, criado_por
            ) VALUES (
                :company_id, :numero_ticket, :titulo, :descricao, :categoria, :prioridade, :status{$moduloIdValue},
                :cliente_id, :empresa_id, :atribuido_para, :criado_por
            )";

            error_log("SQL: " . $sql);
            error_log("Dados para INSERT: " . json_encode(array_merge($data, ['password' => '***HIDDEN***'])));

            try {
                $stmt = $this->db->prepare($sql);
                $stmt->execute($data);
                $ticketId = (int) $this->db->lastInsertId();
                error_log("Ticket criado com ID: " . $ticketId);
            } catch (\PDOException $e) {
                error_log("ERRO PDO ao criar ticket: " . $e->getMessage());
                error_log("Código do erro: " . $e->getCode());
                error_log("SQL State: " . $e->errorInfo[0] ?? 'N/A');
                error_log("SQL Error Info: " . json_encode($e->errorInfo ?? []));
                $this->response->error('Erro ao salvar ticket: ' . $e->getMessage());
                return;
            }

            // Processar upload de imagens
            if (isset($_FILES['imagens']) && !empty($_FILES['imagens']['name'][0])) {
                $this->processarUploadImagens($ticketId, $_FILES['imagens']);
            }

            // Adicionar comentário inicial se houver
            $comentarioInicial = $this->request->post('comentario_inicial');
            if (!empty($comentarioInicial)) {
                $usuarioId = isset($user['id']) ? (int) $user['id'] : null;
                $this->adicionarComentarioPrivado($ticketId, $comentarioInicial, $usuarioId);
            }

            $this->response->success('Ticket criado com sucesso!', [
                'redirect' => UrlHelper::url('/tickets')
            ]);

        } catch (Exception $e) {
            error_log("Erro ao criar ticket: " . $e->getMessage());
            $this->response->error('Erro ao criar ticket: ' . $e->getMessage());
        }
    }

    /**
     * Exibe formulário de criação
     */
    public function create(): void
    {
        $companyId = $this->getCompanyId();
        $empresas = $this->getEmpresas($companyId);
        $pessoas = $this->getPessoas($companyId);
        $usuarios = $this->getUsuarios($companyId);
        $modulos = $this->getModulosAtivos();
        $numeroTicket = $this->gerarProximoNumeroTicket($companyId);

        $this->view('tickets/create', [
            'empresas' => $empresas,
            'pessoas' => $pessoas,
            'usuarios' => $usuarios,
            'modulos' => $modulos,
            'numeroTicket' => $numeroTicket,
            'pageTitle' => 'Novo Ticket'
        ]);
    }

    /**
     * Salva novo ticket
     */
    public function store(): void
    {
        // Verificar permissão de criação
        if (!$this->canCreate('tickets')) {
            $this->response->forbidden('Você não tem permissão para criar tickets.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();
            $user = $this->session->get('user');

            $moduloId = $this->request->post('modulo_id') ?: null;
            $tipo = $this->request->post('tipo', 'normal');
            $outrosTipo = $this->request->post('outros_tipo');

            // Se tipo for "outros" e tiver texto, usar o texto como tipo
            if ($tipo === 'outros' && !empty($outrosTipo)) {
                $tipo = 'outros: ' . trim($outrosTipo);
            }

            $data = [
                'company_id' => $companyId,
                'numero_ticket' => $this->request->post('numero_ticket'),
                'titulo' => $this->request->post('titulo'),
                'descricao' => $this->request->post('descricao'),
                'modulo_id' => $moduloId,
                'categoria' => $tipo, // Usando categoria para armazenar tipo (compatibilidade)
                'prioridade' => $this->request->post('prioridade', 'normal'),
                'status' => $this->request->post('status', 'aberto'),
                'cliente_id' => $this->request->post('cliente_id') ?: null,
                'empresa_id' => $this->request->post('empresa_id') ?: null,
                'atribuido_para' => $this->request->post('atribuido_para') ?: null,
                'criado_por' => $user['id'] ?? null
            ];

            // Validar campos obrigatórios
            if (empty($data['numero_ticket']) || empty($data['titulo']) || empty($data['descricao'])) {
                $this->response->error('Número do ticket, título e descrição são obrigatórios');
                return;
            }

            // Verificar se número já existe
            $check = $this->db->prepare("SELECT id FROM tickets WHERE company_id = :company_id AND numero_ticket = :numero LIMIT 1");
            $check->execute(['company_id' => $companyId, 'numero' => $data['numero_ticket']]);
            if ($check->fetch()) {
                $this->response->error('Número de ticket já existe');
                return;
            }

            // Inserir
            // Verificar se modulo_id existe na tabela
            $moduloIdField = '';
            $moduloIdValue = '';
            $moduloIdExiste = false;
            try {
                $checkCol = $this->db->query("SHOW COLUMNS FROM tickets LIKE 'modulo_id'");
                if ($checkCol->fetch()) {
                    $moduloIdField = ', modulo_id';
                    $moduloIdValue = ', :modulo_id';
                    $moduloIdExiste = true;
                }
            } catch (Exception $e) {
                // Coluna não existe, não adicionar
                $moduloIdExiste = false;
            }

            // Se a coluna não existe, remover modulo_id do array
            if (!$moduloIdExiste) {
                unset($data['modulo_id']);
            }

            $sql = "INSERT INTO tickets (
                company_id, numero_ticket, titulo, descricao, categoria, prioridade, status{$moduloIdField},
                cliente_id, empresa_id, atribuido_para, criado_por
            ) VALUES (
                :company_id, :numero_ticket, :titulo, :descricao, :categoria, :prioridade, :status{$moduloIdValue},
                :cliente_id, :empresa_id, :atribuido_para, :criado_por
            )";

            $stmt = $this->db->prepare($sql);
            $stmt->execute($data);
            $ticketId = $this->db->lastInsertId();

            // Adicionar comentário inicial se houver
            $comentarioInicial = $this->request->post('comentario_inicial');
            if (!empty($comentarioInicial)) {
                $usuarioId = isset($user['id']) ? (int) $user['id'] : null;
                $this->adicionarComentarioPrivado($ticketId, $comentarioInicial, $usuarioId);
            }

            $this->response->success('Ticket criado com sucesso', [
                'redirect' => UrlHelper::url('/tickets')
            ]);

        } catch (Exception $e) {
            error_log("Erro ao criar ticket: " . $e->getMessage());
            $this->response->error('Erro ao criar ticket: ' . $e->getMessage());
        }
    }

    /**
     * Exibe formulário de edição
     */
    public function edit(): void
    {
        // Verificar permissão de edição
        if (!$this->canEdit('tickets')) {
            $this->response->forbidden('Você não tem permissão para editar tickets.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();
            $id = (int) $this->request->get('id');

            if (!$id) {
                $this->response->error('ID do ticket não informado');
                return;
            }

            // Verificar se modulo_id existe na tabela
            $moduloIdExiste = false;
            $moduloJoin = '';
            $moduloSelect = '';
            try {
                $checkCol = $this->db->query("SHOW COLUMNS FROM tickets LIKE 'modulo_id'");
                if ($checkCol->fetch()) {
                    $moduloIdExiste = true;
                    $moduloJoin = 'LEFT JOIN modulos m ON t.modulo_id = m.id';
                    $moduloSelect = 'm.nome as modulo_nome,';
                }
            } catch (Exception $e) {
                // Coluna não existe
                $moduloIdExiste = false;
            }

            $stmt = $this->db->prepare("
                SELECT t.*,
                    p.name as cliente_nome,
                    e.razao_social as empresa_nome,
                    {$moduloSelect}
                FROM tickets t
                LEFT JOIN pessoas p ON t.cliente_id = p.id
                LEFT JOIN empresas e ON t.empresa_id = e.id
                {$moduloJoin}
                WHERE t.id = :id AND t.company_id = :company_id
                LIMIT 1
            ");
            $stmt->execute(['id' => $id, 'company_id' => $companyId]);
            $ticket = $stmt->fetch();

            if (!$ticket) {
                $this->response->error('Ticket não encontrado');
                return;
            }

            $empresas = $this->getEmpresas($companyId);
            $pessoas = $this->getPessoas($companyId);
            $usuarios = $this->getUsuarios($companyId);
            $modulos = $this->getModulosAtivos();
            $comentarios = $this->getComentarios($id);

            $this->view('tickets/edit', [
                'ticket' => $ticket,
                'empresas' => $empresas,
                'pessoas' => $pessoas,
                'usuarios' => $usuarios,
                'modulos' => $modulos,
                'comentarios' => $comentarios,
                'pageTitle' => 'Editar Ticket'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao carregar ticket: " . $e->getMessage());
            $this->response->error('Erro ao carregar ticket');
        }
    }

    /**
     * Atualiza ticket
     */
    public function update(): void
    {
        // Verificar permissão de edição
        if (!$this->canEdit('tickets')) {
            $this->response->forbidden('Você não tem permissão para editar tickets.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();
            $id = (int) $this->request->post('id');
            $user = $this->session->get('user');

            if (!$id) {
                $this->response->error('ID do ticket não informado');
                return;
            }

            // Verificar se existe
            $check = $this->db->prepare("SELECT id, status FROM tickets WHERE id = :id AND company_id = :company_id LIMIT 1");
            $check->execute(['id' => $id, 'company_id' => $companyId]);
            $ticketAtual = $check->fetch();

            if (!$ticketAtual) {
                $this->response->error('Ticket não encontrado');
                return;
            }

            $novoStatus = $this->request->post('status', $ticketAtual['status']);
            $statusMudou = $novoStatus !== $ticketAtual['status'];

            $moduloId = $this->request->post('modulo_id') ?: null;
            $tipo = $this->request->post('tipo', 'normal');
            $outrosTipo = $this->request->post('outros_tipo');

            // Se tipo for "outros" e tiver texto, usar o texto como tipo
            if ($tipo === 'outros' && !empty($outrosTipo)) {
                $tipo = 'outros: ' . trim($outrosTipo);
            }

            $data = [
                'id' => $id,
                'titulo' => $this->request->post('titulo'),
                'descricao' => $this->request->post('descricao'),
                'modulo_id' => $moduloId,
                'categoria' => $tipo, // Usando categoria para armazenar tipo (compatibilidade)
                'prioridade' => $this->request->post('prioridade', 'normal'),
                'status' => $novoStatus,
                'cliente_id' => $this->request->post('cliente_id') ?: null,
                'empresa_id' => $this->request->post('empresa_id') ?: null,
                'atribuido_para' => $this->request->post('atribuido_para') ?: null,
                'solucao' => $this->request->post('solucao') ?: null
            ];

            // Atualizar datas conforme status
            // Status 'Concluído' do enum corresponde ao status resolvido/fechado
            if ($novoStatus === 'Concluído' && $ticketAtual['status'] !== 'Concluído') {
                $data['data_resolucao'] = date('Y-m-d H:i:s');
                // Calcular tempo de resolução
                $stmt = $this->db->prepare("SELECT TIMESTAMPDIFF(MINUTE, data_abertura, NOW()) as minutos FROM tickets WHERE id = :id");
                $stmt->execute(['id' => $id]);
                $tempo = $stmt->fetch();
                $data['tempo_resolucao'] = $tempo['minutos'] ?? null;
                $data['data_fechamento'] = date('Y-m-d H:i:s');
            }

            // Verificar se modulo_id existe na tabela
            $moduloIdUpdate = '';
            try {
                $checkCol = $this->db->query("SHOW COLUMNS FROM tickets LIKE 'modulo_id'");
                if ($checkCol->fetch()) {
                    $moduloIdUpdate = ', modulo_id = :modulo_id';
                } else {
                    unset($data['modulo_id']);
                }
            } catch (Exception $e) {
                unset($data['modulo_id']);
            }

            // Atualizar
            $sql = "UPDATE tickets SET
                titulo = :titulo,
                descricao = :descricao,
                categoria = :categoria,
                prioridade = :prioridade,
                status = :status{$moduloIdUpdate},
                cliente_id = :cliente_id,
                empresa_id = :empresa_id,
                atribuido_para = :atribuido_para,
                solucao = :solucao";

            if (isset($data['data_resolucao'])) {
                $sql .= ", data_resolucao = :data_resolucao";
            }
            if (isset($data['data_fechamento'])) {
                $sql .= ", data_fechamento = :data_fechamento";
            }
            if (isset($data['tempo_resolucao'])) {
                $sql .= ", tempo_resolucao = :tempo_resolucao";
            }

            $sql .= " WHERE id = :id AND company_id = :company_id";

            $data['company_id'] = $companyId;
            $stmt = $this->db->prepare($sql);
            $stmt->execute($data);

            // Adicionar comentário de atualização de status se mudou
            if ($statusMudou) {
                // Os valores do enum do banco são: Aberto, Em Análise, Programação, Pendente, Retorno, Concluído
                $statusLabels = [
                    'Aberto' => 'Aberto',
                    'Em Análise' => 'Em Análise',
                    'Programação' => 'Programação',
                    'Pendente' => 'Pendente',
                    'Retorno' => 'Retorno',
                    'Concluído' => 'Concluído'
                ];
                $comentario = "Status alterado para: " . ($statusLabels[$novoStatus] ?? $novoStatus);
                $usuarioId = isset($user['id']) ? (int) $user['id'] : null;
                $this->adicionarComentarioPrivado($id, $comentario, $usuarioId, 'atualizacao_status', true);

                // Se o status mudou, sempre redirecionar para o index
                $this->response->success('Status atualizado com sucesso', [
                    'redirect' => UrlHelper::url('/tickets')
                ]);
                return;
            }

            $this->response->success('Ticket atualizado com sucesso', [
                'redirect' => UrlHelper::url('/tickets/visualizar?id=' . $id)
            ]);

        } catch (Exception $e) {
            error_log("Erro ao atualizar ticket: " . $e->getMessage());
            $this->response->error('Erro ao atualizar ticket: ' . $e->getMessage());
        }
    }

    /**
     * Visualiza ticket
     */
    public function show(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $id = (int) $this->request->get('id');

            if (!$id) {
                $this->response->error('ID do ticket não informado');
                return;
            }

            $stmt = $this->db->prepare("
                SELECT t.*,
                    p.name as cliente_nome,
                    p.document as cliente_document,
                    p.phone as cliente_phone,
                    p.mobile as cliente_mobile,
                    p.email as cliente_email,
                    e.razao_social as empresa_nome,
                    e.cnpj as empresa_cnpj,
                    e.telefone as empresa_telefone,
                    e.email as empresa_email,
                    u1.name as atribuido_para_nome,
                    u2.name as criado_por_nome
                FROM tickets t
                LEFT JOIN pessoas p ON t.cliente_id = p.id
                LEFT JOIN empresas e ON t.empresa_id = e.id
                LEFT JOIN users u1 ON t.atribuido_para = u1.id
                LEFT JOIN users u2 ON t.criado_por = u2.id
                WHERE t.id = :id AND t.company_id = :company_id
                LIMIT 1
            ");
            $stmt->execute(['id' => $id, 'company_id' => $companyId]);
            $ticket = $stmt->fetch();

            if (!$ticket) {
                $this->response->error('Ticket não encontrado');
                return;
            }

            $comentarios = $this->getComentarios((int) $id);
            $usuarios = $this->getUsuarios($companyId);
            $anexos = $this->getAnexos((int) $id);

            $this->view('tickets/show', [
                'ticket' => $ticket,
                'comentarios' => $comentarios,
                'usuarios' => $usuarios,
                'anexos' => $anexos,
                'pageTitle' => 'Visualizar Ticket'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao visualizar ticket: " . $e->getMessage());
            $this->response->error('Erro ao visualizar ticket');
        }
    }

    /**
     * Deleta ticket
     */
    public function delete(): void
    {
        // Verificar permissão de exclusão
        if (!$this->canDelete('tickets')) {
            $this->response->forbidden('Você não tem permissão para excluir tickets.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();
            $id = (int) $this->request->post('id');

            if (!$id) {
                $this->response->error('ID do ticket não informado');
                return;
            }

            // Verificar se existe
            $check = $this->db->prepare("SELECT id FROM tickets WHERE id = :id AND company_id = :company_id LIMIT 1");
            $check->execute(['id' => $id, 'company_id' => $companyId]);
            if (!$check->fetch()) {
                $this->response->error('Ticket não encontrado');
                return;
            }

            // Deletar comentários primeiro
            $this->db->prepare("DELETE FROM ticket_comentarios WHERE ticket_id = :id")->execute(['id' => $id]);

            // Deletar ticket
            $stmt = $this->db->prepare("DELETE FROM tickets WHERE id = :id AND company_id = :company_id");
            $stmt->execute(['id' => $id, 'company_id' => $companyId]);

            $this->response->success('Ticket excluído com sucesso');

        } catch (Exception $e) {
            error_log("Erro ao excluir ticket: " . $e->getMessage());
            $this->response->error('Erro ao excluir ticket: ' . $e->getMessage());
        }
    }

    /**
     * Adiciona comentário ao ticket
     */
    public function adicionarComentario(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $ticketId = (int) $this->request->post('ticket_id');
            $comentario = $this->request->post('comentario');
            $isInterno = (bool) $this->request->post('is_interno', 0);
            $user = $this->session->get('user');

            if (!$ticketId || !$comentario) {
                $this->response->error('Ticket ID e comentário são obrigatórios');
                return;
            }

            // Verificar se ticket existe e pertence à empresa
            $check = $this->db->prepare("SELECT id FROM tickets WHERE id = :id AND company_id = :company_id LIMIT 1");
            $check->execute(['id' => $ticketId, 'company_id' => $companyId]);
            if (!$check->fetch()) {
                $this->response->error('Ticket não encontrado');
                return;
            }

            $usuarioId = isset($user['id']) ? (int) $user['id'] : null;
            $this->adicionarComentarioPrivado($ticketId, $comentario, $usuarioId, 'comentario', $isInterno);

            $this->response->success('Comentário adicionado com sucesso');

        } catch (Exception $e) {
            error_log("Erro ao adicionar comentário: " . $e->getMessage());
            $this->response->error('Erro ao adicionar comentário: ' . $e->getMessage());
        }
    }

    /**
     * Atualiza status do ticket
     */
    public function atualizarStatus(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $id = (int) $this->request->post('id');
            $status = $this->request->post('status');
            $user = $this->session->get('user');

            if (!$id || !$status) {
                $this->response->error('ID e status são obrigatórios');
                return;
            }

            // Verificar se existe
            $check = $this->db->prepare("SELECT id, status FROM tickets WHERE id = :id AND company_id = :company_id LIMIT 1");
            $check->execute(['id' => $id, 'company_id' => $companyId]);
            $ticket = $check->fetch();

            if (!$ticket) {
                $this->response->error('Ticket não encontrado');
                return;
            }

            $data = ['id' => $id, 'status' => $status, 'company_id' => $companyId];

            // Atualizar datas conforme status
            // Status 'Concluído' do enum corresponde ao status resolvido/fechado
            if ($status === 'Concluído' && $ticket['status'] !== 'Concluído') {
                $data['data_resolucao'] = date('Y-m-d H:i:s');
                $stmt = $this->db->prepare("SELECT TIMESTAMPDIFF(MINUTE, data_abertura, NOW()) as minutos FROM tickets WHERE id = :id");
                $stmt->execute(['id' => $id]);
                $tempo = $stmt->fetch();
                $data['tempo_resolucao'] = $tempo['minutos'] ?? null;
                $data['data_fechamento'] = date('Y-m-d H:i:s');
            }

            $sql = "UPDATE tickets SET status = :status";
            if (isset($data['data_resolucao'])) {
                $sql .= ", data_resolucao = :data_resolucao";
            }
            if (isset($data['data_fechamento'])) {
                $sql .= ", data_fechamento = :data_fechamento";
            }
            if (isset($data['tempo_resolucao'])) {
                $sql .= ", tempo_resolucao = :tempo_resolucao";
            }
            $sql .= " WHERE id = :id AND company_id = :company_id";

            $stmt = $this->db->prepare($sql);
            $stmt->execute($data);

            // Adicionar comentário de atualização
            // Os valores do enum do banco são: Aberto, Em Análise, Programação, Pendente, Retorno, Concluído
            $statusLabels = [
                'Aberto' => 'Aberto',
                'Em Análise' => 'Em Análise',
                'Programação' => 'Programação',
                'Pendente' => 'Pendente',
                'Retorno' => 'Retorno',
                'Concluído' => 'Concluído'
            ];
            $comentario = "Status alterado para: " . ($statusLabels[$status] ?? $status);
            $usuarioId = isset($user['id']) ? (int) $user['id'] : null;
            $this->adicionarComentarioPrivado($id, $comentario, $usuarioId, 'atualizacao_status', true);

            $this->response->success('Status atualizado com sucesso', [
                'redirect' => UrlHelper::url('/tickets')
            ]);

        } catch (Exception $e) {
            error_log("Erro ao atualizar status: " . $e->getMessage());
            $this->response->error('Erro ao atualizar status: ' . $e->getMessage());
        }
    }

    /**
     * Métodos auxiliares privados
     */
    private function gerarProximoNumeroTicket(int $companyId): string
    {
        $stmt = $this->db->prepare("SELECT MAX(CAST(SUBSTRING(numero_ticket, 5) AS UNSIGNED)) AS maxnum
            FROM tickets
            WHERE company_id = :company_id AND numero_ticket LIKE 'TKT-%'");
        $stmt->execute(['company_id' => $companyId]);
        $row = $stmt->fetch();
        $max = (int)($row['maxnum'] ?? 0);
        $next = $max + 1;
        return 'TKT-' . str_pad((string)$next, 6, '0', STR_PAD_LEFT);
    }

    private function getEmpresas(int $companyId): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT id, razao_social, nome_fantasia, cnpj, telefone, email
                FROM empresas
                WHERE (id = :id OR company_id = :company_id)
                AND (ativo = 'Sim' OR ativo = 1 OR ativo IS NULL)
                ORDER BY razao_social ASC
            ");
            $stmt->bindValue(':id', $companyId, \PDO::PARAM_INT);
            $stmt->bindValue(':company_id', $companyId, \PDO::PARAM_INT);
            $stmt->execute();
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar empresas: " . $e->getMessage());
            // Se der erro, tentar sem filtro de ativo
            try {
                $stmt = $this->db->prepare("
                    SELECT id, razao_social, nome_fantasia, cnpj, telefone, email
                    FROM empresas
                    WHERE (id = :id OR company_id = :company_id)
                    ORDER BY razao_social ASC
                ");
                $stmt->bindValue(':id', $companyId, \PDO::PARAM_INT);
                $stmt->bindValue(':company_id', $companyId, \PDO::PARAM_INT);
                $stmt->execute();
                return $stmt->fetchAll();
            } catch (Exception $e2) {
                error_log("Erro ao buscar empresas (fallback): " . $e2->getMessage());
                return [];
            }
        }
    }

    private function getPessoas(int $companyId): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT id, name, trade_name, document, phone, mobile, email
                FROM pessoas
                WHERE company_id = :company_id AND (type IN ('cliente', 'ambos') OR tipo_cliente = 1) AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar pessoas: " . $e->getMessage());
            return [];
        }
    }

    private function getUsuarios(int $companyId): array
    {
        try {
            $stmt = $this->db->prepare("SELECT id, name, email FROM users WHERE company_id = :company_id OR role = 'admin' ORDER BY name");
            $stmt->execute(['company_id' => $companyId]);
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar usuários: " . $e->getMessage());
            return [];
        }
    }

    private function getModulosAtivos(): array
    {
        try {
            // Primeiro, tentar buscar todos os módulos
            $stmt = $this->db->query("SELECT id, nome, nome_interface, ativo FROM modulos ORDER BY nome");
            $modulos = $stmt->fetchAll();

            if (empty($modulos)) {
                error_log("Nenhum módulo encontrado na tabela modulos");
                return [];
            }

            // Filtrar apenas os ativos (aceita SIM, 1, TRUE, S, etc)
            $modulosAtivos = [];
            foreach ($modulos as $modulo) {
                $ativo = strtoupper((string) ($modulo['ativo'] ?? 'NAO'));
                if (in_array($ativo, ['SIM', '1', 'TRUE', 'S', 'YES'], true)) {
                    $modulosAtivos[] = [
                        'id' => $modulo['id'],
                        'nome' => $modulo['nome'],
                        'nome_interface' => $modulo['nome_interface'] ?? null
                    ];
                }
            }

            // Se não encontrou nenhum ativo, retornar todos (fallback)
            if (empty($modulosAtivos)) {
                error_log("Nenhum módulo ativo encontrado, retornando todos os módulos");
                return array_map(function($m) {
                    return [
                        'id' => $m['id'],
                        'nome' => $m['nome'],
                        'nome_interface' => $m['nome_interface'] ?? null
                    ];
                }, $modulos);
            }

            return $modulosAtivos;
        } catch (Exception $e) {
            error_log("Erro ao buscar módulos: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());
            // Se der erro, retornar todos os módulos como fallback
            try {
                $stmt = $this->db->query("SELECT id, nome, nome_interface FROM modulos ORDER BY nome");
                return $stmt->fetchAll();
            } catch (Exception $e2) {
                error_log("Erro ao buscar módulos (fallback): " . $e2->getMessage());
                return [];
            }
        }
    }

    private function getComentarios(int $ticketId): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT tc.*, u.name as usuario_nome
                FROM ticket_comentarios tc
                LEFT JOIN users u ON tc.usuario_id = u.id
                WHERE tc.ticket_id = :ticket_id
                ORDER BY tc.created_at ASC
            ");
            $stmt->execute(['ticket_id' => $ticketId]);
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar comentários: " . $e->getMessage());
            return [];
        }
    }

    private function adicionarComentarioPrivado(int $ticketId, string $comentario, ?int $usuarioId, string $tipo = 'comentario', bool $isInterno = false): void
    {
        try {
            $stmt = $this->db->prepare("
                INSERT INTO ticket_comentarios (ticket_id, usuario_id, comentario, tipo, is_interno)
                VALUES (:ticket_id, :usuario_id, :comentario, :tipo, :is_interno)
            ");
            $stmt->execute([
                'ticket_id' => $ticketId,
                'usuario_id' => $usuarioId,
                'comentario' => $comentario,
                'tipo' => $tipo,
                'is_interno' => $isInterno ? 1 : 0
            ]);
        } catch (Exception $e) {
            error_log("Erro ao adicionar comentário: " . $e->getMessage());
        }
    }

    /**
     * Processa upload de imagens para o ticket
     */
    private function processarUploadImagens(int $ticketId, array $files): void
    {
        try {
            // Criar diretório se não existir
            $uploadDir = ROOT_PATH . '/public/uploads/tickets/' . $ticketId . '/';
            if (!is_dir($uploadDir)) {
                mkdir($uploadDir, 0755, true);
            }

            $allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];
            $maxSize = 5 * 1024 * 1024; // 5MB

            $fileCount = count($files['name']);
            for ($i = 0; $i < $fileCount; $i++) {
                if ($files['error'][$i] !== UPLOAD_ERR_OK) {
                    continue;
                }

                // Validar tipo
                $fileType = $files['type'][$i];
                if (!in_array($fileType, $allowedTypes)) {
                    error_log("Tipo de arquivo não permitido: " . $fileType);
                    continue;
                }

                // Validar tamanho
                if ($files['size'][$i] > $maxSize) {
                    error_log("Arquivo muito grande: " . $files['name'][$i]);
                    continue;
                }

                // Gerar nome único
                $extension = pathinfo($files['name'][$i], PATHINFO_EXTENSION);
                $fileName = uniqid('img_', true) . '.' . $extension;
                $filePath = $uploadDir . $fileName;

                // Mover arquivo
                if (move_uploaded_file($files['tmp_name'][$i], $filePath)) {
                    // Salvar referência no banco (se houver tabela para isso)
                    // Por enquanto, apenas salva o arquivo
                    error_log("Imagem salva: " . $filePath);
                } else {
                    error_log("Erro ao mover arquivo: " . $files['name'][$i]);
                }
            }
        } catch (Exception $e) {
            error_log("Erro ao processar upload de imagens: " . $e->getMessage());
        }
    }

    /**
     * Busca anexos (imagens) do ticket
     */
    private function getAnexos(int $ticketId): array
    {
        $anexos = [];
        try {
            $uploadDir = ROOT_PATH . '/public/uploads/tickets/' . $ticketId . '/';

            if (is_dir($uploadDir)) {
                $files = scandir($uploadDir);
                $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];

                foreach ($files as $file) {
                    if ($file === '.' || $file === '..') {
                        continue;
                    }

                    $filePath = $uploadDir . $file;
                    if (is_file($filePath)) {
                        $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
                        if (in_array($extension, $allowedExtensions)) {
                            $anexos[] = [
                                'nome' => $file,
                                'caminho' => '/public/uploads/tickets/' . $ticketId . '/' . $file,
                                'tamanho' => filesize($filePath),
                                'data' => date('d/m/Y H:i', filemtime($filePath))
                            ];
                        }
                    }
                }
            }
        } catch (Exception $e) {
            error_log("Erro ao buscar anexos: " . $e->getMessage());
        }

        return $anexos;
    }
}

