<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Helpers\UrlHelper;
use Exception;

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

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

            // Buscar contratos
            $stmt = $this->db->prepare("
                SELECT c.*,
                    e.razao_social as empresa_nome,
                    p.name as pessoa_nome,
                    u.name as criado_por_nome
                FROM contratos c
                LEFT JOIN empresas e ON c.empresa_id = e.id
                LEFT JOIN pessoas p ON c.pessoa_id = p.id
                LEFT JOIN users u ON c.created_by = u.id
                WHERE c.company_id = :company_id
                ORDER BY c.created_at DESC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $contratos = $stmt->fetchAll();

            $this->view('contratos/index', [
                'contratos' => $contratos,
                'pageTitle' => 'Contratos',
                'activeMenu' => 'contratos'
            ]);

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

    /**
     * Exibe formulário de criação
     */
    public function create(): void
    {
        $companyId = $this->getCompanyId();
        $empresas = $this->getEmpresas($companyId);
        $pessoas = $this->getPessoas($companyId);
        $numeroContrato = $this->gerarProximoNumeroContrato($companyId);

        $this->view('contratos/create', [
            'empresas' => $empresas,
            'pessoas' => $pessoas,
            'numeroContrato' => $numeroContrato,
            'pageTitle' => 'Novo Contrato'
        ]);
    }

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

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

            $data = [
                'company_id' => $companyId,
                'numero_contrato' => $this->request->post('numero_contrato'),
                'tipo' => $this->request->post('tipo', 'licenca_software'),
                'empresa_id' => $this->request->post('empresa_id') ?: null,
                'pessoa_id' => $this->request->post('pessoa_id') ?: null,
                'representante_legal' => $this->request->post('representante_legal') ?: null,
                'cpf_representante' => $this->request->post('cpf_representante') ?: null,
                'data_inicio' => $this->request->post('data_inicio'),
                'data_fim' => $this->request->post('data_fim') ?: null,
                'data_assinatura' => $this->request->post('data_assinatura') ?: null,
                'valor_mensal' => $this->request->post('valor_mensal', 0),
                'valor_total' => $this->request->post('valor_total', 0),
                'valor_implantacao' => $this->request->post('valor_implantacao', 0),
                'plano' => $this->request->post('plano') ?: null,
                'quantidade_usuarios' => $this->request->post('quantidade_usuarios', 1),
                'valor_usuario_adicional' => $this->request->post('valor_usuario_adicional', 0),
                'forma_pagamento' => $this->request->post('forma_pagamento') ?: null,
                'status' => $this->request->post('status', 'rascunho'),
                'observacoes' => $this->request->post('observacoes') ?: null,
                'created_by' => $user['id'] ?? null
            ];

            // Validar campos obrigatórios
            if (empty($data['numero_contrato']) || empty($data['data_inicio'])) {
                $this->response->error('Número do contrato e data de início são obrigatórios');
                return;
            }

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

            // Inserir
            $sql = "INSERT INTO contratos (
                company_id, numero_contrato, tipo, empresa_id, pessoa_id,
                representante_legal, cpf_representante,
                data_inicio, data_fim, data_assinatura,
                valor_mensal, valor_total, valor_implantacao,
                plano, quantidade_usuarios, valor_usuario_adicional,
                forma_pagamento, status, observacoes, created_by
            ) VALUES (
                :company_id, :numero_contrato, :tipo, :empresa_id, :pessoa_id,
                :representante_legal, :cpf_representante,
                :data_inicio, :data_fim, :data_assinatura,
                :valor_mensal, :valor_total, :valor_implantacao,
                :plano, :quantidade_usuarios, :valor_usuario_adicional,
                :forma_pagamento, :status, :observacoes, :created_by
            )";

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

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

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

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

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

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

            $stmt = $this->db->prepare("
                SELECT c.*,
                    e.razao_social as empresa_nome,
                    p.name as pessoa_nome
                FROM contratos c
                LEFT JOIN empresas e ON c.empresa_id = e.id
                LEFT JOIN pessoas p ON c.pessoa_id = p.id
                WHERE c.id = :id AND c.company_id = :company_id
                LIMIT 1
            ");
            $stmt->execute(['id' => $id, 'company_id' => $companyId]);
            $contrato = $stmt->fetch();

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

            $empresas = $this->getEmpresas($companyId);
            $pessoas = $this->getPessoas($companyId);

            $this->view('contratos/edit', [
                'contrato' => $contrato,
                'empresas' => $empresas,
                'pessoas' => $pessoas,
                'pageTitle' => 'Editar Contrato'
            ]);

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

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

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

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

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

            $data = [
                'id' => $id,
                'numero_contrato' => $this->request->post('numero_contrato'),
                'tipo' => $this->request->post('tipo', 'licenca_software'),
                'empresa_id' => $this->request->post('empresa_id') ?: null,
                'pessoa_id' => $this->request->post('pessoa_id') ?: null,
                'representante_legal' => $this->request->post('representante_legal') ?: null,
                'cpf_representante' => $this->request->post('cpf_representante') ?: null,
                'data_inicio' => $this->request->post('data_inicio'),
                'data_fim' => $this->request->post('data_fim') ?: null,
                'data_assinatura' => $this->request->post('data_assinatura') ?: null,
                'valor_mensal' => $this->request->post('valor_mensal', 0),
                'valor_total' => $this->request->post('valor_total', 0),
                'valor_implantacao' => $this->request->post('valor_implantacao', 0),
                'plano' => $this->request->post('plano') ?: null,
                'quantidade_usuarios' => $this->request->post('quantidade_usuarios', 1),
                'valor_usuario_adicional' => $this->request->post('valor_usuario_adicional', 0),
                'forma_pagamento' => $this->request->post('forma_pagamento') ?: null,
                'status' => $this->request->post('status', 'rascunho'),
                'observacoes' => $this->request->post('observacoes') ?: null,
                'updated_by' => $user['id'] ?? null
            ];

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

            // Atualizar
            $sql = "UPDATE contratos SET
                numero_contrato = :numero_contrato,
                tipo = :tipo,
                empresa_id = :empresa_id,
                pessoa_id = :pessoa_id,
                representante_legal = :representante_legal,
                cpf_representante = :cpf_representante,
                data_inicio = :data_inicio,
                data_fim = :data_fim,
                data_assinatura = :data_assinatura,
                valor_mensal = :valor_mensal,
                valor_total = :valor_total,
                valor_implantacao = :valor_implantacao,
                plano = :plano,
                quantidade_usuarios = :quantidade_usuarios,
                valor_usuario_adicional = :valor_usuario_adicional,
                forma_pagamento = :forma_pagamento,
                status = :status,
                observacoes = :observacoes,
                updated_by = :updated_by
            WHERE id = :id AND company_id = :company_id";

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

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

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

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

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

            $stmt = $this->db->prepare("
                SELECT c.*,
                    e.razao_social as empresa_nome,
                    e.cnpj as empresa_cnpj,
                    e.endereco as empresa_endereco,
                    e.numero as empresa_numero,
                    e.bairro as empresa_bairro,
                    e.cidade as empresa_cidade,
                    e.uf as empresa_uf,
                    e.cep as empresa_cep,
                    p.name as pessoa_nome,
                    p.document as pessoa_document,
                    u1.name as criado_por_nome,
                    u2.name as atualizado_por_nome
                FROM contratos c
                LEFT JOIN empresas e ON c.empresa_id = e.id
                LEFT JOIN pessoas p ON c.pessoa_id = p.id
                LEFT JOIN users u1 ON c.created_by = u1.id
                LEFT JOIN users u2 ON c.updated_by = u2.id
                WHERE c.id = :id AND c.company_id = :company_id
                LIMIT 1
            ");
            $stmt->execute(['id' => $id, 'company_id' => $companyId]);
            $contrato = $stmt->fetch();

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

            $this->view('contratos/show', [
                'contrato' => $contrato,
                'pageTitle' => 'Visualizar Contrato'
            ]);

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

    /**
     * Imprime contrato
     */
    public function print(): void
    {
        try {
            $id = (int) $this->request->get('id');
            $companyId = $this->getCompanyId();

            if (!$id) {
                echo "Contrato não encontrado";
                return;
            }

            // Buscar dados do contrato
            $stmt = $this->db->prepare("
                SELECT c.*,
                    e.razao_social as empresa_nome,
                    e.cnpj as empresa_cnpj,
                    e.endereco as empresa_endereco,
                    e.numero as empresa_numero,
                    e.bairro as empresa_bairro,
                    e.cidade as empresa_cidade,
                    e.uf as empresa_uf,
                    e.cep as empresa_cep,
                    e.telefone as empresa_telefone,
                    e.email as empresa_email,
                    p.name as pessoa_nome,
                    p.document as pessoa_document,
                    p.trade_name as pessoa_trade_name,
                    p.address as pessoa_endereco,
                    p.numero as pessoa_numero,
                    p.bairro as pessoa_bairro,
                    p.city as pessoa_cidade,
                    p.state as pessoa_uf,
                    p.zip_code as pessoa_cep,
                    p.phone as pessoa_telefone,
                    p.email as pessoa_email
                FROM contratos c
                LEFT JOIN empresas e ON c.empresa_id = e.id
                LEFT JOIN pessoas p ON c.pessoa_id = p.id
                WHERE c.id = :id AND c.company_id = :company_id
                LIMIT 1
            ");
            $stmt->execute(['id' => $id, 'company_id' => $companyId]);
            $contrato = $stmt->fetch();

            if (!$contrato) {
                echo "Contrato não encontrado";
                return;
            }

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

            $this->view('contratos/print', [
                'contrato' => $contrato,
                'empresa' => $empresaPrincipal,
                'pageTitle' => 'Contrato ' . $contrato['numero_contrato']
            ]);

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

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

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

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

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

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

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

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

    /**
     * Gera próximo número de contrato
     */
    private function gerarProximoNumeroContrato(int $companyId): string
    {
        $stmt = $this->db->prepare("SELECT MAX(CAST(SUBSTRING(numero_contrato, 4) AS UNSIGNED)) AS maxnum
            FROM contratos
            WHERE company_id = :company_id AND numero_contrato LIKE 'CT-%'");
        $stmt->execute(['company_id' => $companyId]);
        $row = $stmt->fetch();
        $max = (int)($row['maxnum'] ?? 0);
        $next = $max + 1;
        return 'CT-' . str_pad((string)$next, 6, '0', STR_PAD_LEFT);
    }

    /**
     * Busca empresas
     */
    private function getEmpresas(int $companyId): array
    {
        try {
            // Buscar empresas do company_id, incluindo a empresa principal (id = company_id)
            $stmt = $this->db->prepare("
                SELECT id, razao_social, nome_fantasia, cnpj
                FROM empresas
                WHERE company_id = :company_id OR id = :company_id2
                ORDER BY razao_social
            ");
            $stmt->execute([
                'company_id' => $companyId,
                'company_id2' => $companyId
            ]);
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar empresas: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Busca pessoas
     */
    private function getPessoas(int $companyId): array
    {
        try {
            // Buscar apenas clientes (tipo_cliente = 1)
            $stmt = $this->db->prepare("
                SELECT id, name, document, trade_name, email, phone, mobile, tipo_cliente, tipo_fornecedor
                FROM pessoas
                WHERE company_id = :company_id AND tipo_cliente = 1
                ORDER BY name
            ");
            $stmt->execute(['company_id' => $companyId]);
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar pessoas: " . $e->getMessage());
            return [];
        }
    }
}

