<?php

declare(strict_types=1);

require_once __DIR__ . '/LicenseRemediationState.php';

final class MyronLicenseAuditRepository
{
    public function __construct(private readonly PDO $pdo)
    {
    }

    /**
     * @param array<string, mixed> $detail
     */
    public function append(
        string $eventType,
        string $outcome,
        string $reasonCode = '',
        array $detail = [],
        string $actorUserId = ''
    ): void {
        $statement = $this->pdo->prepare(
            'INSERT INTO license_audit_events (
                id, event_type, outcome, reason_code, plan, status,
                deployment_group, environment, detail_json, actor_user_id, created_at
            ) VALUES (
                :id, :event_type, :outcome, :reason_code, :plan, :status,
                :deployment_group, :environment, :detail_json, :actor_user_id, :created_at
            )'
        );
        $statement->execute([
            ':id' => myronGenerateId('lae'),
            ':event_type' => $this->clean($eventType, 80),
            ':outcome' => $this->clean($outcome, 40),
            ':reason_code' => $this->clean($reasonCode, 120),
            ':plan' => $this->clean((string) ($detail['plan'] ?? ''), 40),
            ':status' => $this->clean((string) ($detail['status'] ?? ''), 40),
            ':deployment_group' => $this->clean((string) ($detail['deploymentGroup'] ?? $detail['deployment_group'] ?? ''), 120),
            ':environment' => $this->clean((string) ($detail['environment'] ?? ''), 40),
            ':detail_json' => (string) json_encode($this->sanitizeDetail($detail), JSON_UNESCAPED_SLASHES),
            ':actor_user_id' => $this->clean($actorUserId, 32),
            ':created_at' => myronNow(),
        ]);
    }

    /**
     * @param array<string, mixed> $detail
     */
    public function appendRemediationReview(string $reasonCode, array $detail = [], string $actorUserId = ''): void
    {
        $severity = MyronLicenseRemediationState::severityForReason($reasonCode);
        $this->append('remediation.review', 'cataloged', $reasonCode, $detail + [
            'internalSeverity' => $severity,
            'humanReviewRequired' => $severity !== 'monitor',
        ], $actorUserId);
    }

    /**
     * @return list<array<string, mixed>>
     */
    public function listRecent(int $limit = 25): array
    {
        $safeLimit = max(1, min(100, $limit));
        $statement = $this->pdo->query(
            'SELECT * FROM license_audit_events ORDER BY created_at DESC LIMIT ' . $safeLimit
        );
        $rows = $statement ? $statement->fetchAll(PDO::FETCH_ASSOC) : [];
        return array_map(static fn (array $row): array => $row, $rows);
    }

    /**
     * @return list<array<string, mixed>>
     */
    public function listRecentByEventPrefix(string $eventTypePrefix, int $limit = 25): array
    {
        $safeLimit = max(1, min(100, $limit));
        $statement = $this->pdo->prepare(
            'SELECT * FROM license_audit_events
             WHERE event_type LIKE :event_type
             ORDER BY created_at DESC
             LIMIT ' . $safeLimit
        );
        $statement->execute([
            ':event_type' => $this->clean($eventTypePrefix, 80) . '%',
        ]);
        $rows = $statement->fetchAll(PDO::FETCH_ASSOC);
        return array_map(static fn (array $row): array => $row, $rows);
    }

    /**
     * @param array<string, mixed> $detail
     * @return array<string, mixed>
     */
    private function sanitizeDetail(array $detail): array
    {
        $blocked = [
            'licenseKey',
            'license_key',
            'deploymentKey',
            'deployment_key',
            'rawLicenseKey',
            'rawDeploymentKey',
        ];
        foreach ($blocked as $key) {
            unset($detail[$key]);
        }

        return $detail;
    }

    private function clean(string $value, int $maxLength): string
    {
        return substr(trim($value), 0, $maxLength);
    }
}
