<?php

declare(strict_types=1);

namespace App\Controllers;

use Exception;
use App\Helpers\UrlHelper;

class PlanoContasController extends BaseController
{
    public function index(): void
    {
        // Verificar permissão de visualização
        if (!$this->canView('plano-contas')) {
            $this->response->forbidden('Você não tem permissão para visualizar plano de contas.');
            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 contas
            $stmtCount = $this->db->prepare("
                SELECT COUNT(*) as total
                FROM plano_contas pc
                WHERE pc.company_id = :company_id
            ");
            $stmtCount->execute(['company_id' => $companyId]);
            $total = (int) $stmtCount->fetch()['total'];
            $totalPages = max(1, (int) ceil($total / $perPage));

            // Buscar contas (paginado)
            $stmt = $this->db->prepare("
                SELECT pc.*,
                       parent.name as parent_name
                FROM plano_contas pc
                LEFT JOIN plano_contas parent ON pc.parent_id = parent.id
                WHERE pc.company_id = :company_id
                ORDER BY pc.code 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();
            $contas = $stmt->fetchAll();

            $this->view('plano-contas/index', [
                'contas' => $contas,
                'pageTitle' => 'Plano de Contas',
                'activeMenu' => 'plano-contas',
                'page' => $page,
                'perPage' => $perPage,
                'total' => $total,
                'totalPages' => $totalPages
            ]);

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

    public function create(): void
    {
        $contas = $this->getContasPai();

        $this->view('plano-contas/create', [
            'contas' => $contas,
            'pageTitle' => 'Nova Conta',
            'activeMenu' => 'plano-contas'
        ]);
    }

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

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

            $data = [
                'company_id' => $companyId,
                'parent_id' => $this->request->post('parent_id') ?: null,
                'code' => $this->request->post('code'),
                'name' => $this->request->post('name'),
                'type' => $this->request->post('type'),
                'notes' => $this->request->post('description') ?: null,
                'allows_entries' => $this->request->post('allows_entries') ? 1 : 0,
                'is_active' => 1,
            ];

            $this->db->beginTransaction();

            $stmt = $this->db->prepare("
                INSERT INTO plano_contas (company_id, parent_id, code, name, type, notes, allows_entries, is_active, created_at, updated_at)
                VALUES (:company_id, :parent_id, :code, :name, :type, :notes, :allows_entries, :is_active, NOW(), NOW())
            ");
            $stmt->execute($data);
            $contaId = (int) $this->db->lastInsertId();

            $this->logActivity('create', 'plano_contas', $contaId, $data);
            $this->db->commit();

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

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

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

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

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

            $contas = $this->getContasPai($id);

            $this->view('plano-contas/edit', [
                'conta' => $conta,
                'contas' => $contas,
                'pageTitle' => 'Editar Conta',
                'activeMenu' => 'plano-contas'
            ]);

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

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

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

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

            $data = [
                'parent_id' => $this->request->post('parent_id') ?: null,
                'code' => $this->request->post('code'),
                'name' => $this->request->post('name'),
                'type' => $this->request->post('type'),
                'notes' => $this->request->post('description') ?: null,
                'allows_entries' => $this->request->post('allows_entries') ? 1 : 0,
                'is_active' => $this->request->post('is_active') ? 1 : 0,
                'id' => $id,
                'company_id' => $this->getCompanyId()
            ];

            $this->db->beginTransaction();

            $stmt = $this->db->prepare("
                UPDATE plano_contas SET
                    parent_id = :parent_id,
                    code = :code,
                    name = :name,
                    type = :type,
                    notes = :notes,
                    allows_entries = :allows_entries,
                    is_active = :is_active,
                    updated_at = NOW()
                WHERE id = :id AND company_id = :company_id
            ");
            $stmt->execute($data);

            $this->logActivity('update', 'plano_contas', $id, $data);
            $this->db->commit();

            $this->success('Conta atualizada com sucesso', [
                'redirect' => UrlHelper::url('/plano-contas')
            ]);

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

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

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

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

            $this->db->beginTransaction();

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

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

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

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

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

    private function getContasPai(?int $excludeId = null): array
    {
        $query = "SELECT id, code, name FROM plano_contas WHERE company_id = :company_id";
        $params = ['company_id' => $this->getCompanyId()];

        if ($excludeId) {
            $query .= " AND id != :exclude_id";
            $params['exclude_id'] = $excludeId;
        }

        $query .= " ORDER BY code ASC";

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