<?php

namespace App\Services;

use App\Models\Server;

/**
 * Turns a server's hardening state into a single security-posture SCORE. Reuses
 * HardeningService::state() (the CIS-relevant gates: SSH root/password, fail2ban, firewall) rather
 * than re-probing. `neutral` items (auto-updates = an operator preference, not a gate) and
 * OS-unsupported items don't count toward the score. The remediation for a failing check is the
 * existing hardening toggle on the server-details page.
 */
class PostureService
{
    public function __construct(private HardeningService $hardening) {}

    /**
     * @return array{score:int, rating:string, passed:int, applicable:int,
     *               checks:array<int, array{key:string,label:string,detail:string,secure:bool,supported:bool,neutral:bool,counts:bool}>}
     */
    public function score(Server $server): array
    {
        $items = $this->hardening->state($server); // throws if the host can't be read

        $checks = [];
        $passed = 0;
        $applicable = 0;

        foreach ($items as $it) {
            // A check counts toward the score only when the OS supports it AND it's a real security
            // gate (not the neutral auto-updates preference).
            $counts = $it['supported'] && ! $it['neutral'];
            if ($counts) {
                $applicable++;
                if ($it['secure']) {
                    $passed++;
                }
            }

            $checks[] = [
                'key' => $it['key'],
                'label' => $it['label'],
                'detail' => $it['detail'],
                'secure' => (bool) $it['secure'],
                'supported' => (bool) $it['supported'],
                'neutral' => (bool) $it['neutral'],
                'counts' => $counts,
            ];
        }

        $score = $applicable > 0 ? (int) round($passed / $applicable * 100) : 100;

        return [
            'score' => $score,
            'rating' => $this->rating($score),
            'passed' => $passed,
            'applicable' => $applicable,
            'checks' => $checks,
        ];
    }

    /** strong ≥90 · fair ≥60 · weak below — mapped to the status triad in the UI. */
    private function rating(int $score): string
    {
        return $score >= 90 ? 'strong' : ($score >= 60 ? 'fair' : 'weak');
    }
}
