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)

    # Get user's reports that have synthesis results (ready for campaign creation)
    from sqlalchemy import not_
    reports = Report.query.filter(
        Report.user_id == current_user.id,
        Report.synthesis_result.isnot(None)
    ).order_by(Report.created_at.desc()).limit(6).all()

    return render_template("campaigns/dashboard.html",
        campaigns=campaigns, accounts=accounts, wa_instances=wa_instances,
        total_views=total_views, total_likes=total_likes, reports=reports)


@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"))

    # Handle POST request - create campaign with form data
    if request.method == "POST":
        try:
            # Get form data
            video_language = request.form.get("video_language", "ar")
            user_notes = request.form.get("user_script_notes", "").strip()

            # Create campaign immediately - no blocking operations
            campaign = Campaign(
                user_id=current_user.id,
                report_id=report.id,
                name=request.form.get("name", report.project_name),
                video_provider=current_user.effective_video_provider,
                video_language=video_language,
                user_script_notes=user_notes,
                script=None,  # Will be generated on detail page
                storyboard_json=None,
                video_duration=None,
                status="created",  # Set to created, not script_processing
            )

            # Fast database commit
            db.session.add(campaign)
            db.session.flush()  # Flush to get ID without full transaction overhead
            campaign_id = campaign.id
            db.session.commit()  # Quick commit

            # Immediate redirect to detail page - no waiting
            current_app.logger.info(f"Campaign {campaign_id} created successfully for user {current_user.id}")
            return redirect(url_for("campaigns.detail", campaign_id=campaign_id))

        except Exception as e:
            current_app.logger.error(f"Campaign creation failed: {e}")
            db.session.rollback()
            flash("فشل إنشاء الحملة. حاول مرة أخرى.", "error")
            return redirect(url_for("campaigns.create", report_id=report_id))

    # GET request - show creation form
    return render_template("campaigns/create.html", report=report)


@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})

    # OPTIMIZATION 1: Skip script generation if no user notes (optional)
    data = request.get_json(silent=True) or {}
    user_notes = data.get("user_notes", "").strip()

    # Save user notes if provided
    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

        # Use campaign's video_language for script generation (not report language)
        video_language = campaign.video_language or "ar"

        # OPTIMIZATION 2: Generate script synchronously but much faster
        campaign.status = "script_processing"
        db.session.commit()

        # OPTIMIZATION 3: Use ultra-fast model and minimal prompt
        from app.ai.providers import get_provider
        provider = get_provider()
        fast_model = "gpt-4o-mini"  # Fastest available model

        # Generate script synchronously (much faster with optimized prompt)
        messages = get_video_script_prompt(
            report.synthesis_result, video_language,
            duration_seconds=campaign.video_duration,
            user_notes=user_notes,
        )

        # Synchronous but very fast call
        import asyncio
        ai_response = asyncio.run(provider.chat(messages, fast_model, temperature=0.7))

        # Parse and validate JSON structure
        try:
            script_data = _parse_json(ai_response)
        except Exception as e:
            current_app.logger.error(f"JSON parsing failed: {e}, response: {ai_response[:200]}")

            # Try to fix common JSON issues
            import re
            cleaned_response = ai_response.strip()

            # Remove markdown code blocks if present
            if cleaned_response.startswith('```'):
                cleaned_response = re.sub(r'^```(?:json)?\n?', '', cleaned_response)
                cleaned_response = re.sub(r'\n```$', '', cleaned_response)

            # Try parsing again
            try:
                script_data = _parse_json(cleaned_response)
            except:
                # Last resort: create minimal structure
                current_app.logger.warning("Using fallback script structure")
                script_data = {
                    "title": f"{lang} Promotional Video",
                    "duration_seconds": dur,
                    "scenes": [
                        {
                            "scene_number": 1,
                            "duration": f"{dur}s",
                            "visual_prompt": project,
                            "narration": summary if summary else "Promotional content",
                            "on_screen_text": "Call to Action",
                            "text_overlays": []
                        }
                    ],
                    "voiceover_full_script": summary if summary else "Promotional video content",
                    "text_overlay_instructions": {"font": "Cairo", "direction": "rtl" if language == "ar" else "ltr"},
                    "music_mood": "upbeat",
                    "target_platforms": ["Instagram", "TikTok"],
                    "hashtags": ["viral", "business"]
                }

        # Ensure scenes have scene_number if missing
        if isinstance(script_data, dict) and "scenes" in script_data:
            for i, scene in enumerate(script_data["scenes"]):
                if isinstance(scene, dict) and "scene_number" not in scene:
                    scene["scene_number"] = i + 1

        campaign.script = json.dumps(script_data, ensure_ascii=False) if isinstance(script_data, dict) else ai_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:
        campaign.status = "draft"
        db.session.commit()
        current_app.logger.error(f"Script generation failed: {e}")
        return jsonify({"error": str(e)}), 500


