import json
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app
from flask_login import login_required, current_user
from app.extensions import db, csrf
from app.ai.diamond import run_sync
from app.models.campaign import (
    SocialAccount, Campaign, CampaignPost, CampaignMetrics,
    WhatsAppInstance, WhatsAppCampaign
)
from app.models.report import Report

campaigns_bp = Blueprint("campaigns", __name__, url_prefix="/campaigns")


@campaigns_bp.route("/")
@login_required
def dashboard():
    campaigns = Campaign.query.filter_by(user_id=current_user.id).order_by(Campaign.created_at.desc()).all()
    accounts = SocialAccount.query.filter_by(user_id=current_user.id).all()
    wa_instances = WhatsAppInstance.query.filter_by(user_id=current_user.id).all()
    total_views = sum(m.views for c in campaigns for p in c.posts for m in p.metrics)
    total_likes = sum(m.likes for c in campaigns for p in c.posts for m in p.metrics)
    return render_template("campaigns/dashboard.html",
        campaigns=campaigns, accounts=accounts, wa_instances=wa_instances,
        total_views=total_views, total_likes=total_likes)


@campaigns_bp.route("/create/<int:report_id>", methods=["GET", "POST"])
@login_required
def create(report_id):
    report = Report.query.get_or_404(report_id)
    if report.user_id != current_user.id:
        return redirect(url_for("campaigns.dashboard"))

    video_provider = current_user.effective_video_provider

    # Get allowed durations from admin config
    allowed_durations = []
    if video_provider and video_provider != "none":
        try:
            from app.models.features import VideoProviderConfig
            allowed_durations = VideoProviderConfig.get_allowed_durations(video_provider)
        except Exception:
            allowed_durations = [5, 10]

    if request.method == "POST":
        name = request.form.get("name", report.project_name)
        user_script_notes = request.form.get("user_script_notes", "").strip() or None
        video_duration = request.form.get("video_duration", type=int)

        if video_provider == "none":
            flash("توليد الفيديو غير متاح في باقتك الحالية.", "error")
            return redirect(url_for("campaigns.create", report_id=report_id))

        # Validate duration against allowed list
        if video_duration and allowed_durations and video_duration not in allowed_durations:
            video_duration = allowed_durations[-1] if allowed_durations else None

        # Generate script first — only save campaign if script succeeds
        if not report.synthesis_result:
            flash("التقرير غير مكتمل. يرجى إكمال التحليل أولاً.", "error")
            return redirect(url_for("campaigns.create", report_id=report_id))

        try:
            from app.ai.prompts.video_script import get_video_script_prompt
            from app.ai.diamond import call_ai, _parse_json

            messages = get_video_script_prompt(
                report.synthesis_result, report.language,
                duration_seconds=video_duration,
                user_notes=user_script_notes,
            )
            response = run_sync(call_ai(messages, model_type="deep"))
            script_data = _parse_json(response)
            script_text = json.dumps(script_data, ensure_ascii=False) if isinstance(script_data, dict) else response
            storyboard = script_data if isinstance(script_data, dict) else None
        except Exception as e:
            current_app.logger.error(f"Script generation failed: {e}")
            flash("فشل توليد السيناريو. حاول مرة أخرى.", "error")
            return redirect(url_for("campaigns.create", report_id=report_id))

        # Script succeeded — now save the campaign
        campaign = Campaign(
            user_id=current_user.id,
            report_id=report.id,
            name=name,
            video_provider=video_provider,
            script=script_text,
            storyboard_json=storyboard,
            user_script_notes=user_script_notes,
            video_duration=video_duration,
            status="script_ready",
        )
        db.session.add(campaign)
        db.session.commit()
        return redirect(url_for("campaigns.detail", campaign_id=campaign.id))

    accounts = SocialAccount.query.filter_by(user_id=current_user.id).all()
    return render_template("campaigns/create.html",
        report=report, accounts=accounts,
        allowed_durations=allowed_durations)


