<?php

declare(strict_types=1);

namespace App\Services\SupportCenter;

use App\Exceptions\SupportCenter\SupportCenterException;
use App\Models\HostSystemAuthorization;

/**
 * 官方授权同步：成功更新快照；失败仅记录同步结果，保留上次成功快照。
 */
final class HostSystemAuthorizationSyncService
{
    public function __construct(
        private readonly SupportCenterOpenApiTransport $transport,
        private readonly SupportCenterRequestContextBuilder $contextBuilder,
        private readonly HostSystemAuthorizationSnapshotMapper $snapshotMapper,
        private readonly HostSiteOnboardingStatusCacheStore $siteStatusCacheStore,
        private readonly SupportCenterAuditLogger $auditLogger,
    ) {}

    public function sync(): HostSystemAuthorization
    {
        $record = HostSystemAuthorization::singleton();
        $siteNo = $this->resolveSiteNo();
        $licenseNo = $this->resolveLicenseNo();
        $payload = $this->contextBuilder->authorizationSyncBody(
            siteNo: $siteNo,
            licenseNo: $licenseNo,
        );

        $this->auditLogger->logAuthorizationSyncStarted($siteNo, $licenseNo);

        try {
            $responseData = $this->transport->post(
                SupportCenterOpenHostEndpoints::AUTHORIZATION_SYNC,
                $payload,
                'host_authorization_sync',
            );

            $record->fill($this->snapshotMapper->mapResponseToAttributes($responseData));
            $record->fill([
                'last_sync_status' => 'success',
                'last_sync_message' => null,
                'last_sync_error_code' => null,
                'last_synced_at' => now()->utc(),
            ]);
            $record->save();

            $this->auditLogger->logAuthorizationSyncCompleted(
                $record->site_no,
                $record->license_no,
                (bool) $record->authorized,
            );

            return $record->fresh() ?? $record;
        } catch (SupportCenterException $exception) {
            $record->fill([
                'last_sync_status' => 'failed',
                'last_sync_message' => $exception->userFacingMessage(),
                'last_sync_error_code' => $exception->errorCode(),
                'last_synced_at' => now()->utc(),
            ]);
            $record->save();

            $this->auditLogger->logAuthorizationSyncFailed($siteNo, $licenseNo, $exception);

            throw $exception;
        }
    }

    private function resolveSiteNo(): ?string
    {
        $configured = config('dberp.support_center.site_no');

        if (is_string($configured) && trim($configured) !== '') {
            return trim($configured);
        }

        $cached = $this->siteStatusCacheStore->get();
        $siteNo = is_array($cached) ? ($cached['site_no'] ?? null) : null;

        return is_string($siteNo) && trim($siteNo) !== '' ? trim($siteNo) : null;
    }

    private function resolveLicenseNo(): ?string
    {
        $configured = config('dberp.support_center.license_no');

        if (is_string($configured) && trim($configured) !== '') {
            return trim($configured);
        }

        $cached = $this->siteStatusCacheStore->get();
        if (! is_array($cached)) {
            return null;
        }

        $data = $cached['data'] ?? null;

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

        $licenseNo = $data['license_no'] ?? null;

        return is_string($licenseNo) && trim($licenseNo) !== '' ? trim($licenseNo) : null;
    }
}