@campaigns_bp.route("/api/script-status/<int:campaign_id>")
@login_required
def api_script_status(campaign_id):
    """Check the status of script generation for polling"""
    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": "ready", "script": campaign.script})
    elif campaign.status == "script_processing":
        return jsonify({"status": "processing", "message": "Script generation in progress"})
    elif campaign.status == "draft":
        return jsonify({"status": "pending", "message": "Script generation not started"})
    else:
        return jsonify({"status": "error", "error": "Unknown status"})


@campaigns_bp.route("/api/update-language/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def api_update_language(campaign_id):
    """Update campaign video language."""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403

    # Don't allow language change if video is already generated
    if campaign.video_url:
        return jsonify({"error": "لا يمكن تغيير اللغة بعد توليد الفيديو"}), 400

    try:
        data = request.get_json(silent=True) or {}
        new_language = data.get("video_language", "ar")

        if new_language not in ["ar", "en"]:
            return jsonify({"error": "Invalid language. Use 'ar' or 'en'"}), 400

        campaign.video_language = new_language
        db.session.commit()

        return jsonify({"status": "done", "language": new_language})
    except Exception as e:
        current_app.logger.error(f"Language update 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 {}

        # Use visual prompt for AI video generation (in English, not Arabic)
        if script_data.get("visual_prompts", {}).get("main_subject"):
            # New format with visual prompts
            visual_prompt = script_data["visual_prompts"]["main_subject"]

            # Add more descriptive elements from the script
            if script_data.get("title"):
                visual_prompt = f"{script_data['title']}: {visual_prompt}"

            # Add language-specific instructions
            if campaign.video_language == "ar":
                visual_prompt += ", no text, no writing, no English letters, visual only, Arabic business style"
            else:
                visual_prompt += ", professional business video"

            # Add style and color info
            if script_data["visual_prompts"].get("overall_style"):
                visual_prompt += f", {script_data['visual_prompts']['overall_style']} style"
            if script_data["visual_prompts"].get("color_scheme"):
                visual_prompt += f", {script_data['visual_prompts']['color_scheme']} colors"

            # Add information from first scene if available
            if script_data.get("scenes") and len(script_data["scenes"]) > 0:
                first_scene = script_data["scenes"][0]
                if first_scene.get("visual_prompt"):
                    visual_prompt += f", {first_scene['visual_prompt']}"
        else:
            # Fallback: try to use visual_prompt from first scene
            if script_data.get("scenes") and len(script_data["scenes"]) > 0:
                visual_prompt = script_data["scenes"][0].get("visual_prompt", "")
                if not visual_prompt:
                    # Last resort: use voiceover but warn about Arabic text
                    visual_prompt = script_data.get("voiceover_full_script", "Professional business video")
                    current_app.logger.warning(f"Using voiceover as visual prompt may cause issues with Arabic text")
            else:
                visual_prompt = script_data.get("voiceover_full_script", "Professional business video")

        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(visual_prompt[:500], duration=duration))

        # Check for billing errors and suggest alternatives
        if result.get("status") == "error":
            error_msg = result.get("error", "")
            if "billing" in error_msg.lower() or "limit" in error_msg.lower():
                # Suggest alternative providers
                alternatives = {
                    "sora": ["kling", "veo", "runway"],
                    "veo": ["kling", "sora", "runway"],
                    "runway": ["kling", "pika", "veo"],
                    "pika": ["kling", "fal", "runway"],
                    "fal": ["kling", "veo", "sora"],
                }

                alt_providers = alternatives.get(effective_provider, ["kling", "veo"])
                result["billing_error"] = True
                result["alternative_providers"] = alt_providers
                result["suggestion"] = f"Try switching to: {', '.join(alt_providers)}. Kling AI is recommended for best performance."

        # Store text overlays for post-processing
        if script_data.get("scenes"):
            text_overlays = []
            for scene in script_data["scenes"]:
                if scene.get("text_overlays"):
                    text_overlays.extend(scene["text_overlays"])
                elif scene.get("on_screen_text"):
                    # Convert simple on_screen_text to text_overlay format
                    text_overlays.append({
                        "text": scene["on_screen_text"],
                        "position": "center",
                        "start_time": scene.get("start_time", 0),
                        "end_time": scene.get("end_time", duration)
                    })

            if text_overlays:
                campaign.text_overlays = json.dumps(text_overlays, ensure_ascii=False)

        # Store overlay instructions
        if script_data.get("text_overlay_instructions"):
            campaign.overlay_instructions = json.dumps(script_data["text_overlay_instructions"], ensure_ascii=False)

        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/recreate-video/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def api_recreate_video(campaign_id):
    """Recreate/regenerate video for campaign with custom settings."""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403

    if not campaign.script:
        return jsonify({"error": "يجب توليد السيناريو أولاً"}), 400

    try:
        # Get new settings from request
        data = request.get_json() or {}
        new_language = data.get("video_language")
        new_duration = data.get("video_duration")
        new_script = data.get("script")

        # Update campaign settings if provided
        if new_language:
            campaign.video_language = new_language
        if new_duration:
            campaign.video_duration = int(new_duration)
        if new_script:
            campaign.script = new_script

        # Save current video to history before recreating
        if campaign.video_url:
            from app.models.campaign import VideoHistory
            old_video = VideoHistory(
                campaign_id=campaign.id,
                user_id=current_user.id,
                video_url=campaign.video_url,
                video_id=campaign.video_id,
                video_with_text_url=campaign.video_with_text_url,
                video_language=campaign.video_language,
                video_duration=campaign.video_duration,
                video_provider=campaign.video_provider,
                script_snapshot=campaign.script
            )
            db.session.add(old_video)
            current_app.logger.info(f"Saved old video to history for campaign {campaign.id}")

        # Clear existing video data from campaign (but keep in history)
        campaign.video_url = None
        campaign.video_id = None
        campaign.video_with_text_url = None
        campaign.status = "script_ready"

        db.session.commit()

        # Trigger video generation with updated settings
        script_data = json.loads(campaign.script) if campaign.script else {}

        # Use visual prompt for AI video generation (in English, not Arabic)
        if script_data.get("visual_prompts", {}).get("main_subject"):
            # New format with visual prompts
            visual_prompt = script_data["visual_prompts"]["main_subject"]

            # Add more descriptive elements from the script
            if script_data.get("title"):
                visual_prompt = f"{script_data['title']}: {visual_prompt}"

            # Add language-specific instructions
            if campaign.video_language == "ar":
                visual_prompt += ", no text, no writing, no English letters, visual only, Arabic business style"
            else:
                visual_prompt += ", professional business video"

            # Add style and color info
            if script_data["visual_prompts"].get("overall_style"):
                visual_prompt += f", {script_data['visual_prompts']['overall_style']} style"
            if script_data["visual_prompts"].get("color_scheme"):
                visual_prompt += f", {script_data['visual_prompts']['color_scheme']} colors"

            # Add information from first scene if available
            if script_data.get("scenes") and len(script_data["scenes"]) > 0:
                first_scene = script_data["scenes"][0]
                if first_scene.get("visual_prompt"):
                    visual_prompt += f", {first_scene['visual_prompt']}"
        else:
            # Fallback: try to use visual_prompt from first scene
            if script_data.get("scenes") and len(script_data["scenes"]) > 0:
                visual_prompt = script_data["scenes"][0].get("visual_prompt", "")
                if not visual_prompt:
                    visual_prompt = script_data.get("voiceover_full_script", "Professional business video")

        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(visual_prompt[:500], duration=duration))

        # Check for billing errors and suggest alternatives
        if result.get("status") == "error":
            error_msg = result.get("error", "")
            if "billing" in error_msg.lower() or "limit" in error_msg.lower():
                # Suggest alternative providers
                alternatives = {
                    "sora": ["kling", "veo", "runway"],
                    "veo": ["kling", "sora", "runway"],
                    "runway": ["kling", "pika", "veo"],
                    "pika": ["kling", "fal", "runway"],
                    "fal": ["kling", "veo", "sora"],
                }

                alt_providers = alternatives.get(effective_provider, ["kling", "veo"])
                result["billing_error"] = True
                result["alternative_providers"] = alt_providers
                result["suggestion"] = f"Try switching to: {', '.join(alt_providers)}. Kling AI is recommended for best performance."

        # Store text overlays for post-processing
        if script_data.get("scenes"):
            text_overlays = []
            for scene in script_data["scenes"]:
                if scene.get("text_overlays"):
                    text_overlays.extend(scene["text_overlays"])
                elif scene.get("on_screen_text"):
                    text_overlays.append({
                        "text": scene["on_screen_text"],
                        "position": "center",
                        "start_time": scene.get("start_time", 0),
                        "end_time": scene.get("end_time", duration)
                    })

            if text_overlays:
                campaign.text_overlays = json.dumps(text_overlays, ensure_ascii=False)

        # Store overlay instructions
        if script_data.get("text_overlay_instructions"):
            campaign.overlay_instructions = json.dumps(script_data["text_overlay_instructions"], ensure_ascii=False)

        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({
            "status": "success",
            "message": f"جاري إنشاء الفيديو باللغة {'العربية' if campaign.video_language == 'ar' else 'English'}",
            "video_id": campaign.video_id
        })

    except Exception as e:
        campaign.status = "script_ready"
        db.session.commit()
        current_app.logger.error(f"Video recreation failed: {e}")
        return jsonify({"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", "")

            # Auto-apply Arabic text overlays if this is an Arabic video
            if campaign.video_language == "ar" and campaign.text_overlays:
                try:
                    from app.services.text_overlay import TextOverlayService
                    import tempfile
                    import requests as _req

                    # Download video to temporary location
                    video_response = _req.get(campaign.video_url, stream=True, timeout=30)
                    with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as tmp_video:
                        for chunk in video_response.iter_content(chunk_size=8192):
                            tmp_video.write(chunk)
                        video_path = tmp_video.name

                    # Parse text overlays
                    text_overlays = campaign.text_overlays if isinstance(campaign.text_overlays, list) else []
                    if text_overlays:
                        # Create output path
                        output_filename = f"ar_{_uuid.uuid4().hex}.mp4"
                        output_path = os.path.join(current_app.static_folder, "videos", output_filename)

                        # Get font settings
                        font_name = "Noto"  # Default Arabic font
                        if campaign.overlay_instructions and isinstance(campaign.overlay_instructions, dict):
                            font_name = campaign.overlay_instructions.get("font", "Noto")

                        # Add Arabic text overlays
                        overlay_service = TextOverlayService()
                        success = overlay_service.add_arabic_text_overlay(
                            video_path, text_overlays, output_path, font_name=font_name
                        )

                        if success:
                            # Clean up input video
                            os.unlink(video_path)

                            # Update campaign with Arabic text overlay version
                            campaign.video_url = url_for("static", filename=f"videos/{output_filename}")
                            campaign.video_with_text_url = campaign.video_url
                            current_app.logger.info(f"Arabic text overlays applied for campaign {campaign.id}")
                        else:
                            os.unlink(video_path)
                            current_app.logger.warning(f"Text overlay failed for campaign {campaign.id}, using original video")
                except Exception as overlay_error:
                    current_app.logger.error(f"Auto text overlay failed: {overlay_error}")
                    # Continue with original video if overlay fails

            # Add Arabic voiceover narration if this is an Arabic video
            if campaign.video_language == "ar":
                try:
                    from app.services.tts_service import TTSService
                    import tempfile
                    import requests as _req

                    # Get script data for voiceover
                    script_data = json.loads(campaign.script) if campaign.script else {}
                    voiceover_text = script_data.get("voiceover_full_script", "")

                    if voiceover_text:
                        tts_service = TTSService()

                        # Download current video to temporary location
                        video_response = _req.get(campaign.video_url, stream=True, timeout=30)
                        with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as tmp_video:
                            for chunk in video_response.iter_content(chunk_size=8192):
                                tmp_video.write(chunk)
                            video_path = tmp_video.name

                        # Generate Arabic audio
                        audio_filename = f"ar_audio_{_uuid.uuid4().hex}.mp3"
                        audio_path = os.path.join(current_app.static_folder, "audio", audio_filename)
                        os.makedirs(os.path.dirname(audio_path), exist_ok=True)

                        audio_generated = tts_service.generate_narration_audio(
                            voiceover_text,
                            language="ar",
                            output_path=audio_path
                        )

                        if audio_generated:
                            # Create output path for video with audio
                            output_filename = f"ar_voice_{_uuid.uuid4().hex}.mp4"
                            output_path = os.path.join(current_app.static_folder, "videos", output_filename)

                            # Add audio to video
                            audio_added = tts_service.add_audio_to_video(
                                video_path,
                                audio_path,
                                output_path
                            )

                            if audio_added:
                                # Clean up temporary files
                                os.unlink(video_path)
                                os.unlink(audio_path)

                                # Update campaign with voiceover version
                                campaign.video_url = url_for("static", filename=f"videos/{output_filename}")
                                campaign.video_with_audio_url = campaign.video_url
                                current_app.logger.info(f"Arabic voiceover added for campaign {campaign.id}")

                                result["arabic_voiceover"] = "Arabic narration has been added to your video."
                                result["audio_note"] = "Professional Arabic voiceover generated using text-to-speech technology."
                            else:
                                # Clean up video if audio mixing failed
                                os.unlink(video_path)
                                os.unlink(audio_path)
                                current_app.logger.warning(f"Audio mixing failed for campaign {campaign.id}, using video without audio")
                        else:
                            os.unlink(video_path)
                            current_app.logger.warning(f"TTS generation failed for campaign {campaign.id}, using video without audio")
                except Exception as tts_error:
                    current_app.logger.error(f"Voiceover generation failed: {tts_error}")
                    # Continue with original video if TTS fails

            campaign.status = "video_ready"
            db.session.commit()
            result["video_url"] = campaign.video_url

            # Inform user about text overlay processing
            if campaign.video_language == "ar" and campaign.text_overlays:
                result["arabic_text_overlay"] = "Arabic text overlays are being applied to your video. This may take a few moments."
                result["processing_note"] = "Arabic text is being added to the video using professional fonts (Noto Naskh Arabic)"
        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("/api/add-text-overlays/<int:campaign_id>", methods=["POST"])
@csrf.exempt
@login_required
def api_add_text_overlays(campaign_id):
    """Add Arabic text overlays to completed video."""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403

    if not campaign.video_url:
        return jsonify({"error": "Video not ready"}), 400

    if not campaign.text_overlays:
        return jsonify({"error": "No text overlays configured"}), 400

    try:
        from app.services.text_overlay import TextOverlayService
        import tempfile
        import os

        # Download video to temporary location
        import requests
        response = requests.get(campaign.video_url, stream=True, timeout=30)

        with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as tmp_video:
            for chunk in response.iter_content(chunk_size=8192):
                tmp_video.write(chunk)
            video_path = tmp_video.name

        # Parse text overlays
        text_overlays = campaign.text_overlays if isinstance(campaign.text_overlays, list) else []

        # Create output path
        output_path = tempfile.mktemp(suffix='.mp4')

        # Get font settings from overlay instructions
        font_name = "Noto"  # Default
        if campaign.overlay_instructions and isinstance(campaign.overlay_instructions, dict):
            font_name = campaign.overlay_instructions.get("font", "Noto")

        # Add text overlays
        overlay_service = TextOverlayService()
        success = overlay_service.add_arabic_text_overlay(
            video_path, text_overlays, output_path, font_name=font_name
        )

        if success:
            # Clean up input video
            os.unlink(video_path)

            # Update campaign with video URL (in production, upload to cloud storage)
            campaign.video_with_text_url = output_path
            campaign.status = "completed"
            db.session.commit()

            return jsonify({
                "status": "success",
                "message": "Arabic text overlays added successfully",
                "video_with_text": output_path,
                "note": "Video processed with Arabic text overlays"
            })
        else:
            os.unlink(video_path)
            return jsonify({"error": "Text overlay failed"}), 500

    except Exception as e:
        current_app.logger.error(f"Text overlay processing error: {e}")
        return jsonify({"error": str(e)}), 500


@campaigns_bp.route("/api/test-arabic-text", methods=["POST"])
@csrf.exempt
@login_required
def api_test_arabic_text():
    """Test Arabic text rendering with sample video."""
    try:
        from app.services.text_overlay import TextOverlayService

        overlay_service = TextOverlayService()

        # Test Arabic rendering
        result = overlay_service.test_arabic_rendering()

        if result.get("status") == "success":
            return jsonify(result)
        else:
            return jsonify(result), 500

    except Exception as e:
        return jsonify({"error": str(e)}), 500


@campaigns_bp.route("/api/video-history/<int:campaign_id>")
@login_required
def api_video_history(campaign_id):
    """Get video history for a campaign"""
    campaign = Campaign.query.get_or_404(campaign_id)
    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403

    from app.models.campaign import VideoHistory
    history = VideoHistory.query.filter_by(
        campaign_id=campaign_id,
        user_id=current_user.id,
        is_deleted=False
    ).order_by(VideoHistory.created_at.desc()).all()

    history_data = []
    for item in history:
        history_data.append({
            "id": item.id,
            "video_url": item.video_url,
            "video_with_text_url": item.video_with_text_url,
            "video_language": item.video_language,
            "video_duration": item.video_duration,
            "video_provider": item.video_provider,
            "created_at": item.created_at.strftime("%Y-%m-%d %H:%M"),
            "language_display": "🇸🇦 العربية" if item.video_language == "ar" else "🇬🇧 English"
        })

    return jsonify({"history": history_data})


@campaigns_bp.route("/api/video-history/delete/<int:history_id>", methods=["POST"])
@login_required
def api_delete_history_video(history_id):
    """Delete a specific video from history"""
    from app.models.campaign import VideoHistory

    history_item = VideoHistory.query.get_or_404(history_id)
    if history_item.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403

    try:
        # Delete the physical video file if it exists
        if history_item.video_url and "static/videos/" in history_item.video_url:
            import os
            from flask import current_app
            video_path = os.path.join(current_app.static_folder, history_item.video_url.lstrip("/static/"))
            if os.path.exists(video_path):
                os.remove(video_path)
                current_app.logger.info(f"Deleted history video file: {video_path}")

        # Delete text overlay video if exists
        if history_item.video_with_text_url and "static/videos/" in history_item.video_with_text_url:
            import os
            from flask import current_app
            video_path = os.path.join(current_app.static_folder, history_item.video_with_text_url.lstrip("/static/"))
            if os.path.exists(video_path):
                os.remove(video_path)
                current_app.logger.info(f"Deleted history text overlay video file: {video_path}")

        # Soft delete (mark as deleted but keep record)
        history_item.is_deleted = True
        history_item.file_removed = True
        db.session.commit()

        return jsonify({"status": "success", "message": "Video deleted successfully"})

    except Exception as e:
        current_app.logger.error(f"Error deleting history video: {e}")
        return jsonify({"error": str(e)}), 500


@campaigns_bp.route("/api/video-history/restore/<int:history_id>", methods=["POST"])
@login_required
def api_restore_history_video(history_id):
    """Restore a video from history to be the current campaign video"""
    from app.models.campaign import VideoHistory

    history_item = VideoHistory.query.get_or_404(history_id)
    campaign = Campaign.query.get_or_404(history_item.campaign_id)

    if campaign.user_id != current_user.id:
        return jsonify({"error": "Unauthorized"}), 403

    try:
        # Save current video to history before restoring
        if campaign.video_url:
            old_video = VideoHistory(
                campaign_id=campaign.id,
                user_id=current_user.id,
                video_url=campaign.video_url,
                video_id=campaign.video_id,
                video_with_text_url=campaign.video_with_text_url,
                video_language=campaign.video_language,
                video_duration=campaign.video_duration,
                video_provider=campaign.video_provider,
                script_snapshot=campaign.script
            )
            db.session.add(old_video)

        # Restore video from history
        campaign.video_url = history_item.video_url
        campaign.video_id = history_item.video_id
        campaign.video_with_text_url = history_item.video_with_text_url
        campaign.video_language = history_item.video_language
        campaign.video_duration = history_item.video_duration
        campaign.video_provider = history_item.video_provider
        campaign.status = "video_ready"

        # Restore script if available
        if history_item.script_snapshot:
            campaign.script = history_item.script_snapshot

        db.session.commit()

        return jsonify({"status": "success", "message": "Video restored successfully"})

    except Exception as e:
        current_app.logger.error(f"Error restoring history video: {e}")
        return jsonify({"error": str(e)}), 500


@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"))
