<?php

namespace App\Http\Controllers;

use App\Models\EmailCampaignClick;
use App\Models\EmailCampaignLink;
use App\Models\EmailCampaignRecipient;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class EmailCampaignTrackingController extends Controller
{
    /**
     * 1x1 transparent GIF returned regardless of token validity (avoid leaking).
     *
     * PRC-293 — KVKK gate. The campaign aggregate counters (opened_at,
     * opened_count) are anonymous and stay enabled even after the
     * recipient unsubscribes — they're operational metrics with no PII.
     * Individual IP+UA capture happens in click() below and IS gated.
     */
    public function open(string $token): Response
    {
        // Strip ".gif" suffix
        $token = preg_replace('/\.gif$/i', '', $token);

        $recipient = EmailCampaignRecipient::where('recipient_token', $token)->first();
        if ($recipient) {
            $recipient->forceFill([
                'opened_at' => $recipient->opened_at ?: now(),
                'opened_count' => $recipient->opened_count + 1,
            ])->save();

            if ($recipient->opened_count === 1 && $recipient->campaign) {
                $recipient->campaign->increment('open_count');
            }
        }

        // 1x1 transparent GIF (43 bytes)
        $gif = base64_decode('R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
        return response($gif, 200, [
            'Content-Type' => 'image/gif',
            'Content-Length' => strlen($gif),
            'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0',
            'Pragma' => 'no-cache',
        ]);
    }

    /**
     * Record click + redirect to original URL.
     */
    public function click(Request $request, string $token, string $linkHash): RedirectResponse
    {
        $recipient = EmailCampaignRecipient::where('recipient_token', $token)->first();
        $link = null;

        if ($recipient && $recipient->campaign_id) {
            $link = EmailCampaignLink::where('campaign_id', $recipient->campaign_id)
                ->where('link_hash', $linkHash)
                ->first();
        }

        if ($recipient && $link) {
            // PRC-293 — KVKK consent gate. If the recipient's subscriber
            // record has been unsubscribed, behavioural tracking (IP +
            // UA) must stop. Hash the IP / drop the UA so the click is
            // still counted (operational metric) without retaining
            // identifying data after consent withdrawal.
            $subscriber = $recipient->subscriber;
            $consentActive = ! $subscriber || $subscriber->status === 'subscribed';

            EmailCampaignClick::create([
                'recipient_id' => $recipient->id,
                'link_id' => $link->id,
                'ip' => $consentActive ? $request->ip() : null,
                'user_agent' => $consentActive ? substr((string) $request->userAgent(), 0, 500) : null,
                'clicked_at' => now(),
            ]);

            $recipient->forceFill([
                'clicked_at' => $recipient->clicked_at ?: now(),
                'click_count' => $recipient->click_count + 1,
            ])->save();

            if ($recipient->click_count === 1 && $recipient->campaign) {
                $recipient->campaign->increment('click_count');
            }
        }

        // PRC-265 — defend against admin-compromise that rewrites
        // EmailCampaignLink.url to a phishing/malicious destination
        // and laundered through our trusted domain. Two-layer guard:
        //   1) scheme allow-list (http/https only); kills `javascript:`,
        //      `data:`, `file://`, etc. payloads outright
        //   2) external host redirects are logged for forensic review
        $target = $link?->url ?: config('app.url');
        $parsed = parse_url((string) $target);
        $scheme = strtolower($parsed['scheme'] ?? '');

        if (! in_array($scheme, ['http', 'https'], true)) {
            return redirect(config('app.url'));
        }

        $appHost = parse_url((string) config('app.url'), PHP_URL_HOST);
        $targetHost = $parsed['host'] ?? '';
        if ($appHost && $targetHost && $targetHost !== $appHost) {
            \Illuminate\Support\Facades\Log::info('Email campaign click redirected externally', [
                'link_id' => $link?->id,
                'recipient_id' => $recipient?->id,
                'destination_host' => $targetHost,
                'ip' => $request->ip(),
            ]);
        }

        return redirect()->away($target);
    }
}
