<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;

class FacebookAdsService
{
    private string $graphBase = 'https://graph.facebook.com/v19.0';
    private string $token;
    private string $account;

    public function __construct(string $token, string $account)
    {
        $this->token = $token;
        // Ensure act_ prefix
        $this->account = str_starts_with($account, 'act_') ? $account : "act_{$account}";
    }

    /**
     * Fetch summary metrics for multiple date presets
     */
    public function fetchSummary(): array
    {
        $presets = ['today', 'this_month', 'this_year', 'last_30d', 'last_7d'];
        $results = [];

        foreach ($presets as $preset) {
            $response = Http::timeout(20)->get("{$this->graphBase}/{$this->account}/insights", [
                'access_token' => $this->token,
                'date_preset'  => $preset,
                'fields'       => 'spend,impressions,clicks,ctr,cpc,actions,purchase_roas',
                'level'        => 'account',
            ]);

            if ($response->failed()) {
                $results[$preset] = null;
                continue;
            }

            $row = $response->json('data.0');
            $results[$preset] = $row ? [
                'spend'       => (float) ($row['spend'] ?? 0),
                'impressions' => (int)   ($row['impressions'] ?? 0),
                'clicks'      => (int)   ($row['clicks'] ?? 0),
                'ctr'         => (float) ($row['ctr'] ?? 0),
                'cpc'         => (float) ($row['cpc'] ?? 0),
                'purchases'   => $this->extractPurchases($row),
                'roas'        => (float) ($row['purchase_roas'][0]['value'] ?? 0),
            ] : null;
        }

        return $results;
    }

    /**
     * Fetch campaign-level breakdown
     */
    public function fetchCampaigns(string $datePreset = 'this_month'): array
    {
        $response = Http::timeout(20)->get("{$this->graphBase}/{$this->account}/campaigns", [
            'access_token' => $this->token,
            'fields'       => 'id,name,status,objective,insights{spend,impressions,clicks,ctr,cpc,actions,purchase_roas,cost_per_action_type}',
            'date_preset'  => $datePreset,
        ]);

        $campaigns = [];
        foreach ($response->json('data', []) as $c) {
            $ins = $c['insights']['data'][0] ?? null;
            $campaigns[] = [
                'id'          => $c['id'],
                'name'        => $c['name'],
                'status'      => $c['status'],
                'objective'   => $c['objective'] ?? '',
                'spend'       => (float) ($ins['spend'] ?? 0),
                'impressions' => (int)   ($ins['impressions'] ?? 0),
                'clicks'      => (int)   ($ins['clicks'] ?? 0),
                'ctr'         => round((float) ($ins['ctr'] ?? 0), 2),
                'cpc'         => round((float) ($ins['cpc'] ?? 0), 2),
                'purchases'   => $ins ? $this->extractPurchases($ins) : 0,
                'roas'        => round((float) ($ins['purchase_roas'][0]['value'] ?? 0), 2),
            ];
        }

        usort($campaigns, fn($a, $b) => $b['spend'] <=> $a['spend']);
        return $campaigns;
    }

    /**
     * Fetch top performing ads
     */
    public function fetchTopAds(string $datePreset = 'this_month'): array
    {
        $response = Http::timeout(25)->get("{$this->graphBase}/{$this->account}/ads", [
            'access_token'     => $this->token,
            'fields'           => 'id,name,status,adset{name},insights{spend,impressions,clicks,actions,purchase_roas,cost_per_action_type},creative{id,name,thumbnail_url}',
            'date_preset'      => $datePreset,
            'effective_status' => ['ACTIVE', 'PAUSED'],
            'limit'            => 25,
        ]);

        $ads = [];
        foreach ($response->json('data', []) as $ad) {
            $ins  = $ad['insights']['data'][0] ?? null;
            if (!$ins) continue;

            $spend     = (float) ($ins['spend'] ?? 0);
            $purchases = $this->extractPurchases($ins);
            $cps       = ($purchases > 0 && $spend > 0) ? round($spend / $purchases, 2) : null;

            $ads[] = [
                'id'          => $ad['id'],
                'name'        => $ad['name'],
                'status'      => $ad['status'],
                'adset_name'  => $ad['adset']['name'] ?? '',
                'spend'       => $spend,
                'impressions' => (int) ($ins['impressions'] ?? 0),
                'clicks'      => (int) ($ins['clicks'] ?? 0),
                'purchases'   => $purchases,
                'cps'         => $cps,
                'roas'        => round((float) ($ins['purchase_roas'][0]['value'] ?? 0), 2),
                'thumbnail'   => $ad['creative']['thumbnail_url'] ?? null,
            ];
        }

        // Sort best performers (lowest CPS) first
        usort($ads, function ($a, $b) {
            if ($a['cps'] === null && $b['cps'] === null) return $b['spend'] <=> $a['spend'];
            if ($a['cps'] === null) return 1;
            if ($b['cps'] === null) return -1;
            return $a['cps'] <=> $b['cps'];
        });

        return array_slice($ads, 0, 10);
    }

    /**
     * Verify token + account
     */
    public function verify(): array
    {
        $response = Http::timeout(10)->get("{$this->graphBase}/{$this->account}", [
            'access_token' => $this->token,
            'fields'       => 'id,name,currency,account_status',
        ]);

        if ($response->failed() || isset($response->json()['error'])) {
            return ['success' => false, 'error' => $response->json('error.message', 'Invalid credentials')];
        }

        return ['success' => true, 'account_name' => $response->json('name'), 'currency' => $response->json('currency', 'USD')];
    }

    private function extractPurchases(array $ins): int
    {
        foreach ($ins['actions'] ?? [] as $action) {
            if (in_array($action['action_type'], ['purchase', 'offsite_conversion.fb_pixel_purchase', 'onsite_web_app_purchase'])) {
                return (int) ($action['value'] ?? 0);
            }
        }
        return 0;
    }
}
