<?php

namespace App\Services\CreditScore\Components;

use App\Services\CreditScore\ComponentResult;

class LoanHistoryComponent
{
    public function __construct(private readonly array $configuration)
    {
    }

    public function calculate(array $data): ComponentResult
    {
        $totalLoans = max(0, (int) ($data['total_loans'] ?? 0));
        $neutral = (float) ($this->configuration['thin_file']['neutral_component_score'] ?? 50);

        if ($totalLoans === 0) {
            return new ComponentResult(
                'loan_history',
                $neutral,
                false,
                ['history_available' => false, 'total_loans' => 0],
                [],
                ['Completed loan history is not yet available.'],
            );
        }

        $completedLoans = max(0, (int) ($data['completed_loans'] ?? 0));
        $activeGoodLoans = max(0, (int) ($data['active_good_loans'] ?? 0));
        $writeOffs = max(0, (int) ($data['write_offs'] ?? 0));
        $unresolvedWriteOffs = max(0, (int) ($data['unresolved_write_offs'] ?? 0));
        $restructurings = max(0, (int) ($data['restructurings'] ?? 0));
        $recoveryRatio = $this->clamp((float) ($data['write_off_recovery_ratio'] ?? 0), 0, 1);

        $score = 50;
        $score += min(24, $completedLoans * 8);
        $score += min(12, $activeGoodLoans * 4);
        $score -= min(24, $restructurings * 8);
        $score -= min(50, $writeOffs * 25);
        $score -= min(40, $unresolvedWriteOffs * 20);

        if ($writeOffs > 0) {
            $score += min(10, $recoveryRatio * 10);
        }

        $score = $this->clamp($score, 0, 100);
        $positive = [];
        $negative = [];

        if ($completedLoans > 0) {
            $positive[] = "{$completedLoans} loan(s) were successfully completed.";
        }
        if ($activeGoodLoans > 0) {
            $positive[] = "{$activeGoodLoans} active loan(s) are in good standing.";
        }
        if ($restructurings > 0) {
            $negative[] = "{$restructurings} loan restructuring(s) are recorded.";
        }
        if ($writeOffs > 0) {
            $negative[] = "{$writeOffs} write-off(s) are recorded.";
        }
        if ($unresolvedWriteOffs > 0) {
            $negative[] = "{$unresolvedWriteOffs} write-off(s) remain unresolved.";
        }

        return new ComponentResult(
            'loan_history',
            $score,
            true,
            [
                'history_available' => true,
                'total_loans' => $totalLoans,
                'completed_loans' => $completedLoans,
                'active_good_loans' => $activeGoodLoans,
                'write_offs' => $writeOffs,
                'unresolved_write_offs' => $unresolvedWriteOffs,
                'restructurings' => $restructurings,
                'write_off_recovery_ratio' => round($recoveryRatio, 4),
            ],
            $positive,
            $negative,
        );
    }

    private function clamp(float $value, float $minimum, float $maximum): float
    {
        return max($minimum, min($maximum, $value));
    }
}
