<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Helpers\UrlHelper;
use Exception;

class SaidasController extends BaseController
{
    public function index(): void
    {
        // Verificar permissão de visualização
        if (!$this->canView('saidas')) {
            $this->response->forbidden('Você não tem permissão para visualizar saídas.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();

            // Verificar estrutura da tabela
            $stmtCols = $this->db->query("SHOW COLUMNS FROM contas_pagar");
            $colunas = $stmtCols->fetchAll(\PDO::FETCH_COLUMN, 0);
            $temPessoaId = in_array('pessoa_id', $colunas ?? [], true);
            $temSupplierId = in_array('supplier_id', $colunas ?? [], true);
            $temAmountPaid = in_array('amount_paid', $colunas ?? [], true);
            $temAmountReceived = in_array('amount_received', $colunas ?? [], true);

            // Preparar JOIN com pessoas
            $selectFornecedor = '';
            $joinFornecedor = '';
            $campoJoin = $temPessoaId ? 'pessoa_id' : ($temSupplierId ? 'supplier_id' : null);

            if ($campoJoin) {
                $selectFornecedor = ', p.name as supplier_name, p.document as supplier_document';
                $joinFornecedor = "LEFT JOIN pessoas p ON cp.{$campoJoin} = p.id";
            }

            // Filtros (busca inline como em entradas)
            $search = $this->request->get('fornecedor', '');
            $filtroStatus = $this->request->get('status') ?? '';

            // Construir WHERE
            $where = ['cp.company_id = :company_id'];
            $params = ['company_id' => $companyId];

            if (!empty($search)) {
                $where[] = '(cp.description LIKE :search OR p.name LIKE :search OR p.nome LIKE :search OR p.document LIKE :search)';
                $params['search'] = "%{$search}%";
            }

            if (!empty($filtroStatus)) {
                $where[] = 'cp.status = :status';
                $params['status'] = $filtroStatus;
            }

            $whereClause = implode(' AND ', $where);

            // Buscar contas
            $stmt = $this->db->prepare("
                SELECT
                    cp.*
                    {$selectFornecedor}
                FROM contas_pagar cp
                {$joinFornecedor}
                WHERE {$whereClause}
                ORDER BY cp.due_date ASC, cp.id DESC
            ");
            $stmt->execute($params);
            $contas = $stmt->fetchAll();

            $this->view('saidas/index', [
                'contas' => $contas,
                'filtros' => [
                    'status' => $filtroStatus,
                    'fornecedor' => $search
                ],
                'pageTitle' => 'Contas a Pagar',
                'activeMenu' => 'saidas'
            ]);

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

    public function create(): void
    {
        try {
            $companyId = $this->getCompanyId();

            // Buscar fornecedores (mesma busca das compras)
            try {
                $stmt = $this->db->prepare("
                    SELECT id, name, trade_name, document, phone, mobile, email FROM pessoas
                    WHERE company_id = :company_id
                    AND tipo_fornecedor = 1
                    AND is_active = 1
                    ORDER BY name ASC
                ");
                $stmt->execute(['company_id' => $companyId]);
                $fornecedores = $stmt->fetchAll();
            } catch (Exception $e) {
                error_log("Erro ao buscar fornecedores: " . $e->getMessage());
                $fornecedores = [];
            }

            // Buscar métodos de pagamento
            $metodosPagamento = $this->getMetodosPagamento();

            // Buscar contas bancárias
            $contasBancarias = $this->getContasBancarias();

            // Buscar status do módulo saídas/contas_pagar
            $stmt = $this->db->prepare("
                SELECT codigo, nome, descricao, cor, icone, ordem, is_default
                FROM modulo_status
                WHERE company_id = :company_id
                  AND modulo = 'contas_pagar'
                  AND ativo = 1
                ORDER BY ordem ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $statusSaidas = $stmt->fetchAll();

            // Buscar plano de contas
            $planoContas = $this->getPlanoContas();

            // Buscar centros de custo
            $centroCustos = $this->getCentroCustos();

            $this->view('saidas/create', [
                'pessoas' => [],
                'fornecedores' => $fornecedores,
                'metodosPagamento' => $metodosPagamento,
                'contasBancarias' => $contasBancarias,
                'planoContas' => $planoContas,
                'centroCustos' => $centroCustos,
                'statusSaidas' => $statusSaidas,
                'pageTitle' => 'Nova Conta a Pagar',
                'activeMenu' => 'saidas'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao carregar formulário de contas a pagar: " . $e->getMessage());
            $this->error('Erro ao carregar formulário');
        }
    }

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

        try {
            $companyId = $this->getCompanyId();

            $amount = (float) ($this->request->post('amount') ?? 0);
            $amountPaid = (float) ($this->request->post('amount_paid') ?? 0);
            $juros = (float) ($this->request->post('juros') ?? 0);
            $multa = (float) ($this->request->post('multa') ?? 0);
            $desconto = (float) ($this->request->post('desconto') ?? 0);
            $despesa = (float) ($this->request->post('despesa') ?? 0);

            // Calcular valor restante: Valor + Juros + Multa + Despesa - Desconto - Valor Pago
            $amountRemaining = $amount + $juros + $multa + $despesa - $desconto - $amountPaid;

            // Detectar estrutura da tabela
            $stmtCheck = $this->db->query("SHOW COLUMNS FROM contas_pagar");
            $columns = $stmtCheck->fetchAll();
            $columnNames = array_column($columns, 'Field');

            $campos = ['company_id', 'description', 'amount', 'amount_remaining', 'due_date', 'notes'];
            $valores = [':company_id', ':description', ':amount', ':amount_remaining', ':due_date', ':notes'];

            if (in_array('pessoa_id', $columnNames)) {
                $campos[] = 'pessoa_id';
                $valores[] = ':pessoa_id';
            } elseif (in_array('supplier_id', $columnNames)) {
                $campos[] = 'supplier_id';
                $valores[] = ':supplier_id';
            }
            if (in_array('compra_id', $columnNames)) {
                $campos[] = 'compra_id';
                $valores[] = ':compra_id';
            }
            if (in_array('numero', $columnNames)) {
                $campos[] = 'numero';
                $valores[] = ':numero';
            }
            if (in_array('amount_paid', $columnNames)) {
                $campos[] = 'amount_paid';
                $valores[] = ':amount_paid';
            }
            if (in_array('payment_date', $columnNames)) {
                $campos[] = 'payment_date';
                $valores[] = ':payment_date';
            }
            if (in_array('payment_method', $columnNames)) {
                $campos[] = 'payment_method';
                $valores[] = ':metodo_pagamento_id';
            } elseif (in_array('metodo_pagamento_id', $columnNames)) {
                $campos[] = 'metodo_pagamento_id';
                $valores[] = ':metodo_pagamento_id';
            } elseif (in_array('payment_method_id', $columnNames)) {
                $campos[] = 'payment_method_id';
                $valores[] = ':metodo_pagamento_id';
            }
            if (in_array('conta_bancaria_id', $columnNames)) {
                $campos[] = 'conta_bancaria_id';
                $valores[] = ':conta_bancaria_id';
            }
            if (in_array('plano_conta_id', $columnNames)) {
                $campos[] = 'plano_conta_id';
                $valores[] = ':plano_conta_id';
            }
            if (in_array('centro_custo_id', $columnNames)) {
                $campos[] = 'centro_custo_id';
                $valores[] = ':centro_custo_id';
            }
            if (in_array('status_id', $columnNames)) {
                $campos[] = 'status_id';
                $valores[] = ':status_id';
            } elseif (in_array('status', $columnNames)) {
                $campos[] = 'status';
                $valores[] = ':status';
            }
            if (in_array('juros', $columnNames)) {
                $campos[] = 'juros';
                $valores[] = ':juros';
            }
            if (in_array('multa', $columnNames)) {
                $campos[] = 'multa';
                $valores[] = ':multa';
            }
            if (in_array('desconto', $columnNames)) {
                $campos[] = 'desconto';
                $valores[] = ':desconto';
            }
            if (in_array('despesa', $columnNames)) {
                $campos[] = 'despesa';
                $valores[] = ':despesa';
            }

            $campos[] = 'created_at';
            $campos[] = 'updated_at';
            $valores[] = 'NOW()';
            $valores[] = 'NOW()';

            $sql = "INSERT INTO contas_pagar (" . implode(', ', $campos) . ") VALUES (" . implode(', ', $valores) . ")";
            $stmt = $this->db->prepare($sql);

            $dadosBind = [
                'company_id' => $companyId,
                'description' => $this->request->post('description') ?? '',
                'amount' => $amount,
                'amount_remaining' => $amountRemaining,
                'due_date' => $this->request->post('due_date') ?? '',
                'notes' => $this->request->post('notes') ?: null,
            ];

            // Status - O formulário envia status_id com código do status (ex: "pendente")
            $statusValue = $this->request->post('status_id') ?? $this->request->post('status') ?? 'pendente';

            if (in_array('status_id', $columnNames)) {
                if (is_numeric($statusValue)) {
                    $dadosBind['status_id'] = (int) $statusValue;
                } else {
                    // Buscar ID do status pelo código na tabela modulo_status
                    try {
                        $stmtStatus = $this->db->prepare("
                            SELECT id FROM modulo_status
                            WHERE codigo = :codigo
                              AND company_id = :company_id
                              AND modulo = 'contas_pagar'
                            LIMIT 1
                        ");
                        $stmtStatus->execute(['codigo' => $statusValue, 'company_id' => $companyId]);
                        $statusRow = $stmtStatus->fetch();
                        if ($statusRow) {
                            $dadosBind['status_id'] = (int) $statusRow['id'];
                        } else {
                            $dadosBind['status_id'] = null;
                        }
                    } catch (Exception $e) {
                        $dadosBind['status_id'] = null;
                    }
                }
            } elseif (in_array('status', $columnNames)) {
                $dadosBind['status'] = $statusValue;
            }

            // Fornecedor/Pessoa - pode ser pessoa_id ou supplier_id
            $pessoaId = $this->request->post('pessoa_id');
            $pessoaIdValue = !empty($pessoaId) && $pessoaId !== '' && $pessoaId !== '0' ? (int) $pessoaId : null;

            if (in_array('pessoa_id', $columnNames)) {
                $dadosBind['pessoa_id'] = $pessoaIdValue;
            } elseif (in_array('supplier_id', $columnNames)) {
                $dadosBind['supplier_id'] = $pessoaIdValue;
            }
            if (in_array('compra_id', $columnNames)) {
                $dadosBind['compra_id'] = $this->request->post('compra_id') ?: null;
            }
            if (in_array('numero', $columnNames)) {
                $dadosBind['numero'] = $this->request->post('numero') ?: null;
            }
            if (in_array('amount_paid', $columnNames)) {
                $dadosBind['amount_paid'] = $amountPaid;
            }
            if (in_array('payment_date', $columnNames)) {
                $paymentDate = trim($this->request->post('payment_date') ?? '');
                $dadosBind['payment_date'] = $paymentDate !== '' ? $paymentDate : null;
            }
            if (in_array('payment_method', $columnNames) || in_array('metodo_pagamento_id', $columnNames) || in_array('payment_method_id', $columnNames)) {
                $metodoPagamento = trim($this->request->post('metodo_pagamento_id') ?? '');
                $dadosBind['metodo_pagamento_id'] = $metodoPagamento !== '' && $metodoPagamento !== '0' ? (int) $metodoPagamento : null;
            }
            if (in_array('conta_bancaria_id', $columnNames)) {
                $contaBancaria = trim($this->request->post('conta_bancaria_id') ?? '');
                $dadosBind['conta_bancaria_id'] = $contaBancaria !== '' && $contaBancaria !== '0' ? (int) $contaBancaria : null;
            }
            if (in_array('plano_conta_id', $columnNames)) {
                $dadosBind['plano_conta_id'] = $this->request->post('plano_conta_id') ?: null;
            }
            if (in_array('centro_custo_id', $columnNames)) {
                $dadosBind['centro_custo_id'] = $this->request->post('centro_custo_id') ?: null;
            }
            if (in_array('juros', $columnNames)) {
                $dadosBind['juros'] = $juros;
            }
            if (in_array('multa', $columnNames)) {
                $dadosBind['multa'] = $multa;
            }
            if (in_array('desconto', $columnNames)) {
                $dadosBind['desconto'] = $desconto;
            }
            if (in_array('despesa', $columnNames)) {
                $dadosBind['despesa'] = $despesa;
            }

            $this->db->beginTransaction();

            $stmt->execute($dadosBind);
            $contaId = (int) $this->db->lastInsertId();

            $this->logActivity('create', 'contas_pagar', $contaId, $dadosBind);

            // Verificar se o status gera financeiro e inserir no fluxo de caixa
            if (!empty($dadosBind['status_id'])) {
                $this->gerarFluxoCaixa($contaId, (int) $dadosBind['status_id'], $companyId);
            }

            $this->db->commit();

            $this->success('Conta a pagar criada com sucesso', [
                'id' => $contaId,
                'redirect' => UrlHelper::url('/saidas')
            ]);

        } catch (Exception $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log("Erro ao criar conta a pagar: " . $e->getMessage());
            $this->error('Erro ao criar conta a pagar');
        }
    }

    public function edit(): void
    {
        // Verificar permissão de edição
        if (!$this->canEdit('saidas')) {
            $this->response->forbidden('Você não tem permissão para editar saídas.');
            return;
        }

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

            if (empty($id)) {
                $this->error('ID da conta não informado');
                return;
            }

            $conta = $this->getConta($id);

            if (!$conta) {
                $this->response->notFound('Conta a pagar não encontrada');
                return;
            }

            $companyId = $this->getCompanyId();

            // Buscar fornecedores (mesma busca das compras)
            try {
                $stmt = $this->db->prepare("
                    SELECT id, name, trade_name, document, phone, mobile, email FROM pessoas
                    WHERE company_id = :company_id
                    AND tipo_fornecedor = 1
                    AND is_active = 1
                    ORDER BY name ASC
                ");
                $stmt->execute(['company_id' => $companyId]);
                $fornecedores = $stmt->fetchAll();
            } catch (Exception $e) {
                error_log("Erro ao buscar fornecedores: " . $e->getMessage());
                $fornecedores = [];
            }

            // Buscar métodos de pagamento
            $metodosPagamento = $this->getMetodosPagamento();

            // Buscar contas bancárias
            $contasBancarias = $this->getContasBancarias();

            // Buscar status do módulo saídas/contas_pagar
            $stmt = $this->db->prepare("
                SELECT codigo, nome, descricao, cor, icone, ordem, is_default
                FROM modulo_status
                WHERE company_id = :company_id
                  AND modulo = 'contas_pagar'
                  AND ativo = 1
                ORDER BY ordem ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $statusSaidas = $stmt->fetchAll();

            // Buscar plano de contas
            $planoContas = $this->getPlanoContas();

            // Buscar centros de custo
            $centroCustos = $this->getCentroCustos();

            $this->view('saidas/edit', [
                'conta' => $conta,
                'pessoas' => [],
                'fornecedores' => $fornecedores,
                'metodosPagamento' => $metodosPagamento,
                'contasBancarias' => $contasBancarias,
                'planoContas' => $planoContas,
                'centroCustos' => $centroCustos,
                'statusSaidas' => $statusSaidas,
                'pageTitle' => 'Editar Conta a Pagar',
                'activeMenu' => 'saidas'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao editar conta a pagar: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());
            $this->error('Erro ao carregar formulário: ' . $e->getMessage());
        }
    }

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

        try {
            $id = (int) $this->request->post('id');
            $conta = $this->getConta($id);

            if (!$conta) {
                $this->error('Conta a pagar não encontrada');
                return;
            }

            $companyId = $this->getCompanyId();
            $amount = (float) ($this->request->post('amount') ?? 0);
            $amountPaid = (float) ($this->request->post('amount_paid') ?? 0);
            $juros = (float) ($this->request->post('juros') ?? 0);
            $multa = (float) ($this->request->post('multa') ?? 0);
            $desconto = (float) ($this->request->post('desconto') ?? 0);
            $despesa = (float) ($this->request->post('despesa') ?? 0);

            // Calcular valor restante: Valor + Juros + Multa + Despesa - Desconto - Valor Pago
            $amountRemaining = $amount + $juros + $multa + $despesa - $desconto - $amountPaid;

            // Detectar estrutura da tabela
            $stmtCheck = $this->db->query("SHOW COLUMNS FROM contas_pagar");
            $columns = $stmtCheck->fetchAll();
            $columnNames = array_column($columns, 'Field');

            $sets = ['description = :description', 'amount = :amount', 'amount_remaining = :amount_remaining', 'due_date = :due_date', 'notes = :notes'];

            if (in_array('pessoa_id', $columnNames)) {
                $sets[] = 'pessoa_id = :pessoa_id';
            } elseif (in_array('supplier_id', $columnNames)) {
                $sets[] = 'supplier_id = :supplier_id';
            }
            if (in_array('compra_id', $columnNames)) {
                $sets[] = 'compra_id = :compra_id';
            }
            if (in_array('numero', $columnNames)) {
                $sets[] = 'numero = :numero';
            }
            if (in_array('amount_paid', $columnNames)) {
                $sets[] = 'amount_paid = :amount_paid';
            }
            if (in_array('payment_date', $columnNames)) {
                $sets[] = 'payment_date = :payment_date';
            }
            if (in_array('payment_method', $columnNames)) {
                $sets[] = 'payment_method = :metodo_pagamento_id';
            } elseif (in_array('metodo_pagamento_id', $columnNames)) {
                $sets[] = 'metodo_pagamento_id = :metodo_pagamento_id';
            } elseif (in_array('payment_method_id', $columnNames)) {
                $sets[] = 'payment_method_id = :metodo_pagamento_id';
            }
            if (in_array('conta_bancaria_id', $columnNames)) {
                $sets[] = 'conta_bancaria_id = :conta_bancaria_id';
            }
            if (in_array('plano_conta_id', $columnNames)) {
                $sets[] = 'plano_conta_id = :plano_conta_id';
            }
            if (in_array('centro_custo_id', $columnNames)) {
                $sets[] = 'centro_custo_id = :centro_custo_id';
            }
            // Priorizar status_id
            if (in_array('status_id', $columnNames)) {
                $sets[] = 'status_id = :status_id';
                if (in_array('status', $columnNames)) {
                    $sets[] = 'status = NULL';
                }
            } elseif (in_array('status', $columnNames)) {
                $sets[] = 'status = :status';
            }
            if (in_array('juros', $columnNames)) {
                $sets[] = 'juros = :juros';
            }
            if (in_array('multa', $columnNames)) {
                $sets[] = 'multa = :multa';
            }
            if (in_array('desconto', $columnNames)) {
                $sets[] = 'desconto = :desconto';
            }
            if (in_array('despesa', $columnNames)) {
                $sets[] = 'despesa = :despesa';
            }

            $sets[] = 'updated_at = NOW()';

            $sql = "UPDATE contas_pagar SET " . implode(', ', $sets) . " WHERE id = :id AND company_id = :company_id";

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

            $dadosBind = [
                'id' => $id,
                'company_id' => $companyId,
                'description' => $this->request->post('description') ?? '',
                'amount' => $amount,
                'amount_remaining' => $amountRemaining,
                'due_date' => $this->request->post('due_date') ?? '',
                'notes' => $this->request->post('notes') ?: null,
            ];

            // Status - O formulário envia status_id com código do status
            $statusValue = $this->request->post('status_id') ?? $this->request->post('status') ?? 'pendente';

            if (in_array('status_id', $columnNames)) {
                if (is_numeric($statusValue)) {
                    $dadosBind['status_id'] = (int) $statusValue;
                } else {
                    try {
                        $stmtStatus = $this->db->prepare("
                            SELECT id FROM modulo_status
                            WHERE codigo = :codigo
                              AND company_id = :company_id
                              AND modulo = 'contas_pagar'
                            LIMIT 1
                        ");
                        $stmtStatus->execute(['codigo' => $statusValue, 'company_id' => $companyId]);
                        $statusRow = $stmtStatus->fetch();
                        $dadosBind['status_id'] = $statusRow ? (int) $statusRow['id'] : null;
                    } catch (Exception $e) {
                        $dadosBind['status_id'] = null;
                    }
                }
            } elseif (in_array('status', $columnNames)) {
                $dadosBind['status'] = $statusValue;
            }

            // Fornecedor/Pessoa
            $pessoaId = $this->request->post('pessoa_id');
            $pessoaIdValue = !empty($pessoaId) && $pessoaId !== '' && $pessoaId !== '0' ? (int) $pessoaId : null;

            if (in_array('pessoa_id', $columnNames)) {
                $dadosBind['pessoa_id'] = $pessoaIdValue;
            } elseif (in_array('supplier_id', $columnNames)) {
                $dadosBind['supplier_id'] = $pessoaIdValue;
            }
            if (in_array('compra_id', $columnNames)) {
                $dadosBind['compra_id'] = $this->request->post('compra_id') ?: null;
            }
            if (in_array('numero', $columnNames)) {
                $dadosBind['numero'] = $this->request->post('numero') ?: null;
            }
            if (in_array('amount_paid', $columnNames)) {
                $dadosBind['amount_paid'] = $amountPaid;
            }
            if (in_array('payment_date', $columnNames)) {
                $paymentDate = trim($this->request->post('payment_date') ?? '');
                $dadosBind['payment_date'] = $paymentDate !== '' ? $paymentDate : null;
            }
            if (in_array('payment_method', $columnNames) || in_array('metodo_pagamento_id', $columnNames) || in_array('payment_method_id', $columnNames)) {
                $metodoPagamento = trim($this->request->post('metodo_pagamento_id') ?? '');
                $dadosBind['metodo_pagamento_id'] = $metodoPagamento !== '' && $metodoPagamento !== '0' ? (int) $metodoPagamento : null;
            }
            if (in_array('conta_bancaria_id', $columnNames)) {
                $contaBancaria = trim($this->request->post('conta_bancaria_id') ?? '');
                $dadosBind['conta_bancaria_id'] = $contaBancaria !== '' && $contaBancaria !== '0' ? (int) $contaBancaria : null;
            }
            if (in_array('plano_conta_id', $columnNames)) {
                $dadosBind['plano_conta_id'] = $this->request->post('plano_conta_id') ?: null;
            }
            if (in_array('centro_custo_id', $columnNames)) {
                $dadosBind['centro_custo_id'] = $this->request->post('centro_custo_id') ?: null;
            }
            if (in_array('juros', $columnNames)) {
                $dadosBind['juros'] = $juros;
            }
            if (in_array('multa', $columnNames)) {
                $dadosBind['multa'] = $multa;
            }
            if (in_array('desconto', $columnNames)) {
                $dadosBind['desconto'] = $desconto;
            }
            if (in_array('despesa', $columnNames)) {
                $dadosBind['despesa'] = $despesa;
            }

            $this->db->beginTransaction();

            $result = $stmt->execute($dadosBind);
            $rowsAffected = $stmt->rowCount();

            if (!$result || $rowsAffected === 0) {
                throw new \Exception('Nenhuma linha foi atualizada. Verifique se o ID existe e pertence à empresa.');
            }

            $this->logActivity('update', 'contas_pagar', $id, $dadosBind);

            // Verificar se o status mudou para PAGO
            $statusMudouParaPago = false;
            $statusAnteriorPago = false;

            // Verificar status anterior
            if (!empty($conta['status_id'])) {
                $stmtStatusAnt = $this->db->prepare("
                    SELECT codigo FROM modulo_status
                    WHERE id = :status_id AND company_id = :company_id
                ");
                $stmtStatusAnt->execute([
                    'status_id' => $conta['status_id'],
                    'company_id' => $companyId
                ]);
                $statusAntInfo = $stmtStatusAnt->fetch();
                if ($statusAntInfo && strtolower($statusAntInfo['codigo']) === 'pago') {
                    $statusAnteriorPago = true;
                }
            } elseif (!empty($conta['status']) && strtolower($conta['status']) === 'pago') {
                $statusAnteriorPago = true;
            }

            // Verificar novo status
            if (!empty($dadosBind['status_id'])) {
                // Buscar código do status para verificar se é "pago"
                $stmtStatusCheck = $this->db->prepare("
                    SELECT codigo FROM modulo_status
                    WHERE id = :status_id AND company_id = :company_id
                ");
                $stmtStatusCheck->execute([
                    'status_id' => $dadosBind['status_id'],
                    'company_id' => $companyId
                ]);
                $statusInfo = $stmtStatusCheck->fetch();

                if ($statusInfo && strtolower($statusInfo['codigo']) === 'pago' && !$statusAnteriorPago) {
                    $statusMudouParaPago = true;
                }

                // Verificar se o status gera financeiro e inserir no fluxo de caixa
                $this->gerarFluxoCaixa($id, (int) $dadosBind['status_id'], $companyId);
            } elseif (!empty($dadosBind['status']) && strtolower($dadosBind['status']) === 'pago' && !$statusAnteriorPago) {
                $statusMudouParaPago = true;
            }

            $this->db->commit();

            // Se mudou para PAGO, gerar saída no fluxo de caixa (igual ao botão pagar)
            if ($statusMudouParaPago) {
                // Buscar dados atualizados da conta
                $contaAtualizada = $this->getConta($id);
                if ($contaAtualizada) {
                    $this->inserirFluxoCaixa($contaAtualizada, 'saida');
                }
            }

            // Se for AJAX/Fetch, retornar JSON
            if ($this->request->isAjax() || isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
                $this->response->json([
                    'success' => true,
                    'message' => 'Conta a pagar atualizada com sucesso!',
                    'data' => [
                        'redirect' => UrlHelper::url('/saidas')
                    ]
                ]);
                return;
            }

            $this->session->set('flash_success', 'Conta a pagar atualizada com sucesso!');
            $this->redirect('/saidas');

        } catch (Exception $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log("Erro ao atualizar conta a pagar: " . $e->getMessage());

            if ($this->request->isAjax() || isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
                $this->response->json([
                    'success' => false,
                    'message' => 'Erro ao atualizar: ' . $e->getMessage()
                ]);
                return;
            }

            $this->session->set('flash_error', 'Erro ao atualizar: ' . $e->getMessage());
            $this->redirect('/saidas');
        }
    }

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

        try {
            $id = (int) $this->request->post('id');
            $conta = $this->getConta($id);

            if (!$conta) {
                $this->error('Conta a pagar não encontrada');
                return;
            }

            $this->db->beginTransaction();

            $stmt = $this->db->prepare("DELETE FROM contas_pagar WHERE id = :id AND company_id = :company_id");
            $stmt->execute(['id' => $id, 'company_id' => $this->getCompanyId()]);

            $this->logActivity('delete', 'contas_pagar', $id, $conta);
            $this->db->commit();

            $this->success('Conta a pagar excluída com sucesso');

        } catch (Exception $e) {
            $this->db->rollBack();
            error_log("Erro ao excluir conta a pagar: " . $e->getMessage());
            $this->error('Erro ao excluir conta a pagar');
        }
    }

    /**
     * Marca conta como paga
     */
    public function pagar(): void
    {
        try {
            $id = (int) $this->request->post('id');
            $conta = $this->getConta($id);

            if (!$conta) {
                $this->error('Conta a pagar não encontrada');
                return;
            }

            $companyId = $this->getCompanyId();
            $this->db->beginTransaction();

            // Detectar campos da tabela
            $stmtCheck = $this->db->query("SHOW COLUMNS FROM contas_pagar");
            $columns = $stmtCheck->fetchAll();
            $columnNames = array_column($columns, 'Field');

            $sets = ["updated_at = NOW()"];

            // Atualizar status - priorizar status_id se existir
            if (in_array('status_id', $columnNames)) {
                // Buscar ID do status "pago"
                $stmtStatus = $this->db->prepare("
                    SELECT id FROM modulo_status
                    WHERE company_id = :company_id
                    AND modulo = 'contas_pagar'
                    AND codigo = 'pago'
                    AND ativo = 1
                    LIMIT 1
                ");
                $stmtStatus->execute(['company_id' => $companyId]);
                $statusPago = $stmtStatus->fetch();
                if ($statusPago) {
                    $sets[] = "status_id = " . (int) $statusPago['id'];
                }
                // Limpar status antigo se existir
                if (in_array('status', $columnNames)) {
                    $sets[] = "status = NULL";
                }
            } else {
                $sets[] = "status = 'pago'";
            }

            if (in_array('payment_date', $columnNames)) {
                $sets[] = 'payment_date = CURDATE()';
            }

            // Atualizar amount_paid se necessário
            if (in_array('amount_paid', $columnNames)) {
                $sets[] = 'amount_paid = amount';
            } elseif (in_array('amount_received', $columnNames)) {
                $sets[] = 'amount_received = amount';
            }

            if (in_array('amount_remaining', $columnNames)) {
                $sets[] = 'amount_remaining = 0';
            }

            $sql = "UPDATE contas_pagar SET " . implode(', ', $sets) . " WHERE id = :id AND company_id = :company_id";
            $stmt = $this->db->prepare($sql);
            $stmt->execute(['id' => $id, 'company_id' => $companyId]);

            // Buscar conta atualizada para inserir no fluxo de caixa
            $contaAtualizada = $this->getConta($id);
            if ($contaAtualizada) {
                $this->inserirFluxoCaixa($contaAtualizada, 'saida');
            }

            $this->logActivity('pagar', 'contas_pagar', $id, $conta);

            $this->db->commit();

            $this->success('Conta marcada como paga com sucesso');

        } catch (Exception $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log("Erro ao marcar conta como paga: " . $e->getMessage());
            $this->error('Erro ao marcar conta como paga');
        }
    }

    /**
     * Visualiza uma conta a pagar
     */
    public function show(): void
    {
        try {
            $id = (int) $this->request->get('id');
            $conta = $this->getConta($id);

            if (!$conta) {
                $this->error('Conta a pagar não encontrada');
                return;
            }

            // Buscar fornecedor
            $fornecedor = [];
            $pessoaId = $conta['pessoa_id'] ?? $conta['supplier_id'] ?? null;
            if ($pessoaId) {
                $stmt = $this->db->prepare("SELECT * FROM pessoas WHERE id = :id");
                $stmt->execute(['id' => $pessoaId]);
                $fornecedor = $stmt->fetch() ?: [];
            }

            $this->view('saidas/show', [
                'conta' => $conta,
                'fornecedor' => $fornecedor,
                'pageTitle' => 'Conta a Pagar',
                'activeMenu' => 'saidas'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao exibir conta a pagar: " . $e->getMessage());
            $this->error('Erro ao carregar conta a pagar');
        }
    }

    /**
     * Cria lançamento de saída no fluxo de caixa
     */
    private function criarLancamentoFluxoCaixa(int $contaId, float $valor, string $data, string $descricao): void
    {
        try {
            // Verificar se já existe lançamento para esta conta a pagar
            $stmtCheck = $this->db->prepare("
                SELECT id FROM fluxo_caixa
                WHERE reference_type = 'contas_pagar'
                AND reference_id = :reference_id
                AND company_id = :company_id
            ");
            $stmtCheck->execute([
                'reference_id' => $contaId,
                'company_id' => $this->getCompanyId()
            ]);

            if ($stmtCheck->fetch()) {
                // Já existe lançamento, não criar duplicado
                return;
            }

            // Calcular saldo atual
            $stmtSaldo = $this->db->prepare("
                SELECT balance FROM fluxo_caixa
                WHERE company_id = :company_id
                ORDER BY date DESC, id DESC
                LIMIT 1
            ");
            $stmtSaldo->execute(['company_id' => $this->getCompanyId()]);
            $ultimoSaldo = $stmtSaldo->fetchColumn() ?: 0;

            $novoSaldo = $ultimoSaldo - $valor;

            // Inserir lançamento no fluxo de caixa
            $stmtInsert = $this->db->prepare("
                INSERT INTO fluxo_caixa (
                    company_id,
                    date,
                    type,
                    category,
                    description,
                    amount,
                    balance,
                    reference_type,
                    reference_id,
                    created_at
                ) VALUES (
                    :company_id,
                    :date,
                    'saida',
                    'Contas a Pagar',
                    :description,
                    :amount,
                    :balance,
                    'contas_pagar',
                    :reference_id,
                    NOW()
                )
            ");

            $stmtInsert->execute([
                'company_id' => $this->getCompanyId(),
                'date' => $data,
                'description' => $descricao,
                'amount' => $valor,
                'balance' => $novoSaldo,
                'reference_id' => $contaId
            ]);

        } catch (Exception $e) {
            error_log("Erro ao criar lançamento no fluxo de caixa: " . $e->getMessage());
            // Não propaga o erro para não interromper o fluxo principal
        }
    }

    /**
     * Upload de anexo para conta a pagar
     */
    public function uploadAnexo(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $contaId = (int) $this->request->post('conta_id');
            $descricao = $this->request->post('descricao', '');

            if (empty($contaId)) {
                $this->error('ID da conta não informado');
                return;
            }

            // Verificar se a conta existe
            $stmt = $this->db->prepare("SELECT id FROM contas_pagar WHERE id = :id AND company_id = :company_id");
            $stmt->execute(['id' => $contaId, 'company_id' => $companyId]);
            if (!$stmt->fetch()) {
                $this->error('Conta não encontrada');
                return;
            }

            if (!isset($_FILES['arquivo']) || $_FILES['arquivo']['error'] !== UPLOAD_ERR_OK) {
                $this->error('Nenhum arquivo enviado ou erro no upload');
                return;
            }

            $arquivo = $_FILES['arquivo'];
            $extensao = strtolower(pathinfo($arquivo['name'], PATHINFO_EXTENSION));

            // Extensões permitidas
            $extensoesPermitidas = ['jpg', 'jpeg', 'png', 'pdf'];
            if (!in_array($extensao, $extensoesPermitidas)) {
                $this->error('Formato de arquivo não permitido. Permitidos: JPG, JPEG, PNG e PDF');
                return;
            }

            // Tamanho máximo: 10MB
            $tamanhoMax = 10 * 1024 * 1024;
            if ($arquivo['size'] > $tamanhoMax) {
                $this->error('Arquivo muito grande. Tamanho máximo: 10MB');
                return;
            }

            // Criar diretório se não existir
            $uploadDir = \ROOT_PATH . '/storage/uploads/anexos/saidas/';
            if (!is_dir($uploadDir)) {
                mkdir($uploadDir, 0755, true);
            }

            // Nome único para o arquivo
            $nomeArquivo = uniqid() . '_' . time() . '.' . $extensao;
            $caminhoCompleto = $uploadDir . $nomeArquivo;

            // Mover arquivo
            if (!move_uploaded_file($arquivo['tmp_name'], $caminhoCompleto)) {
                $this->error('Erro ao salvar arquivo');
                return;
            }

            // Verificar se a tabela de anexos existe
            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'anexos'");
            if (!$stmtCheck->fetch()) {
                // Criar tabela se não existir
                $sql = file_get_contents(\ROOT_PATH . '/database/migration_create_anexos_table.sql');
                $this->db->exec($sql);
            }

            // Salvar no banco
            $caminhoRelativo = 'storage/uploads/anexos/saidas/' . $nomeArquivo;
            $userId = $this->session->get('user_id');

            $stmt = $this->db->prepare("
                INSERT INTO anexos (
                    company_id, tipo, conta_id, nome_original, nome_arquivo,
                    caminho, tamanho, tipo_mime, descricao, created_by
                ) VALUES (
                    :company_id, 'saida', :conta_id, :nome_original, :nome_arquivo,
                    :caminho, :tamanho, :tipo_mime, :descricao, :created_by
                )
            ");

            $stmt->execute([
                'company_id' => $companyId,
                'conta_id' => $contaId,
                'nome_original' => $arquivo['name'],
                'nome_arquivo' => $nomeArquivo,
                'caminho' => $caminhoRelativo,
                'tamanho' => $arquivo['size'],
                'tipo_mime' => $arquivo['type'],
                'descricao' => $descricao,
                'created_by' => $userId
            ]);

            $anexoId = $this->db->lastInsertId();

            $this->success('Anexo enviado com sucesso', [
                'anexo_id' => $anexoId,
                'nome' => $arquivo['name']
            ]);

        } catch (\Exception $e) {
            error_log("Erro ao fazer upload de anexo: " . $e->getMessage());
            $this->error('Erro ao fazer upload: ' . $e->getMessage());
        }
    }

    /**
     * Listar anexos de uma conta
     */
    public function listarAnexos(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $contaId = (int) $this->request->get('conta_id');

            if (empty($contaId)) {
                $this->error('ID da conta não informado');
                return;
            }

            // Verificar se a tabela existe
            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'anexos'");
            if (!$stmtCheck->fetch()) {
                $this->success('Anexos carregados', ['anexos' => []]);
                return;
            }

            $stmt = $this->db->prepare("
                SELECT a.*, u.name as usuario_nome
                FROM anexos a
                LEFT JOIN users u ON a.created_by = u.id
                WHERE a.company_id = :company_id
                AND a.tipo = 'saida'
                AND a.conta_id = :conta_id
                ORDER BY a.created_at DESC
            ");

            $stmt->execute(['company_id' => $companyId, 'conta_id' => $contaId]);
            $anexos = $stmt->fetchAll();

            $this->success('Anexos carregados', ['anexos' => $anexos]);

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

    /**
     * Deletar anexo
     */
    public function deletarAnexo(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $anexoId = (int) $this->request->post('anexo_id');

            if (empty($anexoId)) {
                $this->error('ID do anexo não informado');
                return;
            }

            // Buscar anexo
            $stmt = $this->db->prepare("
                SELECT * FROM anexos
                WHERE id = :id AND company_id = :company_id AND tipo = 'saida'
            ");
            $stmt->execute(['id' => $anexoId, 'company_id' => $companyId]);
            $anexo = $stmt->fetch();

            if (!$anexo) {
                $this->error('Anexo não encontrado');
                return;
            }

            // Deletar arquivo físico
            $caminhoCompleto = \ROOT_PATH . '/' . $anexo['caminho'];
            if (file_exists($caminhoCompleto)) {
                unlink($caminhoCompleto);
            }

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

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

        } catch (\Exception $e) {
            error_log("Erro ao deletar anexo: " . $e->getMessage());
            $this->error('Erro ao deletar anexo');
        }
    }

    /**
     * Download de anexo
     */
    public function downloadAnexo(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $anexoId = (int) $this->request->get('id');

            $stmt = $this->db->prepare("
                SELECT * FROM anexos
                WHERE id = :id AND company_id = :company_id AND tipo = 'saida'
            ");
            $stmt->execute(['id' => $anexoId, 'company_id' => $companyId]);
            $anexo = $stmt->fetch();

            if (!$anexo) {
                $this->response->notFound('Anexo não encontrado');
                return;
            }

            $caminhoCompleto = \ROOT_PATH . '/' . $anexo['caminho'];
            if (!file_exists($caminhoCompleto)) {
                $this->response->notFound('Arquivo não encontrado');
                return;
            }

            header('Content-Type: ' . $anexo['tipo_mime']);
            header('Content-Disposition: attachment; filename="' . $anexo['nome_original'] . '"');
            header('Content-Length: ' . filesize($caminhoCompleto));
            readfile($caminhoCompleto);
            exit;

        } catch (\Exception $e) {
            error_log("Erro ao fazer download de anexo: " . $e->getMessage());
            $this->error('Erro ao fazer download');
        }
    }

    /**
     * Gera lançamento no fluxo de caixa se o status gerar financeiro
     */
    private function gerarFluxoCaixa(int $contaPagarId, int $statusId, int $companyId): void
    {
        try {
            // Buscar informações do status
            $stmtStatus = $this->db->prepare("
                SELECT gera_financeiro
                FROM modulo_status
                WHERE id = :id AND company_id = :company_id
            ");
            $stmtStatus->execute(['id' => $statusId, 'company_id' => $companyId]);
            $status = $stmtStatus->fetch();

            // Se o status não gera financeiro, não faz nada
            if (!$status || empty($status['gera_financeiro'])) {
                return;
            }

            // Buscar informações da conta a pagar
            $stmtConta = $this->db->prepare("
                SELECT
                    payment_date,
                    amount_paid,
                    amount,
                    description,
                    plano_conta_id,
                    centro_custo_id
                FROM contas_pagar
                WHERE id = :id AND company_id = :company_id
            ");
            $stmtConta->execute(['id' => $contaPagarId, 'company_id' => $companyId]);
            $conta = $stmtConta->fetch();

            if (!$conta) {
                error_log("Conta a pagar #{$contaPagarId} não encontrada para gerar fluxo de caixa");
                return;
            }

            // Se não tem data de pagamento, não gera fluxo
            if (empty($conta['payment_date'])) {
                error_log("Conta a pagar #{$contaPagarId} sem data de pagamento, não gera fluxo");
                return;
            }

            // Usar amount_paid se disponível, senão usar amount
            $valor = !empty($conta['amount_paid']) && $conta['amount_paid'] > 0 ? $conta['amount_paid'] : $conta['amount'];

            if ($valor <= 0) {
                error_log("Conta a pagar #{$contaPagarId} sem valor, não gera fluxo");
                return;
            }

            // Verificar se já existe lançamento no fluxo para esta conta
            $stmtCheck = $this->db->prepare("
                SELECT id
                FROM fluxo_caixa
                WHERE reference_type = 'contas_pagar'
                  AND reference_id = :reference_id
                  AND company_id = :company_id
            ");
            $stmtCheck->execute([
                'reference_id' => $contaPagarId,
                'company_id' => $companyId
            ]);

            if ($stmtCheck->fetch()) {
                // Já existe lançamento, não cria duplicado
                return;
            }

            // Calcular saldo atual
            $stmtSaldo = $this->db->prepare("
                SELECT balance FROM fluxo_caixa
                WHERE company_id = :company_id
                ORDER BY date DESC, id DESC
                LIMIT 1
            ");
            $stmtSaldo->execute(['company_id' => $companyId]);
            $ultimoSaldo = $stmtSaldo->fetchColumn() ?: 0;

            $novoSaldo = $ultimoSaldo - $valor;

            // Inserir no fluxo de caixa
            $stmtInsert = $this->db->prepare("
                INSERT INTO fluxo_caixa (
                    company_id,
                    date,
                    type,
                    category,
                    plano_contas_id,
                    centro_custo_id,
                    description,
                    amount,
                    balance,
                    reference_type,
                    reference_id,
                    created_at
                ) VALUES (
                    :company_id,
                    :date,
                    :type,
                    :category,
                    :plano_contas_id,
                    :centro_custo_id,
                    :description,
                    :amount,
                    :balance,
                    :reference_type,
                    :reference_id,
                    NOW()
                )
            ");

            $stmtInsert->execute([
                'company_id' => $companyId,
                'date' => $conta['payment_date'],
                'type' => 'saida',
                'category' => 'Contas a Pagar',
                'plano_contas_id' => $conta['plano_conta_id'] ?: null,
                'centro_custo_id' => $conta['centro_custo_id'] ?: null,
                'description' => $conta['description'] ?? 'Conta a pagar #' . $contaPagarId,
                'amount' => $valor,
                'balance' => $novoSaldo,
                'reference_type' => 'contas_pagar',
                'reference_id' => $contaPagarId
            ]);

        } catch (Exception $e) {
            error_log("Erro ao gerar fluxo de caixa para conta a pagar #{$contaPagarId}: " . $e->getMessage());
            // Não propaga o erro para não interromper o fluxo principal
        }
    }

    private function getConta(int $id): ?array
    {
        $stmt = $this->db->prepare("SELECT * FROM contas_pagar WHERE id = :id AND company_id = :company_id");
        $stmt->execute(['id' => $id, 'company_id' => $this->getCompanyId()]);
        return $stmt->fetch() ?: null;
    }

    /**
     * Busca métodos de pagamento
     */
    private function getMetodosPagamento(): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT id, name, type
                FROM metodos_pagamento
                WHERE company_id = :company_id AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $this->getCompanyId()]);
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar métodos de pagamento: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Busca contas bancárias
     */
    private function getContasBancarias(): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT id, bank_name, agency, account_number, account_type
                FROM contas_bancarias
                WHERE company_id = :company_id AND is_active = 1
                ORDER BY bank_name ASC, agency ASC
            ");
            $stmt->execute(['company_id' => $this->getCompanyId()]);
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar contas bancárias: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Busca plano de contas
     */
    private function getPlanoContas(): array
    {
        try {
            // Detectar estrutura da tabela
            $stmtColumns = $this->db->query("SHOW COLUMNS FROM plano_contas");
            $columns = $stmtColumns->fetchAll();
            $columnNames = array_column($columns, 'Field');

            // Detectar nome da coluna de código
            $colCodigo = in_array('codigo', $columnNames) ? 'codigo' : (in_array('code', $columnNames) ? 'code' : 'id');

            // Detectar nome da coluna de nome
            $colNome = in_array('nome', $columnNames) ? 'nome' : (in_array('name', $columnNames) ? 'name' : 'id');

            // Detectar coluna ativo
            $colAtivo = in_array('ativo', $columnNames) ? 'ativo' : (in_array('is_active', $columnNames) ? 'is_active' : null);

            // Montar WHERE
            $where = "company_id = :company_id";
            if ($colAtivo) {
                $where .= " AND {$colAtivo} = 1";
            }

            $sql = "SELECT id, {$colCodigo} as codigo, {$colNome} as nome FROM plano_contas WHERE {$where} ORDER BY {$colCodigo} ASC";

            $stmt = $this->db->prepare($sql);
            $stmt->execute(['company_id' => $this->getCompanyId()]);
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar plano de contas: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Busca centros de custo para select
     */
    private function getCentroCustos(): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT id, code, name
                FROM centro_custos
                WHERE company_id = :company_id AND is_active = 1
                ORDER BY code ASC
            ");
            $stmt->execute(['company_id' => $this->getCompanyId()]);
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar centros de custo: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Insere lançamento no fluxo de caixa (similar ao EntradasController)
     */
    private function inserirFluxoCaixa(array $conta, string $tipo = 'saida'): void
    {
        try {
            $companyId = $this->getCompanyId();
            $userId = $this->session->get('user')['id'] ?? null;

            // Verificar se já existe lançamento para esta conta a pagar
            $stmtCheck = $this->db->prepare("
                SELECT id FROM fluxo_caixa
                WHERE reference_type = 'contas_pagar'
                AND reference_id = :reference_id
                AND company_id = :company_id
            ");
            $stmtCheck->execute([
                'reference_id' => $conta['id'],
                'company_id' => $companyId
            ]);

            if ($stmtCheck->fetch()) {
                error_log("[SaidasController] Lançamento de fluxo de caixa já existe para conta ID: {$conta['id']}");
                return; // Já existe lançamento, não criar duplicado
            }

            // Buscar valores da conta
            $peopleId = $conta['pessoa_id'] ?? $conta['supplier_id'] ?? null;
            $amount = (float) ($conta['amount'] ?? $conta['valor'] ?? 0);
            $description = $conta['description'] ?? $conta['descricao'] ?? 'Pagamento de conta';
            $planoContasId = $conta['plano_conta_id'] ?? $conta['plano_contas_id'] ?? null;
            $centroCustoId = $conta['centro_custo_id'] ?? null;
            $paymentDate = $conta['payment_date'] ?? date('Y-m-d');

            // Usar amount_paid se disponível, senão usar amount
            $valor = !empty($conta['amount_paid']) && $conta['amount_paid'] > 0 ? $conta['amount_paid'] : $amount;

            if ($valor <= 0) {
                error_log("[SaidasController] Conta a pagar #{$conta['id']} sem valor, não gera fluxo");
                return;
            }

            // Calcular saldo atual (último saldo do fluxo de caixa)
            $stmtSaldo = $this->db->prepare("
                SELECT balance FROM fluxo_caixa
                WHERE company_id = :company_id
                ORDER BY date DESC, id DESC
                LIMIT 1
            ");
            $stmtSaldo->execute(['company_id' => $companyId]);
            $ultimoSaldo = (float) ($stmtSaldo->fetchColumn() ?: 0);

            // Calcular novo saldo (saída diminui o saldo)
            $novoSaldo = $ultimoSaldo - $valor;

            // Inserir no fluxo de caixa
            $stmt = $this->db->prepare("
                INSERT INTO fluxo_caixa (
                    people_id,
                    responsible_id,
                    company_id,
                    date,
                    type,
                    category,
                    plano_contas_id,
                    centro_custo_id,
                    description,
                    amount,
                    balance,
                    reference_type,
                    reference_id,
                    created_at
                ) VALUES (
                    :people_id,
                    :responsible_id,
                    :company_id,
                    :date,
                    :type,
                    :category,
                    :plano_contas_id,
                    :centro_custo_id,
                    :description,
                    :amount,
                    :balance,
                    'contas_pagar',
                    :reference_id,
                    NOW()
                )
            ");

            $stmt->execute([
                'people_id' => $peopleId,
                'responsible_id' => $userId,
                'company_id' => $companyId,
                'date' => $paymentDate,
                'type' => $tipo,
                'category' => 'Pagamento',
                'plano_contas_id' => $planoContasId,
                'centro_custo_id' => $centroCustoId,
                'description' => $description,
                'amount' => $valor,
                'balance' => $novoSaldo,
                'reference_id' => $conta['id']
            ]);

            error_log("[SaidasController] Fluxo de caixa inserido - Tipo: {$tipo}, Valor: {$valor}, Saldo: {$novoSaldo}, Conta ID: {$conta['id']}");

        } catch (Exception $e) {
            error_log("Erro ao inserir fluxo de caixa: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());
            // Não lança exceção para não interromper o processo principal
        }
    }

    /**
     * Borderô de Pagamentos
     */
    public function bordero(): void
    {
        if (!$this->canView('saidas')) {
            $this->response->forbidden('Você não tem permissão para visualizar borderô de pagamentos.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();

            // Verificar estrutura da tabela
            $stmtCols = $this->db->query("SHOW COLUMNS FROM contas_pagar");
            $colunas = $stmtCols->fetchAll(\PDO::FETCH_COLUMN, 0);
            $temPessoaId = in_array('pessoa_id', $colunas ?? [], true);
            $temSupplierId = in_array('supplier_id', $colunas ?? [], true);
            $campoJoin = $temPessoaId ? 'pessoa_id' : ($temSupplierId ? 'supplier_id' : null);

            // Preparar JOIN com pessoas
            $selectFornecedor = '';
            $joinFornecedor = '';
            if ($campoJoin) {
                $selectFornecedor = ', p.name as supplier_name, p.document as supplier_document';
                $joinFornecedor = "LEFT JOIN pessoas p ON cp.{$campoJoin} = p.id";
            }

            // Buscar contas pendentes para o borderô
            $stmt = $this->db->prepare("
                SELECT cp.*
                {$selectFornecedor}
                FROM contas_pagar cp
                {$joinFornecedor}
                WHERE cp.company_id = :company_id
                AND cp.status IN ('pendente', 'pago_parcial', 'vencido')
                ORDER BY cp.due_date ASC, cp.id DESC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $contas = $stmt->fetchAll();

            $this->view('saidas/bordero', [
                'contas' => $contas,
                'pageTitle' => 'Borderô de Pagamentos',
                'activeMenu' => 'saidas'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao carregar borderô: " . $e->getMessage());
            $this->error('Erro ao carregar borderô de pagamentos');
        }
    }

    /**
     * Impressão do Borderô de Pagamentos
     */
    public function borderoPrint(): void
    {
        if (!$this->canView('saidas')) {
            $this->response->forbidden('Você não tem permissão para visualizar borderô de pagamentos.');
            return;
        }

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

            if (empty($ids)) {
                echo "Nenhuma conta selecionada para impressão.";
                return;
            }

            // Converter string de IDs em array
            $idsArray = is_array($ids) ? $ids : explode(',', $ids);
            $idsArray = array_map('intval', array_filter($idsArray));

            if (empty($idsArray)) {
                echo "IDs inválidos para impressão.";
                return;
            }

            // Buscar dados da empresa
            $stmt = $this->db->prepare("SELECT * FROM empresas WHERE id = :id LIMIT 1");
            $stmt->execute(['id' => $companyId]);
            $empresa = $stmt->fetch();

            if (!$empresa) {
                $empresa = [];
            }

            // Verificar estrutura da tabela
            $stmtCols = $this->db->query("SHOW COLUMNS FROM contas_pagar");
            $colunas = $stmtCols->fetchAll(\PDO::FETCH_COLUMN, 0);
            $temPessoaId = in_array('pessoa_id', $colunas ?? [], true);
            $temSupplierId = in_array('supplier_id', $colunas ?? [], true);
            $campoJoin = $temPessoaId ? 'pessoa_id' : ($temSupplierId ? 'supplier_id' : null);

            // Preparar JOIN com pessoas
            $selectFornecedor = '';
            $joinFornecedor = '';
            if ($campoJoin) {
                $selectFornecedor = ', p.name as supplier_name, p.document as supplier_document, p.trade_name as supplier_trade_name, p.email as supplier_email, p.mobile as supplier_mobile, p.phone as supplier_phone, p.address as supplier_address, p.numero as supplier_numero, p.complemento as supplier_complemento, p.bairro as supplier_bairro, p.city as supplier_city, p.state as supplier_state, p.zip_code as supplier_zip_code';
                $joinFornecedor = "LEFT JOIN pessoas p ON cp.{$campoJoin} = p.id";
            }

            // Placeholders para IN clause
            $placeholders = implode(',', array_fill(0, count($idsArray), '?'));

            // Buscar contas selecionadas
            $stmt = $this->db->prepare("
                SELECT cp.*
                {$selectFornecedor}
                FROM contas_pagar cp
                {$joinFornecedor}
                WHERE cp.company_id = ? AND cp.id IN ({$placeholders})
                ORDER BY cp.due_date ASC, cp.id ASC
            ");
            $stmt->execute(array_merge([$companyId], $idsArray));
            $contas = $stmt->fetchAll();

            if (empty($contas)) {
                echo "Nenhuma conta encontrada para impressão.";
                return;
            }

            // Calcular totais
            $totalGeral = 0;
            foreach ($contas as $conta) {
                $totalGeral += (float)($conta['amount'] ?? 0);
            }

            // Renderizar view de impressão
            include ROOT_PATH . '/views/saidas/bordero-print.php';

        } catch (Exception $e) {
            error_log("Erro ao imprimir borderô: " . $e->getMessage());
            echo "Erro ao gerar impressão: " . $e->getMessage();
        }
    }

    /**
     * Provisionamento
     */
    public function provisionamento(): void
    {
        if (!$this->canView('saidas')) {
            $this->response->forbidden('Você não tem permissão para visualizar provisionamento.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();

            // Verificar estrutura da tabela
            $stmtCols = $this->db->query("SHOW COLUMNS FROM contas_pagar");
            $colunas = $stmtCols->fetchAll(\PDO::FETCH_COLUMN, 0);
            $temPessoaId = in_array('pessoa_id', $colunas ?? [], true);
            $temSupplierId = in_array('supplier_id', $colunas ?? [], true);
            $campoJoin = $temPessoaId ? 'pessoa_id' : ($temSupplierId ? 'supplier_id' : null);

            // Preparar JOIN com pessoas
            $selectFornecedor = '';
            $joinFornecedor = '';
            if ($campoJoin) {
                $selectFornecedor = ', p.name as supplier_name, p.document as supplier_document';
                $joinFornecedor = "LEFT JOIN pessoas p ON cp.{$campoJoin} = p.id";
            }

            // Buscar contas futuras para provisionamento
            $dataInicio = $this->request->get('data_inicio') ?: date('Y-m-01');
            $dataFim = $this->request->get('data_fim') ?: date('Y-m-t');

            $stmt = $this->db->prepare("
                SELECT cp.*
                {$selectFornecedor}
                FROM contas_pagar cp
                {$joinFornecedor}
                WHERE cp.company_id = :company_id
                AND cp.due_date BETWEEN :data_inicio AND :data_fim
                AND cp.status != 'cancelado'
                ORDER BY cp.due_date ASC, cp.id DESC
            ");
            $stmt->execute([
                'company_id' => $companyId,
                'data_inicio' => $dataInicio,
                'data_fim' => $dataFim
            ]);
            $contas = $stmt->fetchAll();

            // Agrupar por data
            $contasPorData = [];
            foreach ($contas as $conta) {
                $data = date('Y-m-d', strtotime($conta['due_date']));
                if (!isset($contasPorData[$data])) {
                    $contasPorData[$data] = [];
                }
                $contasPorData[$data][] = $conta;
            }
            ksort($contasPorData);

            $this->view('saidas/provisionamento', [
                'contas' => $contas,
                'contasPorData' => $contasPorData,
                'dataInicio' => $dataInicio,
                'dataFim' => $dataFim,
                'pageTitle' => 'Provisionamento',
                'activeMenu' => 'saidas'
            ]);

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

    /**
     * Folha de Pagamento
     */
    public function folhaPagamento(): void
    {
        if (!$this->canView('saidas')) {
            $this->response->forbidden('Você não tem permissão para visualizar folha de pagamento.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();

            // Verificar se tabela pessoas tem campo tipo_funcionario
            $temTipoFuncionario = false;
            try {
                $stmtPessoasCols = $this->db->query("SHOW COLUMNS FROM pessoas LIKE 'tipo_funcionario'");
                $temTipoFuncionario = $stmtPessoasCols->rowCount() > 0;
            } catch (Exception $e) {
                $temTipoFuncionario = false;
            }

            // Buscar funcionários (pessoas do tipo funcionário)
            if ($temTipoFuncionario) {
                $stmt = $this->db->prepare("
                    SELECT id, name, document, phone, email, salary, admission_date
                    FROM pessoas
                    WHERE company_id = :company_id
                    AND tipo_funcionario = 1
                    ORDER BY name ASC
                ");
            } else {
                // Se não tem campo tipo_funcionario, buscar todas as pessoas (fallback)
                $stmt = $this->db->prepare("
                    SELECT id, name, document, phone, email,
                           COALESCE(salary, 0) as salary,
                           admission_date
                    FROM pessoas
                    WHERE company_id = :company_id
                    ORDER BY name ASC
                    LIMIT 100
                ");
            }
            $stmt->execute(['company_id' => $companyId]);
            $funcionarios = $stmt->fetchAll();

            // Verificar estrutura da tabela
            $stmtCols = $this->db->query("SHOW COLUMNS FROM contas_pagar");
            $colunas = $stmtCols->fetchAll(\PDO::FETCH_COLUMN, 0);
            $temPessoaId = in_array('pessoa_id', $colunas ?? [], true);
            $temSupplierId = in_array('supplier_id', $colunas ?? [], true);
            $campoJoin = $temPessoaId ? 'pessoa_id' : ($temSupplierId ? 'supplier_id' : null);

            // Verificar se tabela pessoas tem campo tipo_funcionario
            $temTipoFuncionario = false;
            try {
                $stmtPessoasCols = $this->db->query("SHOW COLUMNS FROM pessoas LIKE 'tipo_funcionario'");
                $temTipoFuncionario = $stmtPessoasCols->rowCount() > 0;
            } catch (Exception $e) {
                $temTipoFuncionario = false;
            }

            // Preparar JOIN com pessoas
            $selectFornecedor = '';
            $joinFornecedor = '';
            if ($campoJoin) {
                $selectFornecedor = ', p.name as supplier_name, p.document as supplier_document';
                $joinFornecedor = "LEFT JOIN pessoas p ON cp.{$campoJoin} = p.id";
            }

            // Buscar contas relacionadas a funcionários (folha de pagamento)
            $mes = $this->request->get('mes') ?: date('Y-m');
            $dataInicio = $mes . '-01';
            $dataFim = date('Y-m-t', strtotime($dataInicio));

            $whereTipo = '';
            if ($temTipoFuncionario && $campoJoin) {
                $whereTipo = "AND (p.tipo_funcionario = 1 OR cp.description LIKE '%folha%' OR cp.description LIKE '%salário%' OR cp.description LIKE '%salario%')";
            } else {
                $whereTipo = "AND (cp.description LIKE '%folha%' OR cp.description LIKE '%salário%' OR cp.description LIKE '%salario%')";
            }

            $stmt = $this->db->prepare("
                SELECT cp.*
                {$selectFornecedor}
                FROM contas_pagar cp
                {$joinFornecedor}
                WHERE cp.company_id = :company_id
                AND cp.due_date BETWEEN :data_inicio AND :data_fim
                {$whereTipo}
                ORDER BY cp.due_date ASC
            ");
            $stmt->execute([
                'company_id' => $companyId,
                'data_inicio' => $dataInicio,
                'data_fim' => $dataFim
            ]);
            $contasFolha = $stmt->fetchAll();

            $this->view('saidas/folha-pagamento', [
                'funcionarios' => $funcionarios,
                'contasFolha' => $contasFolha,
                'mes' => $mes,
                'dataInicio' => $dataInicio,
                'dataFim' => $dataFim,
                'pageTitle' => 'Folha de Pagamento',
                'activeMenu' => 'saidas'
            ]);

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