<?php

declare(strict_types=1);

namespace App\Controllers;

use Exception;

/**
 * Controller de Tabelas de Preço
 *
 * @author Systhema
 * @package Systhema
 */
class TabelasPrecoController extends BaseController
{
    /**
     * Lista todas as tabelas de preço
     */
    public function index(): void
    {
        // Verificar permissão de visualização
        if (!$this->canView('tabelas_preco')) {
            $this->response->forbidden('Você não tem permissão para visualizar tabelas de preço.');
            return;
        }

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

            // Buscar empresas para o filtro
            $stmtEmpresas = $this->db->prepare("
                SELECT id, razao_social, nome_fantasia
                FROM empresas
                ORDER BY razao_social ASC
            ");
            $stmtEmpresas->execute();
            $empresas = $stmtEmpresas->fetchAll();

            // Construir query para tabelas de preço
            $query = "
                SELECT
                    tp.*,
                    e.razao_social as empresa_nome,
                    e.nome_fantasia as empresa_fantasia
                FROM tabela_preco tp
                LEFT JOIN empresas e ON tp.company_id = e.id
                WHERE 1=1
            ";
            $params = [];

            if (!empty($search)) {
                $query .= " AND (tp.nome LIKE :search OR tp.descricao LIKE :search)";
                $params['search'] = "%{$search}%";
            }

            if (!empty($empresaId)) {
                $query .= " AND tp.company_id = :empresa_id";
                $params['empresa_id'] = $empresaId;
            }

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

            $query .= " ORDER BY tp.ordem ASC, tp.nome ASC";

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

            $this->view('tabelas-preco/index', [
                'tabelas' => $tabelas,
                'empresas' => $empresas,
                'search' => $search,
                'empresa_id' => $empresaId,
                'status' => $status,
                'pageTitle' => 'Tabelas de Preço',
                'activeMenu' => 'tabelas-preco'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao carregar tabelas de preço: " . $e->getMessage());
            $this->error('Erro ao carregar tabelas de preço');
        }
    }

    /**
     * Exibe formulário de criação
     */
    public function create(): void
    {
        // Verificar permissão de criação
        if (!$this->canCreate('tabelas_preco')) {
            $this->response->forbidden('Você não tem permissão para criar tabelas de preço.');
            return;
        }

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

            // Buscar empresas
            $stmt = $this->db->prepare("
                SELECT id, razao_social, nome_fantasia
                FROM empresas
                ORDER BY razao_social ASC
            ");
            $stmt->execute();
            $empresas = $stmt->fetchAll();

            $this->view('tabelas-preco/form', [
                'empresas' => $empresas,
                'pageTitle' => 'Nova Tabela de Preço',
                'activeMenu' => 'tabelas-preco'
            ]);

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

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

        try {
            $companyId = $this->request->post('company_id') ?: $this->getCompanyId();

            $data = [
                'company_id' => $companyId,
                'nome' => $this->request->post('nome'),
                'descricao' => $this->request->post('descricao') ?: null,
                'tipo' => $this->request->post('tipo', 'padrao'),
                'ativo' => $this->request->post('ativo') ? 1 : 0,
                'ordem' => (int) ($this->request->post('ordem') ?: 0)
            ];

            // Validar nome obrigatório
            if (empty($data['nome'])) {
                $this->error('Nome da tabela é obrigatório');
                return;
            }

            // Verificar se já existe tabela com mesmo nome para a mesma empresa
            $stmtCheck = $this->db->prepare("
                SELECT id FROM tabela_preco
                WHERE company_id = :company_id AND nome = :nome
            ");
            $stmtCheck->execute(['company_id' => $companyId, 'nome' => $data['nome']]);
            if ($stmtCheck->fetch()) {
                $this->error('Já existe uma tabela de preço com este nome para esta empresa');
                return;
            }

            $this->db->beginTransaction();

            $stmt = $this->db->prepare("
                INSERT INTO tabela_preco (company_id, nome, descricao, tipo, ativo, ordem, created_at, updated_at)
                VALUES (:company_id, :nome, :descricao, :tipo, :ativo, :ordem, NOW(), NOW())
            ");
            $stmt->execute($data);

            $tabelaId = (int) $this->db->lastInsertId();
            $this->logActivity('create', 'tabela_preco', $tabelaId, $data);

            $this->db->commit();

            $this->success('Tabela de preço criada com sucesso', ['id' => $tabelaId]);

        } catch (Exception $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log("Erro ao criar tabela de preço: " . $e->getMessage());
            $this->error('Erro ao criar tabela de preço: ' . $e->getMessage());
        }
    }

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

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

            // Buscar tabela de preço
            $stmt = $this->db->prepare("
                SELECT * FROM tabela_preco
                WHERE id = :id
            ");
            $stmt->execute(['id' => $id]);
            $tabela = $stmt->fetch();

            if (!$tabela) {
                $this->error('Tabela de preço não encontrada');
                return;
            }

            // Buscar empresas
            $stmtEmpresas = $this->db->prepare("
                SELECT id, razao_social, nome_fantasia
                FROM empresas
                ORDER BY razao_social ASC
            ");
            $stmtEmpresas->execute();
            $empresas = $stmtEmpresas->fetchAll();

            $this->view('tabelas-preco/form', [
                'tabela' => $tabela,
                'empresas' => $empresas,
                'pageTitle' => 'Editar Tabela de Preço',
                'activeMenu' => 'tabelas-preco'
            ]);

        } catch (Exception $e) {
            error_log("Erro ao carregar tabela de preço: " . $e->getMessage());
            $this->error('Erro ao carregar tabela de preço');
        }
    }

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

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

            // Verificar se a tabela existe
            $stmtCheck = $this->db->prepare("
                SELECT id FROM tabela_preco
                WHERE id = :id
            ");
            $stmtCheck->execute(['id' => $id]);
            if (!$stmtCheck->fetch()) {
                $this->error('Tabela de preço não encontrada');
                return;
            }

            $data = [
                'company_id' => $companyId,
                'nome' => $this->request->post('nome'),
                'descricao' => $this->request->post('descricao') ?: null,
                'tipo' => $this->request->post('tipo', 'padrao'),
                'ativo' => $this->request->post('ativo') ? 1 : 0,
                'ordem' => (int) ($this->request->post('ordem') ?: 0),
                'id' => $id
            ];

            // Validar nome obrigatório
            if (empty($data['nome'])) {
                $this->error('Nome da tabela é obrigatório');
                return;
            }

            // Verificar se já existe outra tabela com mesmo nome para a mesma empresa
            $stmtCheckNome = $this->db->prepare("
                SELECT id FROM tabela_preco
                WHERE company_id = :company_id AND nome = :nome AND id != :id
            ");
            $stmtCheckNome->execute([
                'company_id' => $companyId,
                'nome' => $data['nome'],
                'id' => $id
            ]);
            if ($stmtCheckNome->fetch()) {
                $this->error('Já existe outra tabela de preço com este nome para esta empresa');
                return;
            }

            $this->db->beginTransaction();

            $stmt = $this->db->prepare("
                UPDATE tabela_preco SET
                    company_id = :company_id,
                    nome = :nome,
                    descricao = :descricao,
                    tipo = :tipo,
                    ativo = :ativo,
                    ordem = :ordem,
                    updated_at = NOW()
                WHERE id = :id
            ");
            $stmt->execute($data);

            $this->logActivity('update', 'tabela_preco', $id, $data);

            $this->db->commit();

            $this->success('Tabela de preço atualizada com sucesso');

        } catch (Exception $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log("Erro ao atualizar tabela de preço: " . $e->getMessage());
            $this->error('Erro ao atualizar tabela de preço: ' . $e->getMessage());
        }
    }

    /**
     * Exclui uma tabela de preço
     */
    public function delete(): void
    {
        // Verificar permissão de exclusão
        if (!$this->canDelete('tabelas_preco')) {
            $this->response->forbidden('Você não tem permissão para excluir tabelas de preço.');
            return;
        }

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

            // Verificar se a tabela existe
            $stmtCheck = $this->db->prepare("
                SELECT id, nome FROM tabela_preco
                WHERE id = :id
            ");
            $stmtCheck->execute(['id' => $id]);
            $tabela = $stmtCheck->fetch();

            if (!$tabela) {
                $this->error('Tabela de preço não encontrada');
                return;
            }

            // Verificar se há produtos usando esta tabela
            $stmtCheckUso = $this->db->query("SHOW TABLES LIKE 'produto_preco'");
            if ($stmtCheckUso->rowCount() > 0) {
                // Verificar se existe coluna tabela_preco_id
                $stmtCols = $this->db->query("SHOW COLUMNS FROM produto_preco LIKE 'tabela_preco_id'");
                if ($stmtCols->rowCount() > 0) {
                    $stmtUso = $this->db->prepare("
                        SELECT COUNT(*) as total
                        FROM produto_preco
                        WHERE tabela_preco_id = :tabela_preco_id
                    ");
                    $stmtUso->execute(['tabela_preco_id' => $id]);
                    $uso = $stmtUso->fetch();

                    if ($uso && $uso['total'] > 0) {
                        $this->error("Não é possível excluir esta tabela. Existem {$uso['total']} produto(s) utilizando esta tabela de preço.");
                        return;
                    }
                }

                // Verificar também por descrição (método antigo)
                $stmtUsoDesc = $this->db->prepare("
                    SELECT COUNT(*) as total
                    FROM produto_preco
                    WHERE descricao LIKE :nome_tabela
                ");
                $stmtUsoDesc->execute(['nome_tabela' => 'Tabela: ' . $tabela['nome'] . '%']);
                $usoDesc = $stmtUsoDesc->fetch();

                if ($usoDesc && $usoDesc['total'] > 0) {
                    $this->error("Não é possível excluir esta tabela. Existem {$usoDesc['total']} produto(s) utilizando esta tabela de preço.");
                    return;
                }
            }

            // Verificar se há pessoas (clientes) usando esta tabela
            $stmtCheckPessoas = $this->db->query("SHOW COLUMNS FROM pessoas LIKE 'tabela_preco_id'");
            if ($stmtCheckPessoas->rowCount() > 0) {
                $stmtPessoas = $this->db->prepare("
                    SELECT COUNT(*) as total
                    FROM pessoas
                    WHERE tabela_preco_id = :tabela_preco_id
                ");
                $stmtPessoas->execute(['tabela_preco_id' => $id]);
                $pessoas = $stmtPessoas->fetch();

                if ($pessoas && $pessoas['total'] > 0) {
                    $this->error("Não é possível excluir esta tabela. Existem {$pessoas['total']} pessoa(s) utilizando esta tabela de preço.");
                    return;
                }
            }

            $this->db->beginTransaction();

            $stmt = $this->db->prepare("
                DELETE FROM tabela_preco
                WHERE id = :id
            ");
            $stmt->execute(['id' => $id]);

            $this->logActivity('delete', 'tabela_preco', $id, $tabela);

            $this->db->commit();

            $this->success('Tabela de preço excluída com sucesso');

        } catch (Exception $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log("Erro ao excluir tabela de preço: " . $e->getMessage());
            $this->error('Erro ao excluir tabela de preço: ' . $e->getMessage());
        }
    }

    /**
     * Clona uma tabela de preço para uma ou todas as empresas
     */
    public function clonar(): void
    {
        // Verificar permissão de criação
        if (!$this->canCreate('tabelas_preco')) {
            $this->response->forbidden('Você não tem permissão para criar tabelas de preço.');
            return;
        }

        try {
            $id = (int) $this->request->post('id');
            $tipo = $this->request->post('tipo', 'empresa'); // 'empresa' ou 'todas'
            $empresaDestino = $this->request->post('empresa_destino') ? (int) $this->request->post('empresa_destino') : null;

            // Buscar tabela de preço original
            $stmt = $this->db->prepare("
                SELECT * FROM tabela_preco
                WHERE id = :id
            ");
            $stmt->execute(['id' => $id]);
            $tabelaOriginal = $stmt->fetch();

            if (!$tabelaOriginal) {
                $this->error('Tabela de preço não encontrada');
                return;
            }

            $this->db->beginTransaction();

            $tabelasCriadas = 0;
            $empresasProcessadas = [];

            if ($tipo === 'todas') {
                // Buscar todas as empresas
                $stmtEmpresas = $this->db->prepare("
                    SELECT id FROM empresas
                    ORDER BY id ASC
                ");
                $stmtEmpresas->execute();
                $empresas = $stmtEmpresas->fetchAll();

                foreach ($empresas as $empresa) {
                    // Pular a empresa de origem
                    if ($empresa['id'] == $tabelaOriginal['company_id']) {
                        continue;
                    }

                    // Verificar se já existe tabela com mesmo nome nesta empresa
                    $stmtCheck = $this->db->prepare("
                        SELECT id FROM tabela_preco
                        WHERE company_id = :company_id AND nome = :nome
                    ");
                    $stmtCheck->execute([
                        'company_id' => $empresa['id'],
                        'nome' => $tabelaOriginal['nome']
                    ]);

                    if ($stmtCheck->fetch()) {
                        // Já existe, pular
                        continue;
                    }

                    // Criar cópia da tabela
                    $stmtInsert = $this->db->prepare("
                        INSERT INTO tabela_preco (company_id, nome, descricao, tipo, ativo, ordem, created_at, updated_at)
                        VALUES (:company_id, :nome, :descricao, :tipo, :ativo, :ordem, NOW(), NOW())
                    ");
                    $stmtInsert->execute([
                        'company_id' => $empresa['id'],
                        'nome' => $tabelaOriginal['nome'],
                        'descricao' => $tabelaOriginal['descricao'],
                        'tipo' => $tabelaOriginal['tipo'],
                        'ativo' => $tabelaOriginal['ativo'],
                        'ordem' => $tabelaOriginal['ordem']
                    ]);

                    $tabelasCriadas++;
                    $empresasProcessadas[] = $empresa['id'];
                }
            } else {
                // Clonar para empresa específica
                if (!$empresaDestino) {
                    $this->error('Empresa de destino não informada');
                    return;
                }

                // Verificar se empresa existe
                $stmtEmpresa = $this->db->prepare("
                    SELECT id FROM empresas WHERE id = :id
                ");
                $stmtEmpresa->execute(['id' => $empresaDestino]);
                if (!$stmtEmpresa->fetch()) {
                    $this->error('Empresa de destino não encontrada');
                    return;
                }

                // Verificar se já existe tabela com mesmo nome nesta empresa
                $stmtCheck = $this->db->prepare("
                    SELECT id FROM tabela_preco
                    WHERE company_id = :company_id AND nome = :nome
                ");
                $stmtCheck->execute([
                    'company_id' => $empresaDestino,
                    'nome' => $tabelaOriginal['nome']
                ]);

                if ($stmtCheck->fetch()) {
                    $this->error('Já existe uma tabela de preço com este nome na empresa selecionada');
                    return;
                }

                // Criar cópia da tabela
                $stmtInsert = $this->db->prepare("
                    INSERT INTO tabela_preco (company_id, nome, descricao, tipo, ativo, ordem, created_at, updated_at)
                    VALUES (:company_id, :nome, :descricao, :tipo, :ativo, :ordem, NOW(), NOW())
                ");
                $stmtInsert->execute([
                    'company_id' => $empresaDestino,
                    'nome' => $tabelaOriginal['nome'],
                    'descricao' => $tabelaOriginal['descricao'],
                    'tipo' => $tabelaOriginal['tipo'],
                    'ativo' => $tabelaOriginal['ativo'],
                    'ordem' => $tabelaOriginal['ordem']
                ]);

                $tabelaId = (int) $this->db->lastInsertId();
                $this->logActivity('create', 'tabela_preco', $tabelaId, [
                    'action' => 'clonar',
                    'origem_id' => $id,
                    'empresa_destino' => $empresaDestino
                ]);

                $tabelasCriadas = 1;
                $empresasProcessadas[] = $empresaDestino;
            }

            $this->db->commit();

            $mensagem = $tipo === 'todas'
                ? "Tabela clonada com sucesso para {$tabelasCriadas} empresa(s)"
                : "Tabela clonada com sucesso para a empresa selecionada";

            $this->success($mensagem, [
                'tabelas_criadas' => $tabelasCriadas,
                'empresas_processadas' => $empresasProcessadas
            ]);

        } catch (Exception $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log("Erro ao clonar tabela de preço: " . $e->getMessage());
            $this->error('Erro ao clonar tabela de preço: ' . $e->getMessage());
        }
    }
}

