<?php

namespace App\Controllers;

use Exception;
use App\Helpers\UrlHelper;

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

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

            // Paginação
            $perPage = 50;
            $page = max(1, (int) ($this->request->get('page') ?? 1));
            $offset = ($page - 1) * $perPage;

            // Contar total de métodos
            $stmtCount = $this->db->prepare("
                SELECT COUNT(DISTINCT mp.id) as total
                FROM metodos_pagamento mp
                WHERE mp.company_id = :company_id
            ");
            $stmtCount->execute(['company_id' => $companyId]);
            $total = (int) $stmtCount->fetch()['total'];
            $totalPages = max(1, (int) ceil($total / $perPage));

            // Buscar métodos (paginado)
            $stmt = $this->db->prepare("
                SELECT
                    mp.*,
                    GROUP_CONCAT(mpp.dias ORDER BY mpp.dias ASC SEPARATOR ', ') as prazos
                FROM metodos_pagamento mp
                LEFT JOIN metodos_pagamento_prazos mpp
                    ON mp.id = mpp.metodo_id
                    AND mpp.company_id = mp.company_id
                    AND mpp.ativo = 1
                WHERE mp.company_id = :company_id
                GROUP BY mp.id
                ORDER BY mp.name ASC
                LIMIT :limit OFFSET :offset
            ");
            $stmt->bindValue(':company_id', $companyId, \PDO::PARAM_INT);
            $stmt->bindValue(':limit', $perPage, \PDO::PARAM_INT);
            $stmt->bindValue(':offset', $offset, \PDO::PARAM_INT);
            $stmt->execute();
            $metodos = $stmt->fetchAll();

            $this->view('metodos-pagamento/index', [
                'metodos' => $metodos,
                'pageTitle' => 'Métodos de Pagamento',
                'page' => $page,
                'perPage' => $perPage,
                'total' => $total,
                'totalPages' => $totalPages
            ]);

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

    /**
     * Exibe formulário de criação
     */
    public function create(): void
    {
        $grupos = $this->getGruposMetodosPagamento();

        $this->view('metodos-pagamento/form', [
            'pageTitle' => 'Novo Método de Pagamento',
            'grupos' => $grupos
        ]);
    }

    /**
     * Busca grupos para métodos de pagamento
     */
    private function getGruposMetodosPagamento(): array
    {
        try {
            $companyId = $this->getCompanyId();
            $stmt = $this->db->prepare("
                SELECT id, nome
                FROM grupos_pessoas
                WHERE company_id = :company_id
                AND tipo = 'metodos_pagamento'
                AND ativo = 1
                ORDER BY nome ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            return $stmt->fetchAll() ?: [];
        } catch (Exception $e) {
            return [];
        }
    }

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

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

            $data = [
                'company_id' => $companyId,
                'name' => $this->request->post('name'),
                'type' => $this->request->post('type'),
                'grupo_id' => $this->request->post('grupo_id') ?: null,
                'aplicacao' => $this->request->post('aplicacao') ?: 'ambos',
                'usar_pdv' => $this->request->post('usar_pdv') ? 1 : 0,
                'icon' => $this->request->post('icon'),
                'gateway' => $this->request->post('gateway'),
                'api_key' => $this->request->post('api_key'),
                'webhook_url' => $this->request->post('webhook_url'),
                'installments' => $this->request->post('installments') ?: 1,
                'fee_percentage' => $this->request->post('fee_percentage') ?: 0.00,
                'days_to_receive' => $this->request->post('days_to_receive') ?: 0,
                'notes' => $this->request->post('notes'),
                'is_active' => 1,
                'use_shipay' => $this->request->post('use_shipay') ? 1 : 0,
            ];

            $errors = $this->validate([
                'name' => 'required|min:2',
                'type' => 'required|in:dinheiro,cartao,pix,transferencia,boleto,cheque,cartao_credito,cartao_debito,carne,crediario,voucher,operacoes_internas,outro',
                'aplicacao' => 'required|in:entradas,saidas,ambos',
            ]);

            if (!empty($errors)) {
                $this->error('Dados inválidos', $errors);
                return;
            }

            $this->db->beginTransaction();

            // Verificar se coluna use_shipay existe
            $stmtCheck = $this->db->query("SHOW COLUMNS FROM metodos_pagamento LIKE 'use_shipay'");
            $hasUseShipay = $stmtCheck->rowCount() > 0;

            $campos = 'company_id, name, type, icon, gateway, api_key, webhook_url, installments, fee_percentage, days_to_receive, notes, is_active';
            $valores = ':company_id, :name, :type, :icon, :gateway, :api_key, :webhook_url, :installments, :fee_percentage, :days_to_receive, :notes, :is_active';

            // Verificar se colunas grupo_id e aplicacao existem
            $stmtCheckGrupo = $this->db->query("SHOW COLUMNS FROM metodos_pagamento LIKE 'grupo_id'");
            if ($stmtCheckGrupo->rowCount() > 0) {
                $campos .= ', grupo_id';
                $valores .= ', :grupo_id';
            } else {
                unset($data['grupo_id']);
            }

            $stmtCheckAplicacao = $this->db->query("SHOW COLUMNS FROM metodos_pagamento LIKE 'aplicacao'");
            if ($stmtCheckAplicacao->rowCount() > 0) {
                $campos .= ', aplicacao';
                $valores .= ', :aplicacao';
            } else {
                unset($data['aplicacao']);
            }

            // Verificar se coluna usar_pdv existe
            $stmtCheckUsarPdv = $this->db->query("SHOW COLUMNS FROM metodos_pagamento LIKE 'usar_pdv'");
            if ($stmtCheckUsarPdv->rowCount() > 0) {
                $campos .= ', usar_pdv';
                $valores .= ', :usar_pdv';
            } else {
                unset($data['usar_pdv']);
            }

            if ($hasUseShipay) {
                $campos .= ', use_shipay';
                $valores .= ', :use_shipay';
            } else {
                unset($data['use_shipay']);
            }

            $stmt = $this->db->prepare("
                INSERT INTO metodos_pagamento (
                    {$campos}, created_at, updated_at
                ) VALUES (
                    {$valores}, NOW(), NOW()
                )
            ");

            $stmt->execute($data);
            $metodoId = (int) $this->db->lastInsertId();

            // Salvar prazos (se houver)
            $prazos = $this->request->post('prazos');
            if ($prazos && is_array($prazos)) {
                $this->salvarPrazos($metodoId, $prazos);
            }

            $this->logActivity('create', 'metodos_pagamento', $metodoId, $data);

            $this->db->commit();

            $this->success('Método de pagamento criado com sucesso', [
                'id' => $metodoId,
                'redirect' => UrlHelper::url('/metodos-pagamento')
            ]);

        } catch (Exception $e) {
            $this->db->rollBack();
            error_log("Erro ao criar método de pagamento: " . $e->getMessage());
            $this->error('Erro ao cadastrar método de pagamento');
        }
    }

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

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

            if (!$metodo) {
                $this->response->notFound('Método de pagamento não encontrado');
                return;
            }

            // Buscar prazos configurados
            $prazos = $this->getPrazos($id);

            // Buscar grupos
            $grupos = $this->getGruposMetodosPagamento();

            $this->view('metodos-pagamento/edit', [
                'metodo' => $metodo,
                'prazos' => $prazos,
                'grupos' => $grupos,
                'pageTitle' => 'Editar ' . $metodo['name']
            ]);

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

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

        try {
            $id = (int) $this->request->post('id');
            $metodo = $this->getMetodo($id);

            if (!$metodo) {
                $this->error('Método de pagamento não encontrado');
                return;
            }

            $data = [
                'name' => $this->request->post('name'),
                'type' => $this->request->post('type'),
                'grupo_id' => $this->request->post('grupo_id') ?: null,
                'aplicacao' => $this->request->post('aplicacao') ?: 'ambos',
                'usar_pdv' => $this->request->post('usar_pdv') ? 1 : 0,
                'icon' => $this->request->post('icon'),
                'gateway' => $this->request->post('gateway'),
                'api_key' => $this->request->post('api_key'),
                'webhook_url' => $this->request->post('webhook_url'),
                'installments' => $this->request->post('installments') ?: 1,
                'fee_percentage' => $this->request->post('fee_percentage') ?: 0.00,
                'days_to_receive' => $this->request->post('days_to_receive') ?: 0,
                'notes' => $this->request->post('notes'),
                'is_active' => $this->request->post('is_active', '0') === '1' ? 1 : 0,
                'use_shipay' => $this->request->post('use_shipay') ? 1 : 0,
                'id' => $id
            ];

            $errors = $this->validate([
                'name' => 'required|min:2',
                'type' => 'required|in:dinheiro,cartao,pix,transferencia,boleto,cheque,cartao_credito,cartao_debito,carne,crediario,voucher,operacoes_internas,outro',
                'aplicacao' => 'required|in:entradas,saidas,ambos',
            ]);

            if (!empty($errors)) {
                $this->error('Dados inválidos', $errors);
                return;
            }

            $this->db->beginTransaction();

            // Verificar se coluna use_shipay existe
            $stmtCheck = $this->db->query("SHOW COLUMNS FROM metodos_pagamento LIKE 'use_shipay'");
            $hasUseShipay = $stmtCheck->rowCount() > 0;

            $setClause = "name = :name, type = :type, icon = :icon, gateway = :gateway, api_key = :api_key,
                          webhook_url = :webhook_url, installments = :installments, fee_percentage = :fee_percentage,
                          days_to_receive = :days_to_receive, notes = :notes, is_active = :is_active";

            // Verificar se colunas grupo_id e aplicacao existem
            $stmtCheckGrupo = $this->db->query("SHOW COLUMNS FROM metodos_pagamento LIKE 'grupo_id'");
            if ($stmtCheckGrupo->rowCount() > 0) {
                $setClause .= ", grupo_id = :grupo_id";
            } else {
                unset($data['grupo_id']);
            }

            $stmtCheckAplicacao = $this->db->query("SHOW COLUMNS FROM metodos_pagamento LIKE 'aplicacao'");
            if ($stmtCheckAplicacao->rowCount() > 0) {
                $setClause .= ", aplicacao = :aplicacao";
            } else {
                unset($data['aplicacao']);
            }

            // Verificar se coluna usar_pdv existe
            $stmtCheckUsarPdv = $this->db->query("SHOW COLUMNS FROM metodos_pagamento LIKE 'usar_pdv'");
            if ($stmtCheckUsarPdv->rowCount() > 0) {
                $setClause .= ", usar_pdv = :usar_pdv";
            } else {
                unset($data['usar_pdv']);
            }

            if ($hasUseShipay) {
                $setClause .= ", use_shipay = :use_shipay";
            } else {
                unset($data['use_shipay']);
            }

            $stmt = $this->db->prepare("
                UPDATE metodos_pagamento SET
                    {$setClause},
                    updated_at = NOW()
                WHERE id = :id AND company_id = :company_id
            ");

            $data['company_id'] = $this->getCompanyId();
            $stmt->execute($data);

            // Atualizar prazos
            $prazos = $this->request->post('prazos');
            if ($prazos && is_array($prazos)) {
                // Deletar prazos existentes
                $stmtDel = $this->db->prepare("DELETE FROM metodos_pagamento_prazos WHERE metodo_id = :metodo_id AND company_id = :company_id");
                $stmtDel->execute(['metodo_id' => $id, 'company_id' => $this->getCompanyId()]);

                // Salvar novos prazos
                $this->salvarPrazos($id, $prazos);
            }

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

            $this->db->commit();

            $this->success('Método de pagamento atualizado com sucesso', [
                'redirect' => UrlHelper::url('/metodos-pagamento')
            ]);

        } catch (Exception $e) {
            $this->db->rollBack();
            error_log("Erro ao atualizar método de pagamento: " . $e->getMessage());
            $this->error('Erro ao atualizar método de pagamento');
        }
    }

    /**
     * Exclui um método de pagamento
     */
    public function delete(): void
    {
        // Verificar permissão de exclusão
        if (!$this->canDelete('metodos-pagamento')) {
            $this->response->forbidden('Você não tem permissão para excluir métodos de pagamento.');
            return;
        }

        try {
            $id = (int) $this->request->post('id');
            $metodo = $this->getMetodo($id);

            if (!$metodo) {
                $this->error('Método de pagamento não encontrado');
                return;
            }

            // Verifica se há vendas vinculadas
            $stmt = $this->db->prepare("
                SELECT COUNT(*) FROM vendas
                WHERE payment_method = :id
            ");
            $stmt->execute(['id' => $id]);
            $vendasCount = $stmt->fetchColumn();

            if ($vendasCount > 0) {
                $this->error("Não é possível excluir este método. Existem {$vendasCount} venda(s) vinculada(s).");
                return;
            }

            $this->db->beginTransaction();

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

            $this->logActivity('delete', 'metodos_pagamento', $id, $metodo);

            $this->db->commit();

            $this->success('Método de pagamento excluído com sucesso');

        } catch (Exception $e) {
            $this->db->rollBack();
            error_log("Erro ao excluir método de pagamento: " . $e->getMessage());
            $this->error('Erro ao excluir método de pagamento');
        }
    }

    /**
     * Busca um método de pagamento por ID
     */
    private function getMetodo(int $id): ?array
    {
        $stmt = $this->db->prepare("
            SELECT * FROM metodos_pagamento
            WHERE id = :id AND company_id = :company_id
        ");
        $stmt->execute([
            'id' => $id,
            'company_id' => $this->getCompanyId()
        ]);

        return $stmt->fetch() ?: null;
    }

    /**
     * API: Busca prazos de um método de pagamento
     */
    public function buscarPrazos(): void
    {
        try {
            $metodoId = (int) $this->request->get('metodo_id');

            if (!$metodoId) {
                $this->error('ID do método não informado');
                return;
            }

            $prazos = $this->getPrazos($metodoId);

            $this->success('Prazos carregados', [
                'prazos' => $prazos
            ]);

        } catch (Exception $e) {
            error_log("Erro ao buscar prazos via API: " . $e->getMessage());
            $this->error('Erro ao buscar prazos');
        }
    }

    /**
     * Busca prazos de um método de pagamento
     */
    private function getPrazos(int $metodoId): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT * FROM metodos_pagamento_prazos
                WHERE metodo_id = :metodo_id AND company_id = :company_id AND ativo = 1
                ORDER BY dias ASC
            ");
            $stmt->execute([
                'metodo_id' => $metodoId,
                'company_id' => $this->getCompanyId()
            ]);
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar prazos: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Salva múltiplos prazos de uma vez
     */
    private function salvarPrazos(int $metodoId, array $prazos): void
    {
        $companyId = $this->getCompanyId();

        $stmt = $this->db->prepare("
            INSERT INTO metodos_pagamento_prazos
            (company_id, metodo_id, dias, taxa_adicional, ativo, created_at)
            VALUES (:company_id, :metodo_id, :dias, :taxa_adicional, 1, NOW())
        ");

        foreach ($prazos as $prazo) {
            if (isset($prazo['dias']) && $prazo['dias'] > 0) {
                $stmt->execute([
                    'company_id' => $companyId,
                    'metodo_id' => $metodoId,
                    'dias' => (int) $prazo['dias'],
                    'taxa_adicional' => $prazo['taxa_adicional'] ?? 0
                ]);
            }
        }
    }
}
