<?php

/**
 * Facebook Ads – Autonomous AI Agent Controller v1.0
 *
 * الذكاء الاصطناعي يُنشئ ويُدير الحملات بشكل مستقل:
 * 1. يحلل المنتج ويختار الاستراتيجية
 * 2. يكتب 3 نصوص إعلانية للـ A/B Testing
 * 3. يحدد الجمهور تلقائياً
 * 4. يوزع الميزانية ذكياً
 * 5. يُطلق الحملة مباشرة
 * 6. يراقب الأداء ويُحسّن تلقائياً
 */
class FbAdsAgentController
{
    private const FB_API = 'https://graph.facebook.com/v19.0';

    private function cfg(): array
    {
        return db()->query("SELECT * FROM fb_settings LIMIT 1")->fetch(\PDO::FETCH_ASSOC) ?: [];
    }

    private function json(array $data, int $code = 200): never
    {
        http_response_code($code);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($data, JSON_UNESCAPED_UNICODE);
        exit;
    }

    // ── Agent Dashboard ───────────────────────────────────────────────
    public function index(): void
    {
        FbAdsLicenseGuard::check();
        FbLang::load();

        $pdo = db();
        $cfg = $this->cfg();

        $agents = $pdo->query("
            SELECT a.*, p.title AS product_title, p.featured_image,
                   (SELECT COUNT(*) FROM fb_campaigns WHERE agent_id=a.id) AS campaign_count,
                   (SELECT COALESCE(SUM(spend),0) FROM fb_campaigns WHERE agent_id=a.id) AS total_spent
            FROM fb_agents a
            LEFT JOIN products p ON p.id = a.product_id
            ORDER BY a.created_at DESC LIMIT 20
        ")->fetchAll(\PDO::FETCH_ASSOC);

        $products = $pdo->query("
            SELECT id, title, featured_image, price, currency
            FROM products WHERE status='active' ORDER BY updated_at DESC LIMIT 50
        ")->fetchAll(\PDO::FETCH_ASSOC);

        $isConfigured = !empty($cfg['access_token']) && !empty($cfg['ad_account_id']) && !empty($cfg['page_id']);
        $aiAvailable  = $this->isAiAvailable();

        require ROOT_PATH . '/plugins/FacebookAds/templates/agent.php';
    }

    // ── Step 1: AI Analysis & Strategy ───────────────────────────────
    public function analyze(): void
    {
        $productId = (int)($_POST['product_id'] ?? 0);
        $budget    = (float)($_POST['monthly_budget'] ?? 0);
        $goal      = trim($_POST['goal'] ?? 'sales');
        $lang      = trim($_POST['lang'] ?? 'ar');

        if (!$productId || $budget < 500) {
            $this->json(['success' => false, 'message' => 'Product and budget (min 500 DZD) required.']);
        }

        $product = db()->prepare("SELECT * FROM products WHERE id=? LIMIT 1");
        $product->execute([$productId]);
        $product = $product->fetch(\PDO::FETCH_ASSOC);
        if (!$product) $this->json(['success' => false, 'message' => 'Product not found.']);

        $price = $product['sale_price'] ?: $product['price'];
        $desc  = strip_tags($product['short_description'] ?? $product['description'] ?? '');
        $desc  = mb_substr($desc, 0, 400);

        $goalAr = ['sales'=>'زيادة المبيعات','awareness'=>'الوعي بالمنتج','engagement'=>'زيادة التفاعل'][$goal] ?? 'زيادة المبيعات';
        $langInstr = $lang === 'ar'
            ? \Core\App\Services\AiService::getDialectInstruction(null, 'ar') . ' فقط.'
            : 'Reply in English only.';

        $prompt = <<<PROMPT
{$langInstr}

أنت وكيل تسويق رقمي خبير متخصص في Facebook Ads.
مهمتك: تحليل هذا المنتج وبناء استراتيجية إعلانية كاملة.

المنتج: {$product['title']}
السعر: {$price} {$product['currency']}
الوصف: {$desc}
الميزانية الشهرية: {$budget} {$product['currency']}
الهدف: {$goalAr}

قم بالآتي وأعطِ النتيجة بـ JSON فقط بلا markdown:
{
  "strategy_name": "اسم الاستراتيجية",
  "strategy_summary": "ملخص الاستراتيجية في جملتين",
  "objective": "OUTCOME_SALES|OUTCOME_TRAFFIC|OUTCOME_AWARENESS|OUTCOME_ENGAGEMENT",
  "duration_days": 14,
  "daily_budget": 200,
  "targeting": {
    "age_min": 22,
    "age_max": 45,
    "gender": "all|1|2",
    "countries": ["DZ"],
    "interest_keywords": ["كلمة1", "كلمة2", "كلمة3"]
  },
  "ads": [
    {
      "variant": "A",
      "approach": "احترافي",
      "primary_text": "نص الإعلان الأول (max 125 chars)",
      "headline": "العنوان (max 40 chars)",
      "description": "الوصف (max 30 chars)",
      "why": "لماذا هذا الأسلوب؟"
    },
    {
      "variant": "B",
      "approach": "عاجل/ترويجي",
      "primary_text": "نص الإعلان الثاني",
      "headline": "العنوان",
      "description": "الوصف",
      "why": "لماذا هذا الأسلوب؟"
    },
    {
      "variant": "C",
      "approach": "قصصي/عاطفي",
      "primary_text": "نص الإعلان الثالث",
      "headline": "العنوان",
      "description": "الوصف",
      "why": "لماذا هذا الأسلوب؟"
    }
  ],
  "budget_distribution": {
    "week1_percent": 40,
    "week2_percent": 35,
    "week3_percent": 25
  },
  "success_kpis": {
    "target_ctr": "1.5%",
    "target_cpc": "15 DZD",
    "target_roas": "2.5x"
  },
  "agent_notes": "ملاحظات الوكيل للمستخدم"
}
PROMPT;

        try {
            $ai     = \Core\App\Services\AiService::fromActiveProvider();
            $result = $ai->generate($prompt, [
                'system'     => 'You are a Facebook Ads autonomous agent. Return JSON only.',
                'max_tokens' => 1500,
            ]);

            $result = trim(preg_replace('/^```(?:json)?\s*/m', '', $result));
            $result = trim(preg_replace('/```\s*$/m', '', $result));
            $data   = json_decode($result, true);
            if (!is_array($data)) {
                if (preg_match('/\{.*\}/s', $result, $m)) $data = json_decode($m[0], true);
            }

            if (!is_array($data) || empty($data['ads'])) {
                $this->json(['success' => false, 'message' => 'AI returned invalid strategy.', 'raw' => substr($result, 0, 400)]);
            }

            // Save analysis to session for launch step
            $_SESSION['fb_agent_analysis'] = [
                'product_id'      => $productId,
                'monthly_budget'  => $budget,
                'goal'            => $goal,
                'lang'            => $lang,
                'strategy'        => $data,
            ];

            $this->json(['success' => true, 'strategy' => $data, 'product' => [
                'id'    => $product['id'],
                'title' => $product['title'],
                'image' => $product['featured_image'] ?? '',
                'price' => $price,
            ]]);

        } catch (\Throwable $e) {
            $this->json(['success' => false, 'message' => $e->getMessage()]);
        }
    }

    // ── Step 2: Launch All AI Campaigns ──────────────────────────────
    public function launch(): void
    {
        $cfg = $this->cfg();
        if (empty($cfg['access_token']) || empty($cfg['ad_account_id']) || empty($cfg['page_id'])) {
            $this->json(['success' => false, 'message' => 'Facebook not configured.']);
        }

        $analysisData = $_SESSION['fb_agent_analysis'] ?? null;
        if (!$analysisData) {
            $this->json(['success' => false, 'message' => 'No strategy found. Run analysis first.']);
        }

        $strategy  = $analysisData['strategy'];
        $productId = (int)$analysisData['product_id'];
        $lang      = $analysisData['lang'] ?? 'ar';

        $product = db()->prepare("SELECT * FROM products WHERE id=? LIMIT 1");
        $product->execute([$productId]);
        $product = $product->fetch(\PDO::FETCH_ASSOC);
        if (!$product) $this->json(['success' => false, 'message' => 'Product not found.']);

        $pdo    = db();
        $token  = $cfg['access_token'];
        $acct   = $cfg['ad_account_id'];
        $pageId = $cfg['page_id'];

        $imageUrl  = $this->resolveImageUrl($product['featured_image'] ?? '');
        $productUrl = $this->getSiteUrl() . '/product/' . ($product['slug'] ?? $productId);

        // ── Create Agent record ───────────────────────────────────────
        $targeting    = $strategy['targeting'] ?? [];
        $dailyBudget  = (int)(($strategy['daily_budget'] ?? 200) * 100); // to cents
        $durationDays = (int)($strategy['duration_days'] ?? 14);
        $objective    = $strategy['objective'] ?? 'OUTCOME_SALES';

        $pdo->prepare("
            INSERT INTO fb_agents
                (product_id, strategy_name, strategy_data, monthly_budget, status, lang)
            VALUES (?,?,?,?,'active',?)
        ")->execute([
            $productId,
            $strategy['strategy_name'] ?? 'AI Campaign',
            json_encode($strategy, JSON_UNESCAPED_UNICODE),
            $analysisData['monthly_budget'],
            $lang,
        ]);
        $agentId = (int) $pdo->lastInsertId();

        $results   = [];
        $launched  = 0;
        $failed    = 0;

        // ── Launch one campaign per ad variant ────────────────────────
        foreach ($strategy['ads'] as $ad) {
            $variant  = $ad['variant'] ?? 'A';
            $campName = ($strategy['strategy_name'] ?? 'AI') . " — Variant {$variant}";

            try {
                // Build Facebook targeting
                $fbTargeting = [
                    'geo_locations' => ['countries' => $targeting['countries'] ?? ['DZ']],
                    'age_min'       => max(13, (int)($targeting['age_min'] ?? 18)),
                    'age_max'       => min(65, (int)($targeting['age_max'] ?? 55)),
                ];
                if (!empty($targeting['gender']) && in_array($targeting['gender'], ['1', '2'])) {
                    $fbTargeting['genders'] = [(int)$targeting['gender']];
                }

                // Step 1: Campaign
                $campaignRes = $this->fbPost("/act_{$acct}/campaigns", [
                    'name'                   => $campName,
                    'objective'              => $objective,
                    'status'                 => 'PAUSED',
                    'special_ad_categories'  => '[]',
                    'access_token'           => $token,
                ]);
                if (empty($campaignRes['id'])) throw new \Exception('Campaign failed: '.($campaignRes['error']['message']??json_encode($campaignRes)));

                // Step 2: Ad Set
                $adSetRes = $this->fbPost("/act_{$acct}/adsets", [
                    'name'              => $campName . ' — Set',
                    'campaign_id'       => $campaignRes['id'],
                    'billing_event'     => 'IMPRESSIONS',
                    'optimization_goal' => $this->getOptimizationGoal($objective),
                    'bid_strategy'      => 'LOWEST_COST_WITHOUT_CAP',
                    'daily_budget'      => $dailyBudget,
                    'targeting'         => json_encode($fbTargeting),
                    'start_time'        => date('Y-m-d\TH:i:sO'),
                    'end_time'          => date('Y-m-d\TH:i:sO', strtotime("+{$durationDays} days")),
                    'status'            => 'PAUSED',
                    'access_token'      => $token,
                ]);
                if (empty($adSetRes['id'])) throw new \Exception('AdSet failed: '.($adSetRes['error']['message']??''));

                // Step 3: Image upload
                $imageHash = null;
                if ($imageUrl) {
                    $imgRes    = $this->fbPost("/act_{$acct}/adimages", ['url'=>$imageUrl,'access_token'=>$token]);
                    $imageHash = $imgRes['images']['bytes']['hash'] ?? null;
                }

                // Step 3: Creative
                $linkData = [
                    'message'        => $ad['primary_text'] ?? '',
                    'link'           => $productUrl,
                    'name'           => $ad['headline']   ?? $product['title'],
                    'description'    => $ad['description'] ?? '',
                    'call_to_action' => ['type' => 'SHOP_NOW'],
                ];
                if ($imageHash) $linkData['image_hash'] = $imageHash;

                $creativeRes = $this->fbPost("/act_{$acct}/adcreatives", [
                    'name'                => $campName . ' — Creative',
                    'object_story_spec'   => json_encode(['page_id'=>$pageId,'link_data'=>$linkData]),
                    'access_token'        => $token,
                ]);
                if (empty($creativeRes['id'])) throw new \Exception('Creative failed: '.($creativeRes['error']['message']??''));

                // Step 4: Ad
                $adRes = $this->fbPost("/act_{$acct}/ads", [
                    'name'         => $campName . ' — Ad',
                    'adset_id'     => $adSetRes['id'],
                    'creative'     => json_encode(['creative_id'=>$creativeRes['id']]),
                    'status'       => 'PAUSED',
                    'access_token' => $token,
                ]);
                if (empty($adRes['id'])) throw new \Exception('Ad failed: '.($adRes['error']['message']??''));

                // Save campaign to DB
                $pdo->prepare("
                    INSERT INTO fb_campaigns
                        (product_id, agent_id, name, objective, daily_budget, duration_days,
                         targeting, ad_text, ad_headline, ad_description,
                         fb_campaign_id, fb_adset_id, fb_creative_id, fb_ad_id,
                         status, start_time, end_time, ab_variant)
                    VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,'active',NOW(),?,?)
                ")->execute([
                    $productId, $agentId, $campName, $objective,
                    $dailyBudget, $durationDays,
                    json_encode($fbTargeting),
                    $ad['primary_text'] ?? '',
                    $ad['headline']     ?? '',
                    $ad['description']  ?? '',
                    $campaignRes['id'], $adSetRes['id'], $creativeRes['id'], $adRes['id'],
                    date('Y-m-d H:i:s', strtotime("+{$durationDays} days")),
                    $variant,
                ]);

                $results[$variant] = ['success'=>true,'name'=>$campName,'fb_campaign_id'=>$campaignRes['id']];
                $launched++;

            } catch (\Throwable $e) {
                $results[$variant] = ['success'=>false,'name'=>$campName,'error'=>$e->getMessage()];
                $failed++;
            }
        }

