<?php

namespace App\Http\Controllers;

use App\Models\Campaign;
use App\Models\CampaignEvent;
use App\Models\Contact;
use App\Services\BusinessSettings;
use App\Services\TrackingHelper;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Http\RedirectResponse;

class TrackingController extends Controller
{
    // 1x1 transparent GIF
    private const PIXEL = 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';

    public function open(int $campaign, int $contact, string $token): Response
    {
        // Still serve the pixel either way (a broken image in a delivered
        // email looks like a bug), but don't record anything if this
        // tenant has since disabled tracking  e.g. a stale pixel URL from
        // an email sent before tracking was turned off.
        if (TrackingHelper::verify($campaign, $contact, $token) && BusinessSettings::trackingEnabled($campaign)) {
            $this->record($campaign, $contact, 'open');
        }

        return response(base64_decode(self::PIXEL), 200, [
            'Content-Type'  => 'image/gif',
            'Cache-Control' => 'no-cache, no-store, must-revalidate',
            'Pragma'        => 'no-cache',
            'Expires'       => '0',
        ]);
    }

    public function click(int $campaign, int $contact, string $token, Request $request): RedirectResponse
    {
        $url = $request->query('url', '/');

        if (TrackingHelper::verify($campaign, $contact, $token) && BusinessSettings::trackingEnabled($campaign)) {
            $this->record($campaign, $contact, 'click', $url);
        }

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

    public function unsubscribe(int $campaign, int $contact, string $token): Response|RedirectResponse|\Illuminate\Contracts\View\View
    {
        if (!TrackingHelper::verify($campaign, $contact, $token)) {
            abort(404);
        }

        $campaignModel = Campaign::find($campaign);
        $contactModel  = Contact::find($contact);

        if ($contactModel && $contactModel->status !== 'unsubscribed') {
            $contactModel->update(['status' => 'unsubscribed']);
            $this->record($campaign, $contact, 'unsubscribe');
        }

        $redirectUrl = BusinessSettings::emailSettings($campaign)['unsubscribe_redirect_url'];
        if ($redirectUrl) {
            return redirect()->away($redirectUrl);
        }

        $campaignTitle = $campaignModel?->title ?? 'this campaign';

        return response(
            '<html><head><meta charset="utf-8"><title>Unsubscribed</title>
            <style>body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#f9fafb;}
            .box{background:#fff;border:1px solid #e5e7eb;border-radius:12px;padding:40px;max-width:420px;text-align:center;}
            h2{color:#111827;margin:0 0 12px}p{color:#6b7280;margin:0;font-size:14px;line-height:1.6}
            .icon{font-size:48px;margin-bottom:16px}</style></head>
            <body><div class="box"><div class="icon">✅</div>
            <h2>You\'re unsubscribed</h2>
            <p>You\'ve been successfully removed from <strong>' . e($campaignTitle) . '</strong>.<br>You won\'t receive any more emails from this campaign.</p>
            </div></body></html>',
            200,
            ['Content-Type' => 'text/html']
        );
    }

    public function conversion(int $campaign, int $contact, string $token): Response
    {
        if (TrackingHelper::verify($campaign, $contact, $token) && BusinessSettings::trackingEnabled($campaign)) {
            $this->record($campaign, $contact, 'conversion');
        }

        return response(base64_decode(self::PIXEL), 200, [
            'Content-Type'  => 'image/gif',
            'Cache-Control' => 'no-cache, no-store, must-revalidate',
        ]);
    }

    private function record(int $campaignId, int $contactId, string $type, ?string $url = null): void
    {
        $lastSentEvent = CampaignEvent::where('campaign_id', $campaignId)
            ->where('contact_id', $contactId)
            ->where('event_type', 'sent')
            ->whereNotNull('node_id')
            ->latest('id')
            ->first();
        $nodeId = $lastSentEvent?->node_id;

        $existing = CampaignEvent::where('campaign_id', $campaignId)
            ->where('contact_id', $contactId)
            ->where('event_type', $type)
            ->where('node_id', $nodeId)
            ->first();
        $isFirst = !$existing;

        // Opens are stored once per contact per node: a repeat open refreshes the
        // existing row (updated_at = last opened) instead of adding another.
        if ($type === 'open' && $existing) {
            $existing->fill([
                'ip'         => request()->ip(),
                'user_agent' => substr(request()->userAgent() ?? '', 0, 512),
            ]);
            $existing->touch();
            Campaign::where('id', $campaignId)->increment('opens_count');
            return;
        }

        CampaignEvent::create([
            'campaign_id' => $campaignId,
            'contact_id'  => $contactId,
            'node_id'     => $nodeId,
            'event_type'  => $type,
            'url'         => $url ? substr($url, 0, 2048) : null,
            'ip'          => request()->ip(),
            'user_agent'  => substr(request()->userAgent() ?? '', 0, 512),
            'reason'      => match ($type) {
                'open'        => 'Email opened.',
                'click'       => 'Link clicked' . ($url ? ': ' . substr($url, 0, 100) : '.'),
                'unsubscribe' => 'Recipient unsubscribed.',
                'spam'        => 'Email went to Spam / Spam complaint.',
                'bounced'     => 'Email bounced.',
                default       => null,
            },
        ]);

        // Always increment total count
        Campaign::where('id', $campaignId)->increment("{$type}s_count");

        // Increment unique count only on first occurrence per contact
        if ($isFirst) {
            $uniqueField = match ($type) {
                'open'         => 'unique_opens',
                'click'        => 'unique_clicks',
                'unsubscribe'  => 'unsubscribes_count',
                'conversion'   => 'conversions_count',
                default        => null,
            };
            if ($uniqueField && $uniqueField !== "{$type}s_count") {
                Campaign::where('id', $campaignId)->increment($uniqueField);
            }

            $this->logContactActivity($campaignId, $contactId, $type);
        }
    }

    // Feed the contact's activity log on the first occurrence per campaign,
    // so repeat opens/clicks don't flood the timeline
    private function logContactActivity(int $campaignId, int $contactId, string $type): void
    {
        $activity = match ($type) {
            'open'        => ['email_opened',  'Opened campaign email'],
            'click'       => ['email_clicked', 'Clicked a link in campaign'],
            'unsubscribe' => ['unsubscribed',  'Unsubscribed via email link in campaign'],
            'conversion'  => ['conversion',    'Conversion recorded from campaign'],
            default       => null,
        };

        if (!$activity) {
            return;
        }

        $contactModel = Contact::find($contactId);
        if (!$contactModel) {
            return;
        }

        $title = Campaign::find($campaignId)?->title ?? "campaign #{$campaignId}";
        $contactModel->logActivity($activity[0], $activity[1] . ': "' . $title . '"');
    }
}
