<?php

namespace App\Services\CreditScore\Components;

use App\Services\CreditScore\ComponentResult;

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

    public function calculate(array $data): ComponentResult
    {
        $required = (bool) ($data['collateral_required'] ?? false);
        $neutral = (float) ($this->configuration['thin_file']['neutral_component_score'] ?? 50);

        if (! $required) {
            return new ComponentResult(
                'collateral',
                $neutral,
                false,
                ['required' => false],
            );
        }

        $principal = max(0, (float) ($data['relevant_principal'] ?? 0));
        $acceptedValue = max(0, (float) ($data['accepted_collateral_value'] ?? 0));
        $validCollateral = (bool) ($data['valid_collateral'] ?? false);

        if ($principal <= 0) {
            return new ComponentResult(
                'collateral',
                $neutral,
                false,
                ['required' => true, 'valid_collateral' => $validCollateral, 'relevant_principal' => 0],
                [],
                ['Collateral coverage cannot be calculated without a relevant principal amount.'],
            );
        }

        $coverageRatio = $acceptedValue / $principal;
        $thresholds = $this->configuration['thresholds']['collateral_coverage_ratio'] ?? [];
        $excellent = max(0.01, (float) ($thresholds['excellent_min'] ?? 1.50));
        $good = max(0.01, (float) ($thresholds['good_min'] ?? 1.20));
        $minimum = max(0.01, (float) ($thresholds['minimum_acceptable'] ?? 1.00));

        if ($coverageRatio >= $excellent) {
            $score = 100;
        } elseif ($coverageRatio >= $good) {
            $score = 80;
        } elseif ($coverageRatio >= $minimum) {
            $score = 60;
        } else {
            $score = $this->clamp(($coverageRatio / $minimum) * 60, 0, 60);
        }

        if (! $validCollateral) {
            $score = min($score, 25);
        }

        $positive = [];
        $negative = [];
        if ($validCollateral && $coverageRatio >= $good) {
            $positive[] = 'Accepted collateral provides strong coverage for the relevant principal.';
        }
        if ($coverageRatio < $minimum) {
            $negative[] = 'Accepted collateral value is below the configured minimum coverage level.';
        }
        if (! $validCollateral) {
            $negative[] = 'Required collateral is not currently in an acceptable credit-relevant state.';
        }

        return new ComponentResult(
            'collateral',
            $score,
            true,
            [
                'required' => true,
                'valid_collateral' => $validCollateral,
                'accepted_collateral_value' => round($acceptedValue, 2),
                'relevant_principal' => round($principal, 2),
                'coverage_ratio' => round($coverageRatio, 4),
            ],
            $positive,
            $negative,
        );
    }

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