<?php

declare(strict_types=1);

namespace ApiModel\Action;

use ApiModel\Service\BudgetService;
use ApiModel\Shared\Http\HttpUtil;
use ApiModel\Shared\Support\AuthContext;
use Psr\Http\Message\ServerRequestInterface;

final class BudgetAction
{
    public function __construct(private readonly BudgetService $service) {}

    // Años Fiscales
    /** @return list<array<string, mixed>> */
    public function listFiscalYears(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        return $this->service->listFiscalYears();
    }

    /** @return array<string, mixed> */
    public function createFiscalYear(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        return $this->service->createFiscalYear(HttpUtil::parseJson($request));
    }

    /** @return array<string, mixed> */
    public function updateFiscalYearStatus(ServerRequestInterface $request, string $id): array
    {
        AuthContext::jwtUser($request);
        $data = HttpUtil::parseJson($request);
        return $this->service->updateFiscalYearStatus($id, trim((string) ($data['status'] ?? '')));
    }

    // Clasificadores
    /** @return list<array<string, mixed>> */
    public function listClassifiers(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        return $this->service->listClassifiers();
    }

    /** @return array<string, mixed> */
    public function createClassifier(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        return $this->service->createClassifier(HttpUtil::parseJson($request));
    }

    /** @return array<string, mixed> */
    public function updateClassifier(ServerRequestInterface $request, string $id): array
    {
        AuthContext::jwtUser($request);
        return $this->service->updateClassifier($id, HttpUtil::parseJson($request));
    }

    // Unidades Organizacionales
    /** @return list<array<string, mixed>> */
    public function listOrgUnits(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        return $this->service->listOrgUnits();
    }

    /** @return array<string, mixed> */
    public function createOrgUnit(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        return $this->service->createOrgUnit(HttpUtil::parseJson($request));
    }

    /** @return array<string, mixed> */
    public function updateOrgUnit(ServerRequestInterface $request, string $id): array
    {
        AuthContext::jwtUser($request);
        return $this->service->updateOrgUnit($id, HttpUtil::parseJson($request));
    }

    // Formulación
    /** @return list<array<string, mixed>> */
    public function listFormulations(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $params = $request->getQueryParams();
        $fiscalYearId = trim((string) ($params['fiscal_year_id'] ?? ''));
        $orgUnitId = isset($params['org_unit_id']) && trim((string) $params['org_unit_id']) !== '' ? trim((string) $params['org_unit_id']) : null;

        return $this->service->listFormulations($fiscalYearId, $orgUnitId);
    }

    /** @return array<string, mixed> */
    public function saveFormulation(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $params = $request->getQueryParams();
        $fiscalYearId = trim((string) ($params['fiscal_year_id'] ?? ''));
        
        $this->service->saveFormulation($fiscalYearId, HttpUtil::parseJson($request));
        return ['status' => 'success'];
    }

    // Modificaciones
    /** @return list<array<string, mixed>> */
    public function listModifications(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $params = $request->getQueryParams();
        $fiscalYearId = trim((string) ($params['fiscal_year_id'] ?? ''));

        return $this->service->listModifications($fiscalYearId);
    }

    /** @return array<string, mixed> */
    public function getModification(ServerRequestInterface $request, string $id): array
    {
        AuthContext::jwtUser($request);
        return $this->service->getModification($id);
    }

    /** @return array<string, mixed> */
    public function createModification(ServerRequestInterface $request): array
    {
        $u = AuthContext::jwtUser($request);
        return $this->service->createModification($u['userId'], HttpUtil::parseJson($request));
    }

    // Disponibilidad y Ejecución
    /** @return array<string, mixed> */
    public function checkAvailability(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $params = $request->getQueryParams();
        $fiscalYearId = trim((string) ($params['fiscal_year_id'] ?? ''));
        $orgUnitId = trim((string) ($params['org_unit_id'] ?? ''));
        $classifierId = trim((string) ($params['classifier_id'] ?? ''));
        $amount = (float) ($params['amount'] ?? 0.0);

        $info = $this->service->getAvailabilityInfo($fiscalYearId, $orgUnitId, $classifierId);
        $hasAvailability = $info['available'] >= $amount;

        return array_merge($info, [
            'has_availability' => $hasAvailability,
            'requested_amount' => $amount
        ]);
    }

    /** @return list<array<string, mixed>> */
    public function listExecutions(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $params = $request->getQueryParams();
        $fiscalYearId = trim((string) ($params['fiscal_year_id'] ?? ''));
        $orgUnitId = isset($params['org_unit_id']) && trim((string) $params['org_unit_id']) !== '' ? trim((string) $params['org_unit_id']) : null;
        $classifierId = isset($params['classifier_id']) && trim((string) $params['classifier_id']) !== '' ? trim((string) $params['classifier_id']) : null;
        $startDate = isset($params['start_date']) && trim((string) $params['start_date']) !== '' ? trim((string) $params['start_date']) : null;
        $endDate = isset($params['end_date']) && trim((string) $params['end_date']) !== '' ? trim((string) $params['end_date']) : null;

        return $this->service->listExecutions($fiscalYearId, $orgUnitId, $classifierId, $startDate, $endDate);
    }

    /** @return list<array<string, mixed>> */
    public function getExecutionSummary(ServerRequestInterface $request): array
    {
        AuthContext::jwtUser($request);
        $params = $request->getQueryParams();
        $fiscalYearId = trim((string) ($params['fiscal_year_id'] ?? ''));
        $orgUnitId = isset($params['org_unit_id']) && trim((string) $params['org_unit_id']) !== '' ? trim((string) $params['org_unit_id']) : null;
        $startDate = isset($params['start_date']) && trim((string) $params['start_date']) !== '' ? trim((string) $params['start_date']) : null;
        $endDate = isset($params['end_date']) && trim((string) $params['end_date']) !== '' ? trim((string) $params['end_date']) : null;

        return $this->service->getExecutionSummary($fiscalYearId, $orgUnitId, $startDate, $endDate);
    }
}