@campaigns_bp.route("/detail/<int:campaign_id>")
@login_required
def detail(campaign_id):
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return redirect(url_for("campaigns.dashboard"))

    # Get allowed durations for the video provider
    allowed_durations = []
    provider = campaign.video_provider or current_user.effective_video_provider
    if provider and provider != "none":
        try:
            from app.models.features import VideoProviderConfig
            allowed_durations = VideoProviderConfig.get_allowed_durations(provider)
        except Exception:
            allowed_durations = [5, 10]

    # Get sponsor platforms available for free publishing
    sponsor_platforms = []
    try:
        from app.models.ads import SponsorSocialAccount
        sponsor_platforms = SponsorSocialAccount.get_active_platforms()
    except Exception:
        pass

    # Get user's connected social accounts
    user_accounts = SocialAccount.query.filter_by(user_id=current_user.id).all()
    user_platforms = [a.platform for a in user_accounts if a.access_token]

    return render_template("campaigns/detail.html",
        campaign=campaign, allowed_durations=allowed_durations,
        sponsor_platforms=sponsor_platforms, user_platforms=user_platforms)


@campaigns_bp.route("/api/generate-script/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def api_generate_script(campaign_id):
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403
    if campaign.script:
        return jsonify({"status": "done", "script": campaign.script})

    # Save user notes from request body if provided
    data = request.get_json(silent=True) or {}
    user_notes = data.get("user_notes", "").strip()
    if user_notes:
        campaign.user_script_notes = user_notes
        db.session.commit()

    try:
        from app.ai.prompts.video_script import get_video_script_prompt
        from app.ai.diamond import call_ai, _parse_json

        report = campaign.report
        if not report or not report.synthesis_result:
            return jsonify({"error": "Report not found"}), 400

        messages = get_video_script_prompt(
            report.synthesis_result, report.language,
            duration_seconds=campaign.video_duration,
            user_notes=campaign.user_script_notes,
        )
        response = run_sync(call_ai(messages, model_type="deep"))

        script_data = _parse_json(response)
        campaign.script = json.dumps(script_data, ensure_ascii=False) if isinstance(script_data, dict) else response
        campaign.storyboard_json = script_data if isinstance(script_data, dict) else None
        campaign.status = "script_ready"
        db.session.commit()
        return jsonify({"status": "done", "script": campaign.script})
    except Exception as e:
        current_app.logger.error(f"Script generation failed: {e}")
        return jsonify({"error": str(e)}), 500


@campaigns_bp.route("/api/update-script/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def api_update_script(campaign_id):
    """Save user's manual script edits."""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403
    if campaign.video_url:
        return jsonify({"error": "لا يمكن تعديل السيناريو بعد توليد الفيديو"}), 400

    data = request.get_json(silent=True) or {}
    new_script = data.get("script", "").strip()
    if not new_script:
        return jsonify({"error": "السيناريو فارغ"}), 400

    campaign.script = new_script
    # Try to parse as JSON for storyboard
    try:
        from app.ai.diamond import _parse_json
        parsed = _parse_json(new_script)
        if isinstance(parsed, dict):
            campaign.storyboard_json = parsed
    except Exception:
        pass
    campaign.status = "script_ready"
    db.session.commit()
    return jsonify({"status": "done"})


@campaigns_bp.route("/api/improve-script/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def api_improve_script(campaign_id):
    """AI improves the current script based on user suggestion."""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403
    if campaign.video_url:
        return jsonify({"error": "لا يمكن تعديل السيناريو بعد توليد الفيديو"}), 400

    data = request.get_json(silent=True) or {}
    suggestion = data.get("suggestion", "").strip()
    current_script = data.get("current_script", "").strip() or campaign.script or ""

    if not current_script:
        return jsonify({"error": "لا يوجد سيناريو للتحسين"}), 400

    try:
        from app.ai.diamond import call_ai, _parse_json

        improve_instruction = "Improve and enhance this video marketing script."
        if suggestion:
            improve_instruction += f" The user specifically asked: \"{suggestion}\""

        lang = "Arabic" if (campaign.report and campaign.report.language == "ar") else "English"
        dur = campaign.video_duration or 30

        messages = [
            {
                "role": "system",
                "content": (
                    f"You are a professional video script editor. {improve_instruction} "
                    f"Keep the response in {lang}. The video must be {dur} seconds long. "
                    "Return the improved script as valid JSON with the same structure as the original. "
                    "Keys: title, duration_seconds, scenes (array), voiceover_full_script, music_mood, target_platforms, hashtags."
                ),
            },
            {
                "role": "user",
                "content": f"Here is the current script to improve:\n\n{current_script[:3000]}"
            },
        ]

        response = run_sync(call_ai(messages, model_type="deep"))
        improved = _parse_json(response)
        improved_text = json.dumps(improved, ensure_ascii=False) if isinstance(improved, dict) else response

        # If called from the editor, return the text without saving (user must click save)
        if data.get("current_script"):
            return jsonify({"status": "done", "script": improved_text})

        # If called from the quick improve button, save directly
        campaign.script = improved_text
        if isinstance(improved, dict):
            campaign.storyboard_json = improved
        campaign.status = "script_ready"
        db.session.commit()
        return jsonify({"status": "done", "script": improved_text})

    except Exception as e:
        current_app.logger.error(f"Script improvement failed: {e}")
        return jsonify({"error": str(e)}), 500


@campaigns_bp.route("/api/generate-video/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def api_generate_video(campaign_id):
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403

    # Accept duration from request body (JSON or form)
    req_data = request.get_json(silent=True) or {}
    req_duration = req_data.get("duration")
    if req_duration:
        try:
            campaign.video_duration = int(req_duration)
        except (ValueError, TypeError):
            pass

    try:
        script_data = json.loads(campaign.script) if campaign.script else {}
        prompt = script_data.get("voiceover_full_script", campaign.script or "")

        effective_provider = campaign.video_provider or current_user.effective_video_provider or "sora"
        from app.ai.video_providers import get_video_provider
        provider = get_video_provider(effective_provider)

        duration = campaign.video_duration or 10
        result = run_sync(provider.generate_video(prompt[:500], duration=duration))

        if result.get("status") == "error":
            campaign.status = "script_ready"
            db.session.commit()
            return jsonify(result), 400

        campaign.video_id = result.get("video_id") or result.get("operation_id")
        campaign.video_provider = effective_provider
        campaign.status = "video_processing"
        db.session.commit()
        return jsonify(result)
    except Exception as e:
        campaign.status = "script_ready"
        db.session.commit()
        return jsonify({"status": "error", "error": str(e)}), 500


@campaigns_bp.route("/api/video-status/<int:campaign_id>", methods=["GET"])
@login_required
def api_video_status(campaign_id):
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403

    if campaign.video_url:
        # Fix: if video_url is an OpenAI API URL, re-download it locally
        if "api.openai.com" in campaign.video_url:
            try:
                import os, uuid as _uuid, requests as _req
                api_key = current_app.config.get("OPENAI_API_KEY", "")
                resp = _req.get(campaign.video_url, headers={"Authorization": f"Bearer {api_key}"}, timeout=120)
                if resp.status_code == 200:
                    videos_dir = os.path.join(current_app.static_folder, "videos")
                    os.makedirs(videos_dir, exist_ok=True)
                    filename = f"{_uuid.uuid4().hex}.mp4"
                    filepath = os.path.join(videos_dir, filename)
                    with open(filepath, "wb") as f:
                        f.write(resp.content)
                    campaign.video_url = url_for("static", filename=f"videos/{filename}")
                    db.session.commit()
            except Exception:
                pass
        return jsonify({"status": "completed", "video_url": campaign.video_url})

    if not campaign.video_id:
        if campaign.status == "video_processing":
            campaign.status = "script_ready"
            db.session.commit()
        return jsonify({"status": "error", "error": "لم يتم العثور على عملية توليد فيديو. يرجى إعادة المحاولة."})

    try:
        from app.ai.video_providers import get_video_provider
        provider = get_video_provider(campaign.video_provider or "sora")

        result = run_sync(provider.check_status(campaign.video_id))

        if result.get("status") == "completed":
            # If provider returned raw video bytes, save locally
            video_bytes = result.pop("video_bytes", None)
            if video_bytes:
                import os, uuid as _uuid
                videos_dir = os.path.join(current_app.static_folder, "videos")
                os.makedirs(videos_dir, exist_ok=True)
                filename = f"{_uuid.uuid4().hex}.mp4"
                filepath = os.path.join(videos_dir, filename)
                with open(filepath, "wb") as f:
                    f.write(video_bytes)
                campaign.video_url = url_for("static", filename=f"videos/{filename}")
                result["video_url"] = campaign.video_url
            else:
                campaign.video_url = result.get("video_url", "")
            campaign.status = "video_ready"
            db.session.commit()
            result["video_url"] = campaign.video_url
        elif result.get("status") == "error":
            campaign.status = "script_ready"
            campaign.video_id = None
            db.session.commit()

        return jsonify(result)
    except Exception as e:
        campaign.status = "script_ready"
        campaign.video_id = None
        db.session.commit()
        return jsonify({"status": "error", "error": str(e)}), 500


@campaigns_bp.route("/api/retry-video/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def api_retry_video(campaign_id):
    """Reset a stuck campaign back to script_ready so user can retry video generation."""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403
    campaign.status = "script_ready"
    campaign.video_id = None
    campaign.video_url = None
    db.session.commit()
    return jsonify({"status": "reset"})


@campaigns_bp.route("/video/<int:campaign_id>")
@login_required
def serve_video(campaign_id):
    """Serve video file — downloads from OpenAI API if needed and redirects to local file."""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return redirect(url_for("campaigns.dashboard"))

    if not campaign.video_url:
        flash("لا يوجد فيديو متاح.", "error")
        return redirect(url_for("campaigns.detail", campaign_id=campaign.id))

    # If already a local URL, redirect directly
    if "api.openai.com" not in campaign.video_url:
        return redirect(campaign.video_url)

    # Download from OpenAI API and save locally
    import os, uuid as _uuid, requests as _req
    try:
        api_key = current_app.config.get("OPENAI_API_KEY", "")
        resp = _req.get(campaign.video_url, headers={"Authorization": f"Bearer {api_key}"}, timeout=120, stream=True)
        if resp.status_code == 200:
            videos_dir = os.path.join(current_app.static_folder, "videos")
            os.makedirs(videos_dir, exist_ok=True)
            filename = f"{_uuid.uuid4().hex}.mp4"
            filepath = os.path.join(videos_dir, filename)
            with open(filepath, "wb") as f:
                for chunk in resp.iter_content(chunk_size=8192):
                    f.write(chunk)
            campaign.video_url = url_for("static", filename=f"videos/{filename}")
            db.session.commit()
            return redirect(campaign.video_url)
        else:
            flash(f"خطأ في تنزيل الفيديو: {resp.status_code}", "error")
            return redirect(url_for("campaigns.detail", campaign_id=campaign.id))
    except Exception as e:
        flash(f"خطأ: {str(e)}", "error")
        return redirect(url_for("campaigns.detail", campaign_id=campaign.id))


@campaigns_bp.route("/delete/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def delete(campaign_id):
    """Delete a campaign."""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return redirect(url_for("campaigns.dashboard"))
    # Delete related posts and metrics
    for post in campaign.posts:
        CampaignMetrics.query.filter_by(post_id=post.id).delete()
    CampaignPost.query.filter_by(campaign_id=campaign.id).delete()
    db.session.delete(campaign)
    db.session.commit()
    flash("تم حذف الحملة", "success")
    return redirect(url_for("campaigns.dashboard"))


@campaigns_bp.route("/api/publish/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def api_publish(campaign_id):
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403

    data = request.get_json(silent=True) or {}
    platforms = data.get("platforms", [])
    captions = data.get("captions", {})
    publish_mode = data.get("publish_mode", "my_accounts")  # my_accounts / sponsor

    if not campaign.video_url:
        return jsonify({"error": "No video available"}), 400

    results = {}
    for platform_name in platforms:
        # Resolve the access token based on publish mode
        access_token = None

        if publish_mode == "sponsor":
            # Use admin's sponsor account
            from app.models.ads import SponsorSocialAccount
            sponsor_acc = SponsorSocialAccount.get_account_for_platform(platform_name)
            if not sponsor_acc or not sponsor_acc.access_token:
                results[platform_name] = {"status": "error", "error": "لا يوجد حساب راعي لهذه المنصة"}
                continue
            access_token = sponsor_acc.access_token
        else:
            # Use user's own account
            account = SocialAccount.query.filter_by(
                user_id=current_user.id, platform=platform_name
            ).first()
            if not account or not account.access_token:
                results[platform_name] = {"status": "error", "error": "Account not connected"}
                continue
            access_token = account.access_token

        caption = captions.get(platform_name, campaign.name)
        post = CampaignPost(
            campaign_id=campaign.id,
            platform=platform_name,
            publish_mode=publish_mode,
            caption=caption,
            status="publishing",
        )
        db.session.add(post)
        db.session.commit()

        from app.social.publisher import get_platform
        platform = get_platform(platform_name)
        if not platform:
            post.status = "error"
            results[platform_name] = {"status": "error", "error": "Platform not supported"}
            continue

        try:
            result = run_sync(
                platform.publish(campaign.video_url, caption, access_token)
            )
            post.status = result.get("status", "error")
            post.post_id = result.get("post_id")
            post.post_url = result.get("post_url")
            results[platform_name] = result
        except Exception as e:
            post.status = "error"
            results[platform_name] = {"status": "error", "error": str(e)}
        db.session.commit()

    campaign.status = "published"
    db.session.commit()
    return jsonify({"results": results})


# ══════════════════════════════════════════════════════════════
#  Paid Ad Campaign Routes (User-facing)
# ══════════════════════════════════════════════════════════════

from app.models.ads import (
    AdCampaign, AdCampaignMetrics, AdAuditLog,
    UserAdBudget, AdBudgetWallet, AdminAdAccount
)


@campaigns_bp.route("/my-ads")
@login_required
def my_ads():
    """User's ad campaigns dashboard with stats and filters."""
    from datetime import datetime, timedelta

    # Filters
    platform = request.args.get("platform", "").strip()
    status = request.args.get("status", "").strip()
    date_from = request.args.get("date_from", "").strip()
    date_to = request.args.get("date_to", "").strip()
    q = request.args.get("q", "").strip()
    sort_by = request.args.get("sort", "date").strip()

    # User's ad campaigns
    camp_query = AdCampaign.query.filter_by(user_id=current_user.id)
    if status:
        camp_query = camp_query.filter(AdCampaign.status == status)
    if q:
        camp_query = camp_query.filter(AdCampaign.name.ilike(f"%{q}%"))

    if sort_by == "spend":
        ad_campaigns = camp_query.order_by(AdCampaign.budget_amount.desc()).all()
    elif sort_by == "views":
        ad_campaigns = camp_query.order_by(AdCampaign.created_at.desc()).all()
    else:
        ad_campaigns = camp_query.order_by(AdCampaign.created_at.desc()).all()

    # Metrics
    campaign_ids = [c.id for c in ad_campaigns]
    metrics_query = AdCampaignMetrics.query
    if campaign_ids:
        metrics_query = metrics_query.filter(AdCampaignMetrics.ad_campaign_id.in_(campaign_ids))
    else:
        metrics_query = metrics_query.filter(False)
    if platform:
        metrics_query = metrics_query.filter(AdCampaignMetrics.platform == platform)
    if date_from:
        metrics_query = metrics_query.filter(AdCampaignMetrics.date >= date_from)
    if date_to:
        metrics_query = metrics_query.filter(AdCampaignMetrics.date <= date_to)
    all_metrics = metrics_query.all()

    # Aggregates
    total_spend = sum(m.spend for m in all_metrics)
    total_views = sum(m.views for m in all_metrics)
    total_clicks = sum(m.clicks for m in all_metrics)
    total_impressions = sum(m.impressions for m in all_metrics)
    avg_ctr = round((total_clicks / total_impressions * 100), 2) if total_impressions > 0 else 0
    avg_cpv = round(total_spend / total_views, 4) if total_views > 0 else 0

    # User budget
    user_budget = UserAdBudget.query.filter_by(user_id=current_user.id).first()

    # Daily chart data
    daily_data = {}
    for m in all_metrics:
        d = str(m.date)
        if d not in daily_data:
            daily_data[d] = {"spend": 0, "views": 0, "clicks": 0}
        daily_data[d]["spend"] += m.spend
        daily_data[d]["views"] += m.views
        daily_data[d]["clicks"] += m.clicks
    daily_labels = sorted(daily_data.keys())
    daily_spend = [round(daily_data[d]["spend"], 2) for d in daily_labels]
    daily_views = [daily_data[d]["views"] for d in daily_labels]

    # Platform breakdown
    platform_spend = {}
    for m in all_metrics:
        platform_spend[m.platform] = platform_spend.get(m.platform, 0) + m.spend

    import json as _json
    return render_template("campaigns/my_ads.html",
        ad_campaigns=ad_campaigns, all_metrics=all_metrics,
        total_spend=total_spend, total_views=total_views,
        total_clicks=total_clicks, total_impressions=total_impressions,
        avg_ctr=avg_ctr, avg_cpv=avg_cpv,
        user_budget=user_budget,
        daily_labels=_json.dumps(daily_labels),
        daily_spend=_json.dumps(daily_spend),
        daily_views=_json.dumps(daily_views),
        platform_spend=_json.dumps(platform_spend),
        f_platform=platform, f_status=status,
        f_date_from=date_from, f_date_to=date_to,
        f_q=q, f_sort=sort_by,
        active_count=sum(1 for c in ad_campaigns if c.status == "active"),
    )


@campaigns_bp.route("/my-ads/<int:ad_campaign_id>")
@login_required
def ad_detail(ad_campaign_id):
    """User views details of their own ad campaign."""
    ad_camp = AdCampaign.query.get_or_404(ad_campaign_id)
    if ad_camp.user_id != current_user.id:
        return redirect(url_for("campaigns.my_ads"))

    metrics = AdCampaignMetrics.query.filter_by(ad_campaign_id=ad_camp.id)\
        .order_by(AdCampaignMetrics.date.asc()).all()

    # Daily chart data
    daily_data = {}
    for m in metrics:
        d = str(m.date)
        if d not in daily_data:
            daily_data[d] = {"spend": 0, "views": 0, "clicks": 0}
        daily_data[d]["spend"] += m.spend
        daily_data[d]["views"] += m.views
        daily_data[d]["clicks"] += m.clicks
    daily_labels = sorted(daily_data.keys())
    daily_spend = [round(daily_data[d]["spend"], 2) for d in daily_labels]
    daily_views = [daily_data[d]["views"] for d in daily_labels]
    daily_clicks = [daily_data[d]["clicks"] for d in daily_labels]

    # Platform breakdown
    platform_data = {}
    for m in metrics:
        if m.platform not in platform_data:
            platform_data[m.platform] = {"spend": 0, "views": 0, "clicks": 0}
        platform_data[m.platform]["spend"] += m.spend
        platform_data[m.platform]["views"] += m.views
        platform_data[m.platform]["clicks"] += m.clicks

    import json as _json
    return render_template("campaigns/ad_detail.html",
        ad_camp=ad_camp, metrics=metrics,
        daily_labels=_json.dumps(daily_labels),
        daily_spend=_json.dumps(daily_spend),
        daily_views=_json.dumps(daily_views),
        daily_clicks=_json.dumps(daily_clicks),
        platform_data=_json.dumps({k: v["spend"] for k, v in platform_data.items()}),
    )


@campaigns_bp.route("/launch-ad/<int:campaign_id>", methods=["GET", "POST"])
@login_required
def launch_ad(campaign_id):
    """User creates a paid ad campaign from an existing video campaign."""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return redirect(url_for("campaigns.dashboard"))
    if not campaign.video_url:
        flash("يجب توليد الفيديو أولاً قبل إطلاق حملة إعلانية.", "error")
        return redirect(url_for("campaigns.detail", campaign_id=campaign.id))

    user_budget = UserAdBudget.query.filter_by(user_id=current_user.id).first()
    if not user_budget or not user_budget.is_active:
        flash("ليس لديك ميزانية إعلانية مخصصة. تواصل مع مدير النظام.", "error")
        return redirect(url_for("campaigns.detail", campaign_id=campaign.id))

    # Available platforms
    active_platforms = AdminAdAccount.query.filter_by(is_active=True).all()
    available_platforms = [a.platform for a in active_platforms]

    if request.method == "POST":
        platforms = request.form.getlist("platforms")
        budget_amount = request.form.get("budget_amount", 0, type=float)
        duration_days = request.form.get("duration_days", 7, type=int)

        if not platforms:
            flash("اختر منصة واحدة على الأقل.", "error")
            return redirect(url_for("campaigns.launch_ad", campaign_id=campaign.id))

        if budget_amount <= 0:
            flash("الميزانية يجب أن تكون أكبر من صفر.", "error")
            return redirect(url_for("campaigns.launch_ad", campaign_id=campaign.id))

        if budget_amount > user_budget.remaining:
            flash(f"الميزانية المطلوبة (${budget_amount}) تتجاوز رصيدك المتبقي (${user_budget.remaining:.2f}).", "error")
            return redirect(url_for("campaigns.launch_ad", campaign_id=campaign.id))

        daily_budget = round(budget_amount / max(duration_days, 1), 2)

        # Get AI targeting suggestions
        from app.ads.targeting import suggest_targeting_sync
        report = campaign.report
        if report:
            ai_suggestions = suggest_targeting_sync(report, platforms, budget_amount, report.language or "ar")
        else:
            from app.ads.targeting import _default_suggestions
            ai_suggestions = _default_suggestions(platforms, budget_amount)

        # Create the ad campaign
        ad_camp = AdCampaign(
            user_id=current_user.id,
            campaign_id=campaign.id,
            name=campaign.name,
            platforms_json=platforms,
            budget_amount=budget_amount,
            daily_budget=daily_budget,
            duration_days=duration_days,
            targeting_json={
                "age_min": ai_suggestions.get("age_min", 18),
                "age_max": ai_suggestions.get("age_max", 45),
                "gender": ai_suggestions.get("gender", "all"),
                "locations": ai_suggestions.get("locations", ["SA"]),
                "interests": ai_suggestions.get("interests", []),
                "budget_split": ai_suggestions.get("budget_split", {}),
            },
            ai_suggestions_json=ai_suggestions,
            ad_caption=ai_suggestions.get(f"ad_caption_{report.language}" if report else "ad_caption_ar", ""),
            ad_cta=ai_suggestions.get("cta", "LEARN_MORE"),
            status="pending_approval",
        )
        db.session.add(ad_camp)

        # Audit log
        log = AdAuditLog(
            user_id=current_user.id,
            ad_campaign_id=None,  # will be set after flush
            action="submitted",
            details_json={"budget": budget_amount, "platforms": platforms, "duration": duration_days},
        )
        db.session.add(log)
        db.session.flush()
        log.ad_campaign_id = ad_camp.id

        # Notify admin
        from app.models.user import User
        admins = User.query.filter_by(is_admin=True).all()
        from app.models.features import Notification
        for admin in admins:
            notif = Notification(
                user_id=admin.id,
                title="حملة إعلانية جديدة",
                message=f"حملة إعلانية جديدة بانتظار المراجعة: {ad_camp.name} من {current_user.name}",
                category="ads",
            )
            db.session.add(notif)

        db.session.commit()
        flash("تم تقديم الحملة للمراجعة. سيتم إخطارك عند اعتمادها.", "success")
        return redirect(url_for("campaigns.my_ads"))

    return render_template("campaigns/launch_ad.html",
        campaign=campaign, user_budget=user_budget,
        available_platforms=available_platforms)


@campaigns_bp.route("/api/ad-targeting/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def api_ad_targeting(campaign_id):
    """AJAX: Get AI targeting suggestions for a campaign."""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403

    data = request.get_json(silent=True) or {}
    platforms = data.get("platforms", ["facebook"])
    budget = data.get("budget", 5.0)

    from app.ads.targeting import suggest_targeting_sync
    report = campaign.report
    if report:
        suggestions = suggest_targeting_sync(report, platforms, budget, report.language or "ar")
    else:
        from app.ads.targeting import _default_suggestions
        suggestions = _default_suggestions(platforms, budget)

    return jsonify(suggestions)


@campaigns_bp.route("/my-ads/<int:ad_campaign_id>/request-pause", methods=["POST"])
@login_required
def request_pause_ad(ad_campaign_id):
    """User requests to pause their ad campaign."""
    ad_camp = AdCampaign.query.get_or_404(ad_campaign_id)
    if ad_camp.user_id != current_user.id:
        return redirect(url_for("campaigns.my_ads"))

    if ad_camp.status == "active":
        ad_camp.status = "paused"
        log = AdAuditLog(
            user_id=current_user.id,
            ad_campaign_id=ad_camp.id,
            action="paused",
            details_json={"requested_by": "user"},
        )
        db.session.add(log)
        db.session.commit()
        flash("تم إيقاف الحملة مؤقتاً.", "success")
    else:
        flash("لا يمكن إيقاف هذه الحملة في حالتها الحالية.", "error")
    return redirect(url_for("campaigns.ad_detail", ad_campaign_id=ad_campaign_id))


@campaigns_bp.route("/accounts")
@login_required
def accounts():
    accounts = SocialAccount.query.filter_by(user_id=current_user.id).all()
    wa_instances = WhatsAppInstance.query.filter_by(user_id=current_user.id).all()
    return render_template("campaigns/accounts.html", accounts=accounts, wa_instances=wa_instances)


@campaigns_bp.route("/oauth/<platform>")
@login_required
def oauth_start(platform):
    from app.social.publisher import get_platform
    p = get_platform(platform)
    if not p:
        flash(f"Platform {platform} not supported.", "error")
        return redirect(url_for("campaigns.accounts"))
    redirect_uri = url_for("campaigns.oauth_callback", platform=platform, _external=True)
    return redirect(p.get_oauth_url(redirect_uri))


@campaigns_bp.route("/oauth/callback/<platform>")
@login_required
def oauth_callback(platform):
    code = request.args.get("code")
    if not code:
        flash("OAuth failed.", "error")
        return redirect(url_for("campaigns.accounts"))

    from app.social.publisher import get_platform
    p = get_platform(platform)
    redirect_uri = url_for("campaigns.oauth_callback", platform=platform, _external=True)

    token_data = run_sync(p.handle_oauth_callback(code, redirect_uri))

    access_token = token_data.get("access_token", "")
    if not access_token:
        flash(f"Could not get token: {token_data}", "error")
        return redirect(url_for("campaigns.accounts"))

    existing = SocialAccount.query.filter_by(user_id=current_user.id, platform=platform).first()
    if existing:
        existing.access_token = access_token
        existing.refresh_token = token_data.get("refresh_token", "")
    else:
        account = SocialAccount(
            user_id=current_user.id,
            platform=platform,
            access_token=access_token,
            refresh_token=token_data.get("refresh_token", ""),
        )
        db.session.add(account)
    db.session.commit()
    flash(f"{platform} connected!", "success")
    return redirect(url_for("campaigns.accounts"))
