<?php

declare(strict_types=1);

namespace App\Services\SupportCenter;

use Illuminate\Support\Carbon;

/**
 * Support Center 授权同步响应 → 本地快照字段映射。
 */
final class HostSystemAuthorizationSnapshotMapper
{
    /**
     * @param  array<string, mixed>  $data
     * @return array<string, mixed>
     */
    public function mapResponseToAttributes(array $data): array
    {
        return [
            'authorized' => (bool) ($data['authorized'] ?? false),
            'product_code' => $this->nullableString($data['product_code'] ?? null) ?? 'dberp',
            'site_no' => $this->nullableString($data['site_no'] ?? null),
            'license_no' => $this->nullableString($data['license_no'] ?? null),
            'license_holder' => $this->nullableString($data['license_holder'] ?? $data['holder'] ?? null),
            'service_status' => $this->nullableString($data['service_status'] ?? null),
            'expires_at' => $this->parseDateTime($data['expires_at'] ?? null),
            'bound_domains' => $this->normalizeStringList($data['bound_domains'] ?? null),
            'entitlements' => $this->normalizeEntitlements($data['entitlements'] ?? null),
            'raw_snapshot' => SupportCenterSnapshotSanitizer::sanitize($data),
        ];
    }

    private function nullableString(mixed $value): ?string
    {
        if (! is_string($value)) {
            return null;
        }

        $trimmed = trim($value);

        return $trimmed === '' ? null : $trimmed;
    }

    private function parseDateTime(mixed $value): ?Carbon
    {
        if (! is_string($value) || trim($value) === '') {
            return null;
        }

        try {
            return Carbon::parse($value)->utc();
        } catch (\Throwable) {
            return null;
        }
    }

    /**
     * @return list<string>|null
     */
    private function normalizeStringList(mixed $value): ?array
    {
        if ($value === null) {
            return null;
        }

        if (is_string($value)) {
            $trimmed = trim($value);

            return $trimmed === '' ? null : [$trimmed];
        }

        if (! is_array($value)) {
            return null;
        }

        $items = [];

        foreach ($value as $item) {
            if (is_string($item) && trim($item) !== '') {
                $items[] = trim($item);
            }
        }

        return $items === [] ? null : array_values(array_unique($items));
    }

    /**
     * @return array<string, bool>|null
     */
    private function normalizeEntitlements(mixed $value): ?array
    {
        if ($value === null) {
            return null;
        }

        if (! is_array($value)) {
            return null;
        }

        if (array_is_list($value)) {
            $mapped = [];

            foreach ($value as $item) {
                if (is_string($item) && $item !== '') {
                    $mapped[$item] = true;
                }
            }

            return $mapped === [] ? null : $mapped;
        }

        $mapped = [];

        foreach ($value as $key => $item) {
            if (! is_string($key) || $key === '') {
                continue;
            }

            $mapped[$key] = filter_var($item, FILTER_VALIDATE_BOOLEAN);
        }

        return $mapped === [] ? null : $mapped;
    }
}
