<?php

declare(strict_types=1);

namespace App\Controllers;

use Exception;
use App\Helpers\UrlHelper;

class TransferenciaEstoqueController extends BaseController
{
    public function index(): void
    {
        // Verificar permissão de visualização
        if (!$this->canView('transferencia-estoque')) {
            $this->response->forbidden('Você não tem permissão para visualizar transferências de estoque.');
            return;
        }

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

            // Criar tabelas se não existirem
            $this->criarTabelaTransferencias();

            // Verificar se colunas de empresa existem
            $stmt = $this->db->query("SHOW COLUMNS FROM transferencias_estoque LIKE 'empresa_origem_id'");
            $temColunasEmpresa = $stmt->rowCount() > 0;

            // Buscar transferências
            if ($temColunasEmpresa) {
                $query = "
                    SELECT
                        t.id,
                        t.data_transferencia,
                        t.numero,
                        t.observacoes,
                        lo.name as local_origem_nome,
                        ld.name as local_destino_nome,
                        eo.razao_social as empresa_origem_nome,
                        ed.razao_social as empresa_destino_nome,
                        u.name as usuario_nome,
                        COUNT(ti.id) as total_itens
                    FROM transferencias_estoque t
                    LEFT JOIN locais_estoque lo ON t.local_origem_id = lo.id
                    LEFT JOIN locais_estoque ld ON t.local_destino_id = ld.id
                    LEFT JOIN empresas eo ON t.empresa_origem_id = eo.id
                    LEFT JOIN empresas ed ON t.empresa_destino_id = ed.id
                    LEFT JOIN users u ON t.created_by = u.id
                    LEFT JOIN transferencias_estoque_itens ti ON t.id = ti.transferencia_id
                    WHERE t.company_id = :company_id
                ";
            } else {
                $query = "
                    SELECT
                        t.id,
                        t.data_transferencia,
                        t.numero,
                        t.observacoes,
                        lo.name as local_origem_nome,
                        ld.name as local_destino_nome,
                        u.name as usuario_nome,
                        COUNT(ti.id) as total_itens
                    FROM transferencias_estoque t
                    LEFT JOIN locais_estoque lo ON t.local_origem_id = lo.id
                    LEFT JOIN locais_estoque ld ON t.local_destino_id = ld.id
                    LEFT JOIN users u ON t.created_by = u.id
                    LEFT JOIN transferencias_estoque_itens ti ON t.id = ti.transferencia_id
                    WHERE t.company_id = :company_id
                ";
            }

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

            if (!empty($search)) {
                if ($temColunasEmpresa) {
                    $query .= " AND (t.numero LIKE :search OR t.observacoes LIKE :search OR lo.name LIKE :search OR ld.name LIKE :search OR eo.razao_social LIKE :search OR ed.razao_social LIKE :search)";
                } else {
                    $query .= " AND (t.numero LIKE :search OR t.observacoes LIKE :search OR lo.name LIKE :search OR ld.name LIKE :search)";
                }
                $params['search'] = "%{$search}%";
            }

            $query .= " GROUP BY t.id ORDER BY t.data_transferencia DESC, t.id DESC";

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

            $this->view('transferencia-estoque/index', [
                'transferencias' => $transferencias,
                'search' => $search,
                'pageTitle' => 'Transferências de Estoque',
                'activeMenu' => 'estoque'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao carregar transferências: " . $e->getMessage());
            $this->error('Erro ao carregar transferências de estoque');
        }
    }

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

            // Criar tabelas se não existirem
            $this->criarTabelaTransferencias();

            // Buscar locais de estoque
            $stmt = $this->db->prepare("
                SELECT * FROM locais_estoque
                WHERE company_id = :company_id AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $locais = $stmt->fetchAll();

            // Buscar produtos/itens
            $produtos = $this->getProdutos($companyId);

            // Gerar próximo número
            $proximoNumero = $this->getProximoNumero($companyId);

            // Buscar empresas vinculadas ao usuário
            $empresasVinculadas = $this->getEmpresasVinculadasUsuario();

            // Verificar se controle de lote está ativo
            $usarLoteEstoque = false;
            try {
                // Tentar buscar com empresa_id primeiro
                $stmt = $this->db->prepare("
                    SELECT valor FROM parametros
                    WHERE chave = 'usar_lote_estoque' AND empresa_id = :empresa_id
                    LIMIT 1
                ");
                $stmt->execute(['empresa_id' => $companyId]);
                $result = $stmt->fetch();

                if ($result && ((int) $result['valor'] === 1 || $result['valor'] === '1')) {
                    $usarLoteEstoque = true;
                } else {
                    // Tentar buscar sem empresa_id (parâmetro global)
                    $stmt = $this->db->prepare("
                        SELECT valor FROM parametros
                        WHERE chave = 'usar_lote_estoque' AND (empresa_id IS NULL OR empresa_id = 0)
                        LIMIT 1
                    ");
                    $stmt->execute();
                    $result = $stmt->fetch();
                    $usarLoteEstoque = ($result && ((int) $result['valor'] === 1 || $result['valor'] === '1'));
                }
            } catch (Exception $e) {
                error_log("Erro ao verificar usar_lote_estoque: " . $e->getMessage());
                $usarLoteEstoque = false;
            }

            $this->view('transferencia-estoque/form', [
                'locais' => $locais,
                'produtos' => $produtos,
                'proximoNumero' => $proximoNumero,
                'empresasVinculadas' => $empresasVinculadas,
                'usarLoteEstoque' => $usarLoteEstoque,
                'pageTitle' => 'Nova Transferência',
                'activeMenu' => 'estoque'
            ]);

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

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

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

            $data = [
                'company_id' => $companyId,
                'numero' => $this->request->post('numero'),
                'data_transferencia' => $this->request->post('data_transferencia') ?: date('Y-m-d'),
                'local_origem_id' => (int) $this->request->post('local_origem_id'),
                'local_destino_id' => (int) $this->request->post('local_destino_id'),
                'empresa_origem_id' => $this->request->post('empresa_origem_id') ? (int) $this->request->post('empresa_origem_id') : null,
                'empresa_destino_id' => $this->request->post('empresa_destino_id') ? (int) $this->request->post('empresa_destino_id') : null,
                'observacoes' => $this->request->post('observacoes') ?: null,
                'created_by' => $userId
            ];

            $itens = json_decode($this->request->post('itens', '[]'), true);

            if (empty($itens)) {
                $this->error('Adicione pelo menos um item à transferência');
                return;
            }

            if ($data['local_origem_id'] === $data['local_destino_id']) {
                $this->error('O local de origem e destino não podem ser iguais');
                return;
            }

            $this->db->beginTransaction();

            // Criar tabela se não existir
            $this->criarTabelaTransferencias();

            // Verificar se colunas de empresa existem
            $stmt = $this->db->query("SHOW COLUMNS FROM transferencias_estoque LIKE 'empresa_origem_id'");
            $temColunasEmpresa = $stmt->rowCount() > 0;

            // Inserir transferência
            if ($temColunasEmpresa) {
                $stmt = $this->db->prepare("
                    INSERT INTO transferencias_estoque (
                        company_id, numero, data_transferencia, local_origem_id,
                        local_destino_id, empresa_origem_id, empresa_destino_id,
                        observacoes, created_by, created_at, updated_at
                    ) VALUES (
                        :company_id, :numero, :data_transferencia, :local_origem_id,
                        :local_destino_id, :empresa_origem_id, :empresa_destino_id,
                        :observacoes, :created_by, NOW(), NOW()
                    )
                ");
            } else {
                $stmt = $this->db->prepare("
                    INSERT INTO transferencias_estoque (
                        company_id, numero, data_transferencia, local_origem_id,
                        local_destino_id, observacoes, created_by, created_at, updated_at
                    ) VALUES (
                        :company_id, :numero, :data_transferencia, :local_origem_id,
                        :local_destino_id, :observacoes, :created_by, NOW(), NOW()
                    )
                ");
            }
            $stmt->execute($data);
            $transferenciaId = (int) $this->db->lastInsertId();

            // Inserir itens e movimentar estoque
            foreach ($itens as $item) {
                $itemId = (int) ($item['item_id'] ?? $item['product_id'] ?? 0);
                $quantidade = (float) ($item['quantidade'] ?? 0);

                if ($itemId <= 0 || $quantidade <= 0) {
                    continue;
                }

                // Inserir item da transferência
                $stmtItem = $this->db->prepare("
                    INSERT INTO transferencias_estoque_itens (
                        transferencia_id, item_id, quantidade, observacoes, created_at
                    ) VALUES (
                        :transferencia_id, :item_id, :quantidade, :observacoes, NOW()
                    )
                ");
                $stmtItem->execute([
                    'transferencia_id' => $transferenciaId,
                    'item_id' => $itemId,
                    'quantidade' => $quantidade,
                    'observacoes' => $item['observacoes'] ?? null
                ]);

                // Criar movimentação de saída (origem)
                $this->criarMovimentacao([
                    'company_id' => $companyId,
                    'item_id' => $itemId,
                    'local_estoque_id' => $data['local_origem_id'],
                    'type' => 'saida',
                    'quantity' => $quantidade,
                    'reference_type' => 'transferencia',
                    'reference_id' => $transferenciaId,
                    'reason' => "Transferência #{$data['numero']} - Saída para " . $this->getLocalNome($data['local_destino_id']),
                    'created_by' => $userId
                ]);

                // Criar movimentação de entrada (destino)
                $this->criarMovimentacao([
                    'company_id' => $companyId,
                    'item_id' => $itemId,
                    'local_estoque_id' => $data['local_destino_id'],
                    'type' => 'entrada',
                    'quantity' => $quantidade,
                    'reference_type' => 'transferencia',
                    'reference_id' => $transferenciaId,
                    'reason' => "Transferência #{$data['numero']} - Entrada de " . $this->getLocalNome($data['local_origem_id']),
                    'created_by' => $userId
                ]);
            }

            $this->logActivity('create', 'transferencias_estoque', $transferenciaId, $data);
            $this->db->commit();

            $this->success('Transferência criada com sucesso', [
                'redirect' => UrlHelper::url('/estoque/transferencia')
            ]);

        } catch (Exception $e) {
            $this->db->rollBack();
            error_log("Erro ao criar transferência: " . $e->getMessage());
            $this->error('Erro ao criar transferência: ' . $e->getMessage());
        }
    }

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

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

            // Criar tabelas se não existirem
            $this->criarTabelaTransferencias();

            $transferencia = $this->getTransferencia($id, $companyId);

            if (!$transferencia) {
                $this->response->notFound('Transferência não encontrada');
                return;
            }

            // Buscar locais de estoque
            $stmt = $this->db->prepare("
                SELECT * FROM locais_estoque
                WHERE company_id = :company_id AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $locais = $stmt->fetchAll();

            // Buscar produtos
            $produtos = $this->getProdutos($companyId);

            // Buscar itens da transferência
            $stmt = $this->db->prepare("
                SELECT * FROM transferencias_estoque_itens
                WHERE transferencia_id = :transferencia_id
            ");
            $stmt->execute(['transferencia_id' => $id]);
            $itens = $stmt->fetchAll();

            // Buscar empresas vinculadas ao usuário
            $empresasVinculadas = $this->getEmpresasVinculadasUsuario();

            $this->view('transferencia-estoque/form', [
                'transferencia' => $transferencia,
                'locais' => $locais,
                'produtos' => $produtos,
                'itens' => $itens,
                'empresasVinculadas' => $empresasVinculadas,
                'pageTitle' => 'Editar Transferência',
                'activeMenu' => 'estoque'
            ]);

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

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

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

            // Criar tabelas se não existirem
            $this->criarTabelaTransferencias();

            $transferencia = $this->getTransferencia($id, $companyId);

            if (!$transferencia) {
                $this->error('Transferência não encontrada');
                return;
            }

            // Transferências não podem ser editadas após criação (por segurança)
            // Apenas observações podem ser atualizadas
            $observacoes = $this->request->post('observacoes') ?: null;

            $this->db->beginTransaction();

            $stmt = $this->db->prepare("
                UPDATE transferencias_estoque SET
                    observacoes = :observacoes,
                    updated_at = NOW()
                WHERE id = :id AND company_id = :company_id
            ");
            $stmt->execute([
                'observacoes' => $observacoes,
                'id' => $id,
                'company_id' => $companyId
            ]);

            $this->logActivity('update', 'transferencias_estoque', $id, ['observacoes' => $observacoes]);
            $this->db->commit();

            $this->success('Transferência atualizada com sucesso', [
                'redirect' => UrlHelper::url('/estoque/transferencia')
            ]);

        } catch (Exception $e) {
            $this->db->rollBack();
            error_log("Erro ao atualizar transferência: " . $e->getMessage());
            $this->error('Erro ao atualizar transferência');
        }
    }

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

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

            // Criar tabelas se não existirem
            $this->criarTabelaTransferencias();

            $transferencia = $this->getTransferencia($id, $companyId);

            if (!$transferencia) {
                $this->error('Transferência não encontrada');
                return;
            }

            $this->db->beginTransaction();

            // Deletar movimentações relacionadas
            $stmt = $this->db->prepare("
                DELETE FROM estoque_movimentos
                WHERE reference_type = 'transferencia' AND reference_id = :transferencia_id
            ");
            $stmt->execute(['transferencia_id' => $id]);

            // Deletar itens
            $stmt = $this->db->prepare("
                DELETE FROM transferencias_estoque_itens
                WHERE transferencia_id = :transferencia_id
            ");
            $stmt->execute(['transferencia_id' => $id]);

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

            $this->logActivity('delete', 'transferencias_estoque', $id, $transferencia);
            $this->db->commit();

            $this->success('Transferência excluída com sucesso');

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

    public function visualizar(): void
    {
        try {
            $id = (int) $this->request->get('id');
            $companyId = $this->getCompanyId();

            // Criar tabelas se não existirem
            $this->criarTabelaTransferencias();

            $transferencia = $this->getTransferencia($id, $companyId);

            if (!$transferencia) {
                $this->response->notFound('Transferência não encontrada');
                return;
            }

            // Buscar itens
            $stmt = $this->db->prepare("
                SELECT ti.*,
                       COALESCE(i.name, p.name) as item_nome,
                       COALESCE(i.code, p.code, p.sku) as item_codigo,
                       COALESCE(i.unit, p.unit, 'UN') as item_unidade
                FROM transferencias_estoque_itens ti
                LEFT JOIN itens i ON ti.item_id = i.id
                LEFT JOIN produtos p ON ti.item_id = p.id
                WHERE ti.transferencia_id = :transferencia_id
            ");
            $stmt->execute(['transferencia_id' => $id]);
            $itens = $stmt->fetchAll();

            $this->view('transferencia-estoque/visualizar', [
                'transferencia' => $transferencia,
                'itens' => $itens,
                'pageTitle' => 'Visualizar Transferência',
                'activeMenu' => 'estoque'
            ]);

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

    private function getTransferencia(int $id, int $companyId): ?array
    {
        // Verificar se colunas de empresa existem
        $stmt = $this->db->query("SHOW COLUMNS FROM transferencias_estoque LIKE 'empresa_origem_id'");
        $temColunasEmpresa = $stmt->rowCount() > 0;

        if ($temColunasEmpresa) {
            $stmt = $this->db->prepare("
                    SELECT t.*,
                           lo.name as local_origem_nome,
                           ld.name as local_destino_nome,
                           eo.razao_social as empresa_origem_nome,
                           ed.razao_social as empresa_destino_nome,
                           u.name as usuario_nome
                    FROM transferencias_estoque t
                    LEFT JOIN locais_estoque lo ON t.local_origem_id = lo.id
                    LEFT JOIN locais_estoque ld ON t.local_destino_id = ld.id
                    LEFT JOIN empresas eo ON t.empresa_origem_id = eo.id
                    LEFT JOIN empresas ed ON t.empresa_destino_id = ed.id
                    LEFT JOIN users u ON t.created_by = u.id
                    WHERE t.id = :id AND t.company_id = :company_id
                ");
        } else {
            $stmt = $this->db->prepare("
                    SELECT t.*,
                           lo.name as local_origem_nome,
                           ld.name as local_destino_nome,
                           u.name as usuario_nome
                    FROM transferencias_estoque t
                    LEFT JOIN locais_estoque lo ON t.local_origem_id = lo.id
                    LEFT JOIN locais_estoque ld ON t.local_destino_id = ld.id
                    LEFT JOIN users u ON t.created_by = u.id
                    WHERE t.id = :id AND t.company_id = :company_id
                ");
        }
        $stmt->execute(['id' => $id, 'company_id' => $companyId]);
        return $stmt->fetch() ?: null;
    }

    private function getProdutos(int $companyId): array
    {
        $produtos = [];

        // Tentar buscar de itens
        try {
            $stmt = $this->db->prepare("
                SELECT id, name, code, unit, stock_quantity
                FROM itens
                WHERE company_id = :company_id AND is_active = 1 AND type = 'produto'
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $itens = $stmt->fetchAll();

            foreach ($itens as $item) {
                $produtos[] = [
                    'id' => $item['id'],
                    'name' => $item['name'],
                    'code' => $item['code'] ?? '',
                    'unit' => $item['unit'] ?? 'UN',
                    'stock' => $item['stock_quantity'] ?? 0
                ];
            }
        } catch (Exception $e) {
            // Tabela itens pode não existir
        }

        // Tentar buscar de produtos
        try {
            $stmt = $this->db->prepare("
                SELECT id, name, code, sku, unit,
                       COALESCE(stock_quantity, quantidade, 0) as stock_quantity
                FROM produtos
                WHERE company_id = :company_id AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $prods = $stmt->fetchAll();

            foreach ($prods as $prod) {
                // Evitar duplicatas
                $existe = false;
                foreach ($produtos as $p) {
                    if ($p['id'] == $prod['id']) {
                        $existe = true;
                        break;
                    }
                }

                if (!$existe) {
                    $produtos[] = [
                        'id' => $prod['id'],
                        'name' => $prod['name'],
                        'code' => $prod['code'] ?? $prod['sku'] ?? '',
                        'unit' => $prod['unit'] ?? 'UN',
                        'stock' => $prod['stock_quantity'] ?? 0
                    ];
                }
            }
        } catch (Exception $e) {
            // Tabela produtos pode não existir
        }

        return $produtos;
    }

    private function getProximoNumero(int $companyId): string
    {
        try {
            $stmt = $this->db->prepare("
                SELECT numero FROM transferencias_estoque
                WHERE company_id = :company_id
                ORDER BY id DESC LIMIT 1
            ");
            $stmt->execute(['company_id' => $companyId]);
            $ultimo = $stmt->fetchColumn();

            if ($ultimo) {
                // Extrair número e incrementar
                if (preg_match('/(\d+)$/', $ultimo, $matches)) {
                    $numero = (int) $matches[1] + 1;
                    return 'TRF-' . str_pad((string) $numero, 6, '0', STR_PAD_LEFT);
                }
            }

            return 'TRF-000001';
        } catch (Exception $e) {
            return 'TRF-000001';
        }
    }

    private function getLocalNome(int $localId): string
    {
        try {
            $stmt = $this->db->prepare("SELECT name FROM locais_estoque WHERE id = :id");
            $stmt->execute(['id' => $localId]);
            $local = $stmt->fetch();
            return $local['name'] ?? 'Local Desconhecido';
        } catch (Exception $e) {
            return 'Local Desconhecido';
        }
    }

    private function criarMovimentacao(array $dados): void
    {
        // Verificar estrutura da tabela estoque_movimentos
        $stmt = $this->db->query("SHOW TABLES LIKE 'estoque_movimentos'");
        if ($stmt->rowCount() === 0) {
            return; // Tabela não existe
        }

        // Verificar colunas
        $stmt = $this->db->query("SHOW COLUMNS FROM estoque_movimentos");
        $colunas = $stmt->fetchAll(\PDO::FETCH_COLUMN);

        $campos = [];
        $valores = [];
        $params = [];

        // Campos obrigatórios
        if (in_array('company_id', $colunas)) {
            $campos[] = 'company_id';
            $valores[] = ':company_id';
            $params['company_id'] = $dados['company_id'];
        }

        if (in_array('item_id', $colunas)) {
            $campos[] = 'item_id';
            $valores[] = ':item_id';
            $params['item_id'] = $dados['item_id'];
        } elseif (in_array('product_id', $colunas)) {
            $campos[] = 'product_id';
            $valores[] = ':product_id';
            $params['product_id'] = $dados['item_id'];
        }

        if (in_array('local_estoque_id', $colunas)) {
            $campos[] = 'local_estoque_id';
            $valores[] = ':local_estoque_id';
            $params['local_estoque_id'] = $dados['local_estoque_id'];
        } elseif (in_array('location_id', $colunas)) {
            $campos[] = 'location_id';
            $valores[] = ':location_id';
            $params['location_id'] = $dados['local_estoque_id'];
        }

        if (in_array('type', $colunas)) {
            $campos[] = 'type';
            $valores[] = ':type';
            $params['type'] = $dados['type'];
        }

        if (in_array('quantity', $colunas)) {
            $campos[] = 'quantity';
            $valores[] = ':quantity';
            $params['quantity'] = $dados['quantity'];
        }

        if (in_array('reason', $colunas) && isset($dados['reason'])) {
            $campos[] = 'reason';
            $valores[] = ':reason';
            $params['reason'] = $dados['reason'];
        }

        if (in_array('reference_type', $colunas) && isset($dados['reference_type'])) {
            $campos[] = 'reference_type';
            $valores[] = ':reference_type';
            $params['reference_type'] = $dados['reference_type'];
        }

        if (in_array('reference_id', $colunas) && isset($dados['reference_id'])) {
            $campos[] = 'reference_id';
            $valores[] = ':reference_id';
            $params['reference_id'] = $dados['reference_id'];
        }

        if (in_array('created_by', $colunas) && isset($dados['created_by'])) {
            $campos[] = 'created_by';
            $valores[] = ':created_by';
            $params['created_by'] = $dados['created_by'];
        }

        if (in_array('created_at', $colunas)) {
            $campos[] = 'created_at';
            $valores[] = 'NOW()';
        }

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

    private function criarTabelaTransferencias(): void
    {
        try {
            // Verificar se tabela existe
            $stmt = $this->db->query("SHOW TABLES LIKE 'transferencias_estoque'");
            if ($stmt->rowCount() > 0) {
                return; // Tabela já existe
            }

            // Verificar se tabelas referenciadas existem
            $stmt = $this->db->query("SHOW TABLES LIKE 'companies'");
            $temCompanies = $stmt->rowCount() > 0;

            $stmt = $this->db->query("SHOW TABLES LIKE 'locais_estoque'");
            $temLocaisEstoque = $stmt->rowCount() > 0;

            $stmt = $this->db->query("SHOW TABLES LIKE 'users'");
            $temUsers = $stmt->rowCount() > 0;

            // Verificar se já existem colunas de empresa
            $stmt = $this->db->query("SHOW TABLES LIKE 'transferencias_estoque'");
            $tabelaExiste = $stmt->rowCount() > 0;

            if ($tabelaExiste) {
                // Verificar se as colunas de empresa já existem
                $stmt = $this->db->query("SHOW COLUMNS FROM transferencias_estoque LIKE 'empresa_origem_id'");
                $temEmpresaOrigem = $stmt->rowCount() > 0;

                if (!$temEmpresaOrigem) {
                    // Adicionar colunas de empresa se não existirem
                    try {
                        $this->db->exec("ALTER TABLE `transferencias_estoque` ADD COLUMN `empresa_origem_id` INT UNSIGNED NULL AFTER `local_destino_id`");
                        $this->db->exec("ALTER TABLE `transferencias_estoque` ADD COLUMN `empresa_destino_id` INT UNSIGNED NULL AFTER `empresa_origem_id`");
                        $this->db->exec("ALTER TABLE `transferencias_estoque` ADD INDEX `idx_empresa_origem` (`empresa_origem_id`)");
                        $this->db->exec("ALTER TABLE `transferencias_estoque` ADD INDEX `idx_empresa_destino` (`empresa_destino_id`)");
                    } catch (Exception $e) {
                        error_log("Erro ao adicionar colunas de empresa: " . $e->getMessage());
                    }
                }
            } else {
                // Criar tabela de transferências sem foreign keys primeiro
                $sqlTransferencias = "
                    CREATE TABLE IF NOT EXISTS `transferencias_estoque` (
                        `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                        `company_id` INT UNSIGNED NOT NULL,
                        `numero` VARCHAR(50) NOT NULL,
                        `data_transferencia` DATE NOT NULL,
                        `local_origem_id` INT UNSIGNED NOT NULL,
                        `local_destino_id` INT UNSIGNED NOT NULL,
                        `empresa_origem_id` INT UNSIGNED NULL,
                        `empresa_destino_id` INT UNSIGNED NULL,
                        `observacoes` TEXT NULL,
                        `created_by` INT UNSIGNED NULL,
                        `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
                        `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                        INDEX `idx_company` (`company_id`),
                        INDEX `idx_numero` (`numero`),
                        INDEX `idx_data` (`data_transferencia`),
                        INDEX `idx_origem` (`local_origem_id`),
                        INDEX `idx_destino` (`local_destino_id`),
                        INDEX `idx_empresa_origem` (`empresa_origem_id`),
                        INDEX `idx_empresa_destino` (`empresa_destino_id`)
                    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
                ";

                $this->db->exec($sqlTransferencias);
            }

            // Adicionar foreign keys se as tabelas existirem
            if ($temCompanies) {
                try {
                    $this->db->exec("ALTER TABLE `transferencias_estoque` ADD CONSTRAINT `fk_transferencias_company` FOREIGN KEY (`company_id`) REFERENCES `companies`(`id`) ON DELETE CASCADE");
                } catch (Exception $e) {
                    // Ignorar se já existe
                }
            }

            if ($temLocaisEstoque) {
                try {
                    $this->db->exec("ALTER TABLE `transferencias_estoque` ADD CONSTRAINT `fk_transferencias_origem` FOREIGN KEY (`local_origem_id`) REFERENCES `locais_estoque`(`id`) ON DELETE RESTRICT");
                } catch (Exception $e) {
                    // Ignorar se já existe
                }
                try {
                    $this->db->exec("ALTER TABLE `transferencias_estoque` ADD CONSTRAINT `fk_transferencias_destino` FOREIGN KEY (`local_destino_id`) REFERENCES `locais_estoque`(`id`) ON DELETE RESTRICT");
                } catch (Exception $e) {
                    // Ignorar se já existe
                }
            }

            if ($temUsers) {
                try {
                    $this->db->exec("ALTER TABLE `transferencias_estoque` ADD CONSTRAINT `fk_transferencias_user` FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE SET NULL");
                } catch (Exception $e) {
                    // Ignorar se já existe
                }
            }

            // Criar tabela de itens da transferência
            $sqlItens = "
                CREATE TABLE IF NOT EXISTS `transferencias_estoque_itens` (
                    `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
                    `transferencia_id` INT UNSIGNED NOT NULL,
                    `item_id` INT UNSIGNED NOT NULL,
                    `quantidade` DECIMAL(15,3) NOT NULL,
                    `observacoes` TEXT NULL,
                    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
                    INDEX `idx_transferencia` (`transferencia_id`),
                    INDEX `idx_item` (`item_id`)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
            ";

            $this->db->exec($sqlItens);

            // Adicionar foreign key para transferencia_id
            try {
                $this->db->exec("ALTER TABLE `transferencias_estoque_itens` ADD CONSTRAINT `fk_transferencias_itens` FOREIGN KEY (`transferencia_id`) REFERENCES `transferencias_estoque`(`id`) ON DELETE CASCADE");
            } catch (Exception $e) {
                // Ignorar se já existe
            }

        } catch (Exception $e) {
            error_log("Erro ao criar tabelas de transferência: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());
            // Não lançar exceção, apenas logar
        }
    }

    /**
     * Busca empresas vinculadas ao usuário logado
     * Retorna apenas as empresas vinculadas através da tabela empresas_users
     */
    private function getEmpresasVinculadasUsuario(): array
    {
        try {
            $userId = $this->getUserId();

            if (!$userId) {
                error_log("TransferenciaEstoque: Usuário não logado");
                return [];
            }

            // Verificar se a tabela empresas existe
            $stmt = $this->db->query("SHOW TABLES LIKE 'empresas'");
            if ($stmt->rowCount() === 0) {
                error_log("TransferenciaEstoque: Tabela 'empresas' não existe");
                return [];
            }

            // Verificar se a tabela empresas_users existe
            $stmt = $this->db->query("SHOW TABLES LIKE 'empresas_users'");
            $temTabelaEmpresasUsers = $stmt->rowCount() > 0;

            // Verificar se existe coluna 'ativo' ou 'status' na tabela empresas
            $stmtCheck = $this->db->query("SHOW COLUMNS FROM empresas LIKE 'ativo'");
            $temColunaAtivo = $stmtCheck->rowCount() > 0;

            $stmtCheck = $this->db->query("SHOW COLUMNS FROM empresas LIKE 'status'");
            $temColunaStatus = $stmtCheck->rowCount() > 0;

            if ($temTabelaEmpresasUsers) {
                // Buscar empresas vinculadas ao usuário através de empresas_users
                $query = "
                    SELECT DISTINCT e.id, e.razao_social, e.nome_fantasia, e.cnpj
                    FROM empresas e
                    INNER JOIN empresas_users eu ON e.id = eu.empresa_id
                    WHERE eu.user_id = :user_id
                ";

                // Adicionar filtro de ativo se existir
                if ($temColunaAtivo) {
                    $query .= " AND (e.ativo = 'Sim' OR e.ativo = 1 OR e.ativo = '1')";
                } elseif ($temColunaStatus) {
                    $query .= " AND (e.status = 'ativo' OR e.status = 1 OR e.status = '1')";
                }

                $query .= " ORDER BY e.razao_social ASC";

                $stmt = $this->db->prepare($query);
                $stmt->execute(['user_id' => $userId]);
                return $stmt->fetchAll();
            } else {
                // Se não existe tabela empresas_users, buscar todas as empresas (comportamento antigo)
                $query = "
                    SELECT id, razao_social, nome_fantasia, cnpj
                    FROM empresas
                ";

                // Adicionar filtro se existir coluna ativo ou status
                if ($temColunaAtivo) {
                    $query .= " WHERE ativo = 'Sim' OR ativo = 1 OR ativo = '1'";
                } elseif ($temColunaStatus) {
                    $query .= " WHERE status = 'ativo' OR status = 1 OR status = '1'";
                }

                $query .= " ORDER BY razao_social ASC";

                $stmt = $this->db->prepare($query);
                $stmt->execute();
                return $stmt->fetchAll();
            }
        } catch (Exception $e) {
            error_log("Erro ao buscar empresas vinculadas ao usuário: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Busca produtos para autocomplete - retorna TODOS os produtos (igual vendas)
     */
    public function buscarProdutos(): void
    {
        try {
            $companyId = $this->getCompanyId();

            // Consultar APENAS tabela produtos (igual vendas)
            $stmt = $this->db->prepare("
                SELECT
                    id,
                    name,
                    sku,
                    COALESCE(sku) as code,
                    COALESCE(unit, 'UN') as unit,
                    COALESCE(stock_quantity, 0) as stock_quantity
                FROM produtos
                WHERE company_id = :company_id
                  AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute([
                'company_id' => $companyId
            ]);

            $produtos = [];
            $resultados = $stmt->fetchAll();

            foreach ($resultados as $prod) {
                $produtos[] = [
                    'id' => (int) ($prod['id'] ?? 0),
                    'name' => $prod['name'] ?? '',
                    'sku' => $prod['sku'] ?? '',
                    'code' => $prod['code'] ?? $prod['sku'] ?? '',
                    'unit' => $prod['unit'] ?? 'UN',
                    'stock_quantity' => (float) ($prod['stock_quantity'] ?? 0)
                ];
            }

            $this->success('Produtos carregados', [
                'produtos' => $produtos
            ]);
        } catch (Exception $e) {
            error_log('Transferência: falha ao buscar produtos: ' . $e->getMessage());
            error_log('Stack trace: ' . $e->getTraceAsString());
            $this->error('Erro ao buscar produtos.');
        }
    }

    /**
     * Busca lotes de um produto
     */
    public function buscarLotesProduto(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $produtoId = (int) $this->request->get('produto_id', 0);
            $localId = (int) $this->request->get('local_id', 0);

            if ($produtoId <= 0) {
                $this->success('Lotes carregados', [
                    'lotes' => []
                ]);
                return;
            }

            $lotes = [];

            // Verificar se a tabela estoque_movimentos existe
            try {
                $stmt = $this->db->query("SHOW TABLES LIKE 'estoque_movimentos'");
                if ($stmt->rowCount() === 0) {
                    $this->success('Lotes carregados', ['lotes' => []]);
                    return;
                }

                // Verificar colunas disponíveis
                $stmt = $this->db->query("SHOW COLUMNS FROM estoque_movimentos");
                $colunas = $stmt->fetchAll(\PDO::FETCH_COLUMN);
                $temColunaLote = in_array('lote', $colunas);
                $temItemId = in_array('item_id', $colunas);
                $temProductId = in_array('product_id', $colunas);

                if ($temColunaLote) {
                    // Montar condição para item_id ou product_id
                    $condicaoProduto = '';
                    if ($temItemId && $temProductId) {
                        $condicaoProduto = '(item_id = :produto_id OR product_id = :produto_id)';
                    } elseif ($temItemId) {
                        $condicaoProduto = 'item_id = :produto_id';
                    } elseif ($temProductId) {
                        $condicaoProduto = 'product_id = :produto_id';
                    } else {
                        $this->success('Lotes carregados', ['lotes' => []]);
                        return;
                    }

                    // Buscar lotes com estoque disponível
                    $query = "
                        SELECT
                            lote,
                            COALESCE(SUM(CASE WHEN type = 'entrada' THEN quantity ELSE -quantity END), 0) as quantidade
                    ";

                    // Adicionar fabricacao e validade se existirem
                    if (in_array('fabricacao', $colunas)) {
                        $query .= ", MIN(fabricacao) as fabricacao";
                    } else {
                        $query .= ", NULL as fabricacao";
                    }

                    if (in_array('validade', $colunas)) {
                        $query .= ", MIN(validade) as validade";
                    } else {
                        $query .= ", NULL as validade";
                    }

                    $query .= "
                        FROM estoque_movimentos
                        WHERE company_id = :company_id
                          AND {$condicaoProduto}
                    ";

                    $params = [
                        'company_id' => $companyId,
                        'produto_id' => $produtoId
                    ];

                    if ($localId > 0 && in_array('local_estoque_id', $colunas)) {
                        $query .= " AND local_estoque_id = :local_id";
                        $params['local_id'] = $localId;
                    }

                    $query .= " GROUP BY lote HAVING quantidade > 0";
                    if (in_array('validade', $colunas)) {
                        $query .= " ORDER BY validade ASC, lote ASC";
                    } else {
                        $query .= " ORDER BY lote ASC";
                    }

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

                    foreach ($resultados as $row) {
                        if (!empty($row['lote'])) {
                            $lotes[] = [
                                'lote' => $row['lote'],
                                'quantidade' => (float) $row['quantidade'],
                                'fabricacao' => $row['fabricacao'] ?? null,
                                'validade' => $row['validade'] ?? null
                            ];
                        }
                    }
                }
            } catch (Exception $e) {
                error_log('Erro ao buscar lotes: ' . $e->getMessage());
            }

            $this->success('Lotes carregados', [
                'lotes' => $lotes
            ]);
        } catch (Exception $e) {
            error_log('Transferência: falha ao buscar lotes: ' . $e->getMessage());
            $this->error('Erro ao buscar lotes.');
        }
    }
}