        // Update agent status
        $pdo->prepare("UPDATE fb_agents SET status=?, launched_at=NOW() WHERE id=?")->execute([
            $launched > 0 ? 'active' : 'error',
            $agentId
        ]);

        unset($_SESSION['fb_agent_analysis']);

        $this->json([
            'success'   => $launched > 0,
            'message'   => "{$launched} campaigns launched, {$failed} failed.",
            'agent_id'  => $agentId,
            'results'   => $results,
            'ads_manager_url' => "https://www.facebook.com/adsmanager/manage/campaigns?act={$acct}",
        ]);
    }

    // ── Agent Optimizer (called by cron or manually) ──────────────────
    public function optimize(int $agentId): void
    {
        $agent = db()->prepare("SELECT * FROM fb_agents WHERE id=? AND status='active'");
        $agent->execute([$agentId]);
        $agent = $agent->fetch(\PDO::FETCH_ASSOC);
        if (!$agent) $this->json(['success' => false, 'message' => 'Agent not found or inactive.']);

        $cfg = $this->cfg();
        $pdo = db();

        // Get all campaigns for this agent
        $campaigns = $pdo->prepare("SELECT * FROM fb_campaigns WHERE agent_id=? AND status='active'");
        $campaigns->execute([$agentId]);
        $campaigns = $campaigns->fetchAll(\PDO::FETCH_ASSOC);

        if (empty($campaigns)) $this->json(['success' => false, 'message' => 'No active campaigns.']);

        // Fetch fresh insights for each campaign
        $insights = [];
        foreach ($campaigns as $c) {
            if (empty($c['fb_campaign_id'])) continue;
            $res = $this->fbGet("/{$c['fb_campaign_id']}/insights", [
                'fields'       => 'impressions,clicks,spend,ctr,cpc,actions',
                'date_preset'  => 'last_7d',
                'access_token' => $cfg['access_token'],
            ]);
            $data = $res['data'][0] ?? [];
            $insights[$c['id']] = [
                'campaign'    => $c,
                'impressions' => (int)($data['impressions'] ?? 0),
                'clicks'      => (int)($data['clicks']      ?? 0),
                'spend'       => (float)($data['spend']     ?? 0),
                'ctr'         => (float)($data['ctr']        ?? 0),
                'cpc'         => (float)($data['cpc']        ?? 0),
                'variant'     => $c['ab_variant'] ?? '?',
            ];
            // Update DB
            $pdo->prepare("UPDATE fb_campaigns SET impressions=?,clicks=?,spend=?,ctr=?,cpc=? WHERE id=?")
                ->execute([$data['impressions']??0,$data['clicks']??0,$data['spend']??0,$data['ctr']??0,$data['cpc']??0,$c['id']]);
        }

        // Ask AI to evaluate and decide
        $summary = json_encode(array_map(fn($i)=>[
            'variant'=>$i['variant'],'impressions'=>$i['impressions'],
            'clicks'=>$i['clicks'],'spend'=>$i['spend'],
            'ctr'=>$i['ctr'],'cpc'=>$i['cpc'],
        ], array_values($insights)), JSON_UNESCAPED_UNICODE);

        $strategy = json_decode($agent['strategy_data'] ?? '{}', true);
        $targetCtr = $strategy['success_kpis']['target_ctr'] ?? '1.5%';
        $targetCpc = $strategy['success_kpis']['target_cpc'] ?? '15 DZD';
        $dialectInstr = \Core\App\Services\AiService::getDialectInstruction(null, 'ar');

        $prompt = <<<PROMPT
{$dialectInstr}

أنت وكيل تسويق ذكي يحلل أداء حملات Facebook ويتخذ قرارات تلقائية.

المعايير المستهدفة: CTR > {$targetCtr} | CPC < {$targetCpc}

أداء الحملات (آخر 7 أيام):
{$summary}

اتخذ قرارات بـ JSON فقط:
{
  "decisions": [
    {
      "variant": "A",
      "action": "keep|pause|increase_budget|decrease_budget",
      "reason": "السبب",
      "budget_change_percent": 0
    }
  ],
  "overall_assessment": "تقييم عام",
  "next_action": "ما الخطوة التالية الموصى بها؟"
}
PROMPT;

        try {
            $ai       = \Core\App\Services\AiService::fromActiveProvider();
            $decision = $ai->generate($prompt, ['system'=>'Return JSON only.','max_tokens'=>500]);
            $decision = trim(preg_replace('/^```(?:json)?\s*/m','',$decision));
            $decision = trim(preg_replace('/```\s*$/m','',$decision));
            $decData  = json_decode($decision, true);

            if (!is_array($decData)) $this->json(['success'=>false,'message'=>'AI decision invalid.']);

            // Apply decisions
            $actions = [];
            foreach ($decData['decisions'] ?? [] as $dec) {
                $variant = $dec['variant'] ?? '';
                $action  = $dec['action']  ?? 'keep';

                // Find campaign for this variant
                foreach ($insights as $campId => $info) {
                    if ($info['variant'] !== $variant) continue;
                    $fbId = $info['campaign']['fb_campaign_id'] ?? '';

                    if ($action === 'pause' && $fbId) {
                        $this->fbPost("/{$fbId}", ['status'=>'PAUSED','access_token'=>$cfg['access_token']]);
                        $pdo->prepare("UPDATE fb_campaigns SET status='paused' WHERE id=?")->execute([$campId]);
                        $actions[] = "Paused variant {$variant}";

                    } elseif (in_array($action, ['increase_budget','decrease_budget'])) {
                        $change  = (int)($dec['budget_change_percent'] ?? 20);
                        $current = $info['campaign']['daily_budget'] ?? 0;
                        $newBudget = $action === 'increase_budget'
                            ? (int)($current * (1 + $change/100))
                            : (int)($current * (1 - $change/100));
                        $newBudget = max(100, $newBudget);
                        $adSetId   = $info['campaign']['fb_adset_id'] ?? '';
                        if ($adSetId) {
                            $this->fbPost("/{$adSetId}", ['daily_budget'=>$newBudget,'access_token'=>$cfg['access_token']]);
                            $pdo->prepare("UPDATE fb_campaigns SET daily_budget=? WHERE id=?")->execute([$newBudget,$campId]);
                        }
                        $actions[] = ucfirst($action)." variant {$variant} by {$change}%";
                    }
                }
            }

            // Save optimization log
            $pdo->prepare("INSERT INTO fb_agent_logs (agent_id, action, data) VALUES (?,?,?)")
                ->execute([$agentId, 'optimize', json_encode($decData, JSON_UNESCAPED_UNICODE)]);

            $this->json([
                'success'    => true,
                'actions'    => $actions,
                'assessment' => $decData['overall_assessment'] ?? '',
                'next_action'=> $decData['next_action'] ?? '',
            ]);

        } catch (\Throwable $e) {
            $this->json(['success' => false, 'message' => $e->getMessage()]);
        }
    }

    // ── Helpers ───────────────────────────────────────────────────────
    private function isAiAvailable(): bool
    {
        try { return (bool)db()->query("SELECT COUNT(*) FROM ai_settings WHERE api_key!='' AND is_active=1")->fetchColumn();
        } catch (\Throwable $e) { return false; }
    }

    private function getOptimizationGoal(string $objective): string
    {
        return match($objective) {
            'OUTCOME_SALES'      => 'OFFSITE_CONVERSIONS',
            'OUTCOME_TRAFFIC'    => 'LINK_CLICKS',
            'OUTCOME_AWARENESS'  => 'REACH',
            'OUTCOME_ENGAGEMENT' => 'POST_ENGAGEMENT',
            default              => 'LINK_CLICKS',
        };
    }

    private function resolveImageUrl(string $img): string
    {
        if (!$img) return '';
        if (str_starts_with($img, 'http')) return $img;
        $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
        return $scheme . '://' . ($_SERVER['HTTP_HOST'] ?? '') . '/' . ltrim($img, '/');
    }

    private function getSiteUrl(): string
    {
        $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
        return $scheme . '://' . ($_SERVER['HTTP_HOST'] ?? '');
    }

    private function fbPost(string $endpoint, array $params): array
    {
        $ch = curl_init(self::FB_API . $endpoint);
        curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true,CURLOPT_POST=>true,CURLOPT_POSTFIELDS=>http_build_query($params),CURLOPT_TIMEOUT=>30,CURLOPT_SSL_VERIFYPEER=>false]);
        $res = curl_exec($ch); curl_close($ch);
        return json_decode($res ?: '{}', true) ?: [];
    }

    private function fbGet(string $endpoint, array $params): array
    {
        $ch = curl_init(self::FB_API . $endpoint . '?' . http_build_query($params));
        curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true,CURLOPT_TIMEOUT=>20,CURLOPT_SSL_VERIFYPEER=>false]);
        $res = curl_exec($ch); curl_close($ch);
        return json_decode($res ?: '{}', true) ?: [];
    }
}
