<?php

declare(strict_types=1);

namespace ApiModel\Action;

use ApiModel\Service\FinancialReportService;
use ApiModel\Shared\Support\AuthContext;
use ApiModel\Shared\Support\CompanyContext;
use ApiModel\Shared\Exceptions\BadRequestException;
use Psr\Http\Message\ServerRequestInterface;

final class ReportAction
{
    public function __construct(private readonly FinancialReportService $reportService) {}

    /**
     * Balanza de Comprobación
     * 
     * @return list<array<string, mixed>>
     */
    public function trialBalance(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $ctx = CompanyContext::require($request);
        $params = $request->getQueryParams();

        $startDate = trim((string) ($params['start_date'] ?? ''));
        $endDate = trim((string) ($params['end_date'] ?? ''));

        if ($startDate === '' || $endDate === '') {
            throw new BadRequestException('Las fechas de inicio y fin son obligatorias.');
        }

        return $this->reportService->getTrialBalance(
            $ctx['company_id'],
            $this->resolveBranch($ctx, $params),
            $startDate,
            $endDate
        );
    }

    /**
     * Balance General
     * 
     * @return array<string, mixed>
     */
    public function balanceSheet(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $ctx = CompanyContext::require($request);
        $params = $request->getQueryParams();

        $endDate = trim((string) ($params['end_date'] ?? ''));
        if ($endDate === '') {
            $endDate = date('Y-m-d');
        }

        return $this->reportService->getBalanceSheet(
            $ctx['company_id'],
            $this->resolveBranch($ctx, $params),
            $endDate
        );
    }

    /**
     * Estado de Resultados
     * 
     * @return array<string, mixed>
     */
    public function profitAndLoss(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $ctx = CompanyContext::require($request);
        $params = $request->getQueryParams();

        $startDate = trim((string) ($params['start_date'] ?? ''));
        $endDate = trim((string) ($params['end_date'] ?? ''));

        if ($startDate === '' || $endDate === '') {
            throw new BadRequestException('Las fechas de inicio y fin son obligatorias.');
        }

        return $this->reportService->getProfitAndLoss(
            $ctx['company_id'],
            $this->resolveBranch($ctx, $params),
            $startDate,
            $endDate
        );
    }

    /**
     * Antigüedad de Cuentas por Cobrar (AR Aging)
     * 
     * @return list<array<string, mixed>>
     */
    public function arAging(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $ctx = CompanyContext::require($request);
        $params = $request->getQueryParams();

        $referenceDate = trim((string) ($params['reference_date'] ?? ''));
        if ($referenceDate === '') {
            $referenceDate = date('Y-m-d');
        }

        return $this->reportService->getArAgingReport(
            $ctx['company_id'],
            $this->resolveBranch($ctx, $params),
            $referenceDate
        );
    }

    /**
     * Antigüedad de Cuentas por Pagar (AP Aging)
     * 
     * @return list<array<string, mixed>>
     */
    public function apAging(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $ctx = CompanyContext::require($request);
        $params = $request->getQueryParams();

        $referenceDate = trim((string) ($params['reference_date'] ?? ''));
        if ($referenceDate === '') {
            $referenceDate = date('Y-m-d');
        }

        return $this->reportService->getApAgingReport(
            $ctx['company_id'],
            $this->resolveBranch($ctx, $params),
            $referenceDate
        );
    }

    /**
     * Libro de Ventas
     * 
     * @return list<array<string, mixed>>
     */
    public function salesBook(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $ctx = CompanyContext::require($request);
        $params = $request->getQueryParams();

        $startDate = trim((string) ($params['start_date'] ?? ''));
        $endDate = trim((string) ($params['end_date'] ?? ''));

        if ($startDate === '' || $endDate === '') {
            throw new BadRequestException('Las fechas de inicio y fin son obligatorias.');
        }

        return $this->reportService->getSalesBook(
            $ctx['company_id'],
            $this->resolveBranch($ctx, $params),
            $startDate,
            $endDate
        );
    }

    /**
     * Libro de Compras
     * 
     * @return list<array<string, mixed>>
     */
    public function purchasesBook(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $ctx = CompanyContext::require($request);
        $params = $request->getQueryParams();

        $startDate = trim((string) ($params['start_date'] ?? ''));
        $endDate = trim((string) ($params['end_date'] ?? ''));

        if ($startDate === '' || $endDate === '') {
            throw new BadRequestException('Las fechas de inicio y fin son obligatorias.');
        }

        return $this->reportService->getPurchasesBook(
            $ctx['company_id'],
            $this->resolveBranch($ctx, $params),
            $startDate,
            $endDate
        );
    }

    public function journalBook(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $ctx = CompanyContext::require($request);
        $params = $request->getQueryParams();

        $startDate = trim((string) ($params['start_date'] ?? ''));
        $endDate = trim((string) ($params['end_date'] ?? ''));

        if ($startDate === '' || $endDate === '') {
            throw new BadRequestException('Las fechas de inicio y fin son obligatorias.');
        }

        return $this->reportService->getJournalBook(
            $ctx['company_id'],
            $this->resolveBranch($ctx, $params),
            $startDate,
            $endDate
        );
    }

    public function generalLedger(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $ctx = CompanyContext::require($request);
        $params = $request->getQueryParams();

        $startDate = trim((string) ($params['start_date'] ?? ''));
        $endDate = trim((string) ($params['end_date'] ?? ''));
        $accountId = isset($params['chart_account_id']) && trim((string) $params['chart_account_id']) !== '' ? trim((string) $params['chart_account_id']) : null;

        if ($startDate === '' || $endDate === '') {
            throw new BadRequestException('Las fechas de inicio y fin son obligatorias.');
        }

        return $this->reportService->getGeneralLedger(
            $ctx['company_id'],
            $this->resolveBranch($ctx, $params),
            $startDate,
            $endDate,
            $accountId
        );
    }

    public function taxSummary(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $ctx = CompanyContext::require($request);
        $params = $request->getQueryParams();

        $startDate = trim((string) ($params['start_date'] ?? ''));
        $endDate = trim((string) ($params['end_date'] ?? ''));

        if ($startDate === '' || $endDate === '') {
            throw new BadRequestException('Las fechas de inicio y fin son obligatorias.');
        }

        return $this->reportService->getTaxSummary(
            $ctx['company_id'],
            $this->resolveBranch($ctx, $params),
            $startDate,
            $endDate
        );
    }

    private function resolveBranch(array $ctx, array $params): ?string
    {
        if (array_key_exists('branch_id', $params)) {
            $branchId = trim((string) $params['branch_id']);
            return $branchId !== '' ? $branchId : null;
        }

        return $ctx['branch_id'] ?? null;
    }
}
