<?php

namespace Modules\Accounts\Services;

use Carbon\Carbon;
use Modules\Accounts\Models\AccountingPeriod;
use Modules\Accounts\Repositories\AccountingPeriodRepository;
use Modules\Core\Exceptions\ApiValidationException;
use Modules\Core\Exceptions\BusinessException;

class AccountingPeriodService
{
    public function __construct(
        protected AccountingPeriodRepository $accountingPeriodRepo,
    ) {}

    public function current(): ?AccountingPeriod
    {
        return $this->accountingPeriodRepo->current();
    }

    public function detect(string|Carbon $date): AccountingPeriod
    {
        $period = $this->accountingPeriodRepo->findByDate($date);

        if (!$period) {
            ApiValidationException::message('No accounting period found for the selected date.');
        }

        if ($period->is_closed) {
            BusinessException::message('Accounting period is closed.');
        }

        if ($period->is_locked) {
            BusinessException::message('Accounting period is locked.');
        }

        return $period;
    }

    public function ensureOpen(AccountingPeriod $period, string|Carbon $transactionDate): void
    {
        $transactionDate = Carbon::parse($transactionDate);

        if ($period->is_closed) {
            BusinessException::message('Accounting period is closed.');
        }

        if ($period->is_locked) {
            BusinessException::message('Accounting period is locked.');
        }

        if ($period->lock_date && $transactionDate->lte($period->lock_date)) {
            BusinessException::message(
                sprintf(
                    'Transactions on or before %s are locked.',
                    $period->lock_date->format('d M Y')
                )
            );
        }
    }

    public function clearCache(): void
    {
        $this->accountingPeriodRepo->clearCache();
    }
}
