<?php

namespace App\Services\CreditScore\Components;

use App\Services\CreditScore\ComponentResult;

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

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

        if ($total === 0) {
            return new ComponentResult(
                'repayment_behaviour',
                $neutral,
                false,
                ['history_available' => false, 'total_installments' => 0],
                [],
                ['Repayment history is not yet available.'],
            );
        }

        $onTime = max(0, (int) ($data['on_time_installments'] ?? 0));
        $withinGrace = max(0, (int) ($data['within_grace_installments'] ?? 0));
        $missed = max(0, (int) ($data['missed_installments'] ?? 0));
        $currentDaysOverdue = max(0, (int) ($data['current_days_overdue'] ?? 0));
        $maxDaysOverdue = max(0, (int) ($data['max_days_overdue'] ?? 0));
        $overdueRatio = $this->clamp((float) ($data['overdue_ratio'] ?? 0), 0, 1);
        $latePenaltyCount = max(0, (int) ($data['late_penalty_count'] ?? 0));
        $seriousArrearsLoans = max(0, (int) ($data['serious_arrears_loans'] ?? 0));

        $punctualityRate = $this->clamp(($onTime + (0.6 * $withinGrace)) / $total, 0, 1);
        $missedRate = $this->clamp($missed / $total, 0, 1);

        $score = $punctualityRate * 100;
        $score -= $missedRate * 25;
        $score -= min(25, ($currentDaysOverdue / 90) * 25);
        $score -= min(15, ($maxDaysOverdue / 90) * 15);
        $score -= min(15, $overdueRatio * 30);
        $score -= min(10, $latePenaltyCount * 2);
        $score -= min(20, $seriousArrearsLoans * 10);
        $score = $this->clamp($score, 0, 100);

        $positive = [];
        $negative = [];

        if ($punctualityRate >= 0.9) {
            $positive[] = 'Most installments were paid on time.';
        } elseif ($punctualityRate < 0.7) {
            $negative[] = 'A significant share of installments were not paid on time.';
        }

        if ($currentDaysOverdue > 0) {
            $negative[] = "The customer is currently {$currentDaysOverdue} days overdue.";
        }
        if ($missed > 0) {
            $negative[] = "{$missed} installment(s) were missed.";
        }

        return new ComponentResult(
            'repayment_behaviour',
            $score,
            true,
            [
                'history_available' => true,
                'total_installments' => $total,
                'on_time_rate' => round($onTime / $total, 4),
                'punctuality_rate' => round($punctualityRate, 4),
                'missed_rate' => round($missedRate, 4),
                'current_days_overdue' => $currentDaysOverdue,
                'max_days_overdue' => $maxDaysOverdue,
                'overdue_ratio' => round($overdueRatio, 4),
                'late_penalty_count' => $latePenaltyCount,
                'serious_arrears_loans' => $seriousArrearsLoans,
            ],
            $positive,
            $negative,
        );
    }

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