<?php

namespace App\Services;

use App\Models\LoanProduct;
use Carbon\CarbonImmutable;
use LogicException;

class RepaymentScheduleGenerator
{
    public function __construct(private MoneyMath $money, private RepaymentPeriodService $periods, private LoanCalculationService $calculator) {}

    /** @param list<string|CarbonImmutable> $customDates @return array{summary:array<string,mixed>,installments:list<array<string,mixed>>} */
    public function generate(LoanProduct $product, string|int $principal, CarbonImmutable $startDate, array $customDates = []): array
    {
        $dates = $this->periods->dueDates($product, $startDate, $customDates);
        $detail = $this->calculator->calculateDetailed($product, $principal, $startDate, $customDates);
        $count = count($dates);
        $principalParts = $this->money->allocate($detail['_principal_minor'], $count);
        $interestParts = $detail['_interest_parts_minor'];
        $feeParts = $this->money->allocate($detail['_fees_minor'], $count);
        $installments = []; $sum = 0;
        foreach ($dates as $i => $date) {
            $amount = $principalParts[$i] + $interestParts[$i] + $feeParts[$i]; $sum += $amount;
            $installments[] = [
                'number'=>$i+1,'principal'=>$this->money->fromMinor($principalParts[$i]),'interest'=>$this->money->fromMinor($interestParts[$i]),
                'fees'=>$this->money->fromMinor($feeParts[$i]),'amount_due'=>$this->money->fromMinor($amount),'due_date'=>$date->toDateString(),
                'amount_paid'=>'0.00','remaining'=>$this->money->fromMinor($amount),'status'=>'upcoming',
            ];
        }
        if ($sum !== $detail['_total_minor']) throw new LogicException('Generated schedule does not reconcile to total repayment.');
        $summary = $detail; unset($summary['_principal_minor'],$summary['_interest_minor'],$summary['_fees_minor'],$summary['_total_minor'],$summary['_interest_parts_minor']);
        return ['summary'=>$summary,'installments'=>$installments];
    }
}
