<?php

namespace App\Services\Iys;

use App\Models\Client;
use App\Models\ClientConsent;
use App\Models\IysConsentSync;
use App\Models\Log;

/**
 * PRC-796 — Tek izin satırının İYS senkron orkestrasyonu (tekil push yolu).
 *
 * İdempotent: (client, iys_type, recipient, granted) → consent_hash tekildir.
 * Aynı mantıksal durum zaten synced ise tekrar push edilmez ($force ile
 * zorlanabilir). Toplu (refid) yol IysBatchSyncService'te.
 *
 * Tüm İYS yanıtları (yasal kanıt) sync satırının response alanında saklanır;
 * hassas kimlik bilgisi yanıtta bulunmaz.
 */
class IysSyncService
{
    public function __construct(
        protected IysApiService $api,
        protected IysConsentMapper $mapper,
    ) {}

    /**
     * Bir müşterinin belirli bir kanaldaki EN SON consent'ini İYS'ye push et.
     *
     * @return IysConsentSync|null  null = kapsam dışı / geçersiz alıcı (atlandı)
     */
    public function syncLatestForChannel(Client $client, string $channel, bool $force = false): ?IysConsentSync
    {
        $consent = $client->consents()
            ->where('channel', $channel)
            ->orderByDesc('created_at')
            ->orderByDesc('id')
            ->first();

        if (! $consent) {
            return null;
        }

        return $this->sync($client, $consent, $force);
    }

    /**
     * Somut bir consent satırını İYS'ye push et (idempotent upsert).
     */
    public function sync(Client $client, ClientConsent $consent, bool $force = false): ?IysConsentSync
    {
        $mapped = $this->mapper->map($client, $consent);

        // Kapsam dışı / geçersiz alıcı → izlenebilir "skipped" satırı bırak (varsa).
        if ($mapped === null) {
            return null;
        }

        $hash = IysConsentSync::buildHash(
            $client->id,
            $mapped['iys_type'],
            $mapped['recipient'],
            $mapped['granted'],
        );

        $sync = IysConsentSync::firstOrNew(['consent_hash' => $hash]);

        // Zaten senkronlanmış aynı durum → force değilse tekrar gönderme (dedupe).
        if (! $force && $sync->exists && $sync->status === IysConsentSync::STATUS_SYNCED) {
            return $sync;
        }

        $sync->fill([
            'client_id' => $client->id,
            'channel' => $consent->channel,
            'iys_type' => $mapped['iys_type'],
            'recipient' => $mapped['recipient'],
            'recipient_type' => $mapped['recipient_type'],
            'granted' => $mapped['granted'],
            'status' => IysConsentSync::STATUS_PENDING,
        ]);
        $sync->save();

        $result = $this->api->addConsent($mapped['consent']);

        if ($result['success']) {
            $sync->update([
                'status' => IysConsentSync::STATUS_SYNCED,
                'iys_recipient_status' => $mapped['granted'] ? 'ONAY' : 'RET',
                'response' => $this->safeResponse($result['response'] ?? []),
                'error_message' => null,
                'synced_at' => now(),
            ]);

            Log::create([
                'observer' => 'IysSyncService',
                'module' => 'iys',
                'method' => 'sync',
                'type' => Log::TYPE_SYSTEM,
                'client_id' => $client->id,
                'ip_address' => '0.0.0.0',
                'description' => "İYS consent synced ({$mapped['iys_type']}, ".($mapped['granted'] ? 'ONAY' : 'RET').')',
            ]);
        } else {
            $sync->update([
                'status' => IysConsentSync::STATUS_FAILED,
                'error_message' => $result['error'] ?? 'unknown',
                'response' => $this->safeResponse($result['response'] ?? []),
                'retries' => $sync->retries + 1,
            ]);
        }

        return $sync;
    }

    /**
     * İYS yanıtından yalnız güvenli/kanıt alanları — hassas veri sızmaz.
     */
    protected function safeResponse(array $response): array
    {
        return array_intersect_key($response, array_flip([
            'requestId', 'refid', 'transactionId', 'status', 'code',
            'message', 'creationDate', 'httpStatus',
        ]));
    }
}
