<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\IntegrationModel;
use App\Models\LeadModel;
use App\Models\WebhookEventModel;

/**
 * MetaIntegrationService
 *
 * Facebook and Instagram Lead Ads (and TikTok's equivalent Lead
 * Generation) all work the same way at the point they matter to A&B
 * Hub: a webhook fires with a leadgen_id, the platform's Leads
 * Retrieval API is called to fetch the actual submitted field values,
 * and a real Lead row is created here from them — reusing
 * LeadModel::findPotentialDuplicates() exactly like every other lead
 * entry point (chatbot, CSV import, manual entry) so duplicate
 * detection is consistent everywhere.
 *
 * Meta Pixel / Google Analytics are simpler: just tracking IDs stored
 * in `integrations.credentials_encrypted` and read back by whichever
 * public-facing page embeds the tracking snippet — no webhook, no
 * OAuth, just configuration.
 */
final class MetaIntegrationService
{
    public function __construct(
        private readonly IntegrationModel $integrations = new IntegrationModel(),
        private readonly LeadModel $leads = new LeadModel(),
        private readonly WebhookEventModel $webhookEvents = new WebhookEventModel()
    ) {
    }

    /**
     * Processes one lead-ad webhook payload. The real field-value
     * retrieval call (platform-specific: Graph API for Facebook/
     * Instagram, TikTok's Lead API) is intentionally abstracted behind
     * $fieldFetcher so this method's lead-creation logic is testable
     * without a live network call — see AiToolService's docblock for
     * the same testability principle applied here.
     *
     * @param callable(string $leadgenId): array{email:?string,phone:?string,full_name:?string} $fieldFetcher
     */
    public function processLeadAdWebhook(string $provider, string $leadgenId, int $businessLineId, callable $fieldFetcher): array
    {
        $eventId = $this->webhookEvents->record($provider, 'leadgen', ['leadgen_id' => $leadgenId]);

        try {
            $fields = $fieldFetcher($leadgenId);

            if (empty($fields['email']) && empty($fields['phone'])) {
                $this->webhookEvents->markFailed($eventId, 'Lead ad submission had no email or phone.');

                return ['success' => false, 'error' => 'No contact info in submission.'];
            }

            $duplicates = $this->leads->findPotentialDuplicates($fields['email'] ?? null, $fields['phone'] ?? null);
            if ($duplicates !== []) {
                $this->webhookEvents->markProcessed($eventId);

                return ['success' => true, 'lead_id' => (int) $duplicates[0]['id'], 'duplicate' => true];
            }

            $newStageId = \App\Core\Database::connection()->query("SELECT id FROM lead_stages WHERE slug = 'new' LIMIT 1")->fetchColumn();
            $nameParts = explode(' ', trim((string) ($fields['full_name'] ?? 'Lead Ad Submission')), 2);

            $leadId = $this->leads->insert([
                'business_line_id' => $businessLineId,
                'lead_stage_id' => (int) $newStageId,
                'first_name' => $nameParts[0],
                'last_name' => $nameParts[1] ?? null,
                'email' => $fields['email'] ?? null,
                'phone' => $fields['phone'] ?? null,
                'notes' => "Captured via {$provider} Lead Ads.",
                'currency' => 'CAD',
            ]);

            ActivityLogger::record('lead', $leadId, 'lead_created', "Lead captured via {$provider} Lead Ads");
            $this->webhookEvents->markProcessed($eventId);

            return ['success' => true, 'lead_id' => $leadId, 'duplicate' => false];
        } catch (\Throwable $e) {
            $this->webhookEvents->markFailed($eventId, $e->getMessage());

            return ['success' => false, 'error' => $e->getMessage()];
        }
    }

    public function pixelId(): ?string
    {
        return $this->integrations->credentialsFor('meta_pixel')['pixel_id'] ?? null;
    }

    public function googleAnalyticsId(): ?string
    {
        return $this->integrations->credentialsFor('google_analytics')['measurement_id'] ?? null;
    }
}
