<?php

namespace App\Services\Consent;

use App\Enums\ConsentChannel;
use App\Enums\ConsentSource;
use App\Jobs\SyncConsentToIysJob;
use App\Models\Client;
use App\Models\ClientConsent;
use App\Models\Log;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class MarketingConsentService
{
    public function grant(Client $client, ConsentChannel $channel, ConsentSource $source, ?Request $request = null): ClientConsent
    {
        return $this->record($client, $channel, $source, true, $request);
    }

    public function withdraw(Client $client, ConsentChannel $channel, ConsentSource $source, ?Request $request = null): ClientConsent
    {
        return $this->record($client, $channel, $source, false, $request);
    }

    public function isGranted(Client $client, ConsentChannel $channel): bool
    {
        $latest = $client->consents()
            ->where('channel', $channel->value)
            ->orderByDesc('created_at')
            ->orderByDesc('id')
            ->first();

        return (bool) $latest?->granted;
    }

    public function history(Client $client, ?ConsentChannel $channel = null): \Illuminate\Database\Eloquent\Collection
    {
        $q = $client->consents()
            ->orderByDesc('created_at')
            ->orderByDesc('id');
        if ($channel) {
            $q->where('channel', $channel->value);
        }

        return $q->get();
    }

    protected function record(Client $client, ConsentChannel $channel, ConsentSource $source, bool $granted, ?Request $request): ClientConsent
    {
        return DB::transaction(function () use ($client, $channel, $source, $granted, $request) {
            $row = ClientConsent::create([
                'client_id' => $client->id,
                'channel' => $channel->value,
                'granted' => $granted,
                'granted_at' => $granted ? now() : null,
                'withdrawn_at' => $granted ? null : now(),
                'ip_address' => $request?->ip(),
                'user_agent' => $request?->userAgent(),
                'source' => $source->value,
                'locale' => app()->getLocale(),
            ]);

            Log::create([
                'observer' => 'MarketingConsentService',
                'module' => 'consent',
                'method' => $granted ? 'grant' : 'withdraw',
                'type' => $granted ? Log::TYPE_CONSENT_GRANTED : Log::TYPE_CONSENT_WITHDRAWN,
                'client_id' => $client->id,
                // logs.ip_address is NOT NULL → keep sentinel for system-context rows.
                'ip_address' => $request?->ip() ?? '0.0.0.0',
                // logs.user_agent is nullable → no sentinel needed.
                'user_agent' => $request?->userAgent(),
                'description' => "Consent {$channel->value} ".($granted ? 'granted' : 'withdrawn')." via {$source->value}",
            ]);

            // PRC-796 — İYS'ye real-time push (yalnız İYS kapsamındaki kanallar;
            // job içinde İYS kapalıysa no-op, kapsam-dışı kanal atlanır).
            if (array_key_exists($channel->value, config('iys.channel_map', []))) {
                DB::afterCommit(fn () => SyncConsentToIysJob::dispatch($client->id, $channel->value));
            }

            return $row;
        });
    }
}
