from flask import Blueprint, jsonify, render_template, request, flash, redirect, url_for, session, current_app
from extensions import get_db_connection, client
from decorators import login_required
from google.genai import types
import markdown
from datetime import datetime, timedelta
import os
import io
import base64
import time
import shutil
import random as py_random
from PIL import Image
from werkzeug.utils import secure_filename

content_bp = Blueprint('content_bp', __name__)

# =========================================================
# 1. GENERATE TEXT ROUTE (Saves topic to session)
# =========================================================
@content_bp.route('/generate_text', methods=['GET', 'POST'])
@login_required
def generate_text():
    """Main content generation page with Instant Quota Feedback"""
    
    if request.method == 'POST':
        if not session.get('linkedin_token'):
            flash("🔗 Please connect to LinkedIn first.", "warning")
            return redirect(url_for('social_bp.connect_hub'))

        # 1. Extract Data
        content_length = request.form.get('content_length')
        content_schedule = request.form.get('content_schedule')
        start_date_str = request.form.get('start_date')
        topic_context = request.form.get('topic_context')
        purpose_goal = request.form.get('purpose_goal')
        target_audience = request.form.get('target_audience')
        tone_of_voice = request.form.get('tone_of_voice')
        formatting = request.form.get('formatting')
        keywords = request.form.get('keywords', '')
        cta = request.form.get('cta', '')
        hashtags = request.form.get('hashtags', '')
        user_prompt = request.form.get('prompt', '')

        try:
            start_date = datetime.strptime(start_date_str, "%Y-%m-%d")
            daywise_content = []
            
            schedule_map = {"Single Day": 1, "2 Days": 2, "5 Days": 5, "1 Week": 7, "2 Weeks": 14}
            num_days = schedule_map.get(content_schedule, 1)
            schedule_items = [start_date + timedelta(days=i) for i in range(num_days)]

            # 2. Iterate through schedule
            for scheduled_date in schedule_items:
                
                # Length Logic
                if content_length == "Short":
                    length_desc = "Exactly 3 distinct paragraphs. No summary."
                    max_tokens = 1500
                elif content_length == "Medium":
                    length_desc = "5-6 detailed paragraphs."
                    max_tokens = 3000
                else:
                    length_desc = "Long-form article (8+ paragraphs)."
                    max_tokens = 5000

                prompt_body = (
                    f"Write a {content_length} LinkedIn post for {scheduled_date.strftime('%A, %B %d, %Y')}.\n"
                    f"Topic: {topic_context}\n"
                    f"Goal: {purpose_goal}\n"
                    f"Audience: {target_audience}\n"
                    f"Tone: {tone_of_voice}\n"
                    f"Length: {length_desc}\n"
                    f"Formatting: {formatting}\n"
                    f"Keywords: {keywords}\n"
                    f"CTA: {cta}\n"
                    f"Hashtags: {hashtags if hashtags else 'Relevant tags'}\n"
                    f"Extra: {user_prompt}\n\n"
                    f"CRITICAL: Complete every sentence. Do not stop mid-thought."
                )

                try:
                    # 3. Single Attempt - No Loop/Retry
                    response = client.models.generate_content(
                        model='gemini-2.5-flash', 
                        contents=prompt_body,
                        config=types.GenerateContentConfig(
                            max_output_tokens=max_tokens,
                            temperature=0.7
                        )
                    )

                    if response and response.text:
                        text_output = response.text.strip()
                        # Cleanup headers
                        for noise in ["Here is a post:", "## LinkedIn Post", "Post Content:"]:
                            text_output = text_output.replace(noise, "")

                        daywise_content.append({
                            "date": scheduled_date.strftime("%Y-%m-%d"),
                            "text": text_output.strip(),
                            "html": markdown.markdown(text_output.strip()),
                            "topic_context": topic_context
                        })
                    else:
                        # Graceful fallback for empty responses
                        daywise_content.append({
                            "date": scheduled_date.strftime("%Y-%m-%d"),
                            "text": "Content generation skipped.",
                            "html": "<p>Skipped.</p>",
                            "topic_context": topic_context
                        })

                except Exception as e:
                    error_msg = str(e)
                    # 4. INSTANT USER FEEDBACK (Stop immediately on 429)
                    if "429" in error_msg:
                        flash("⚠️ Daily Limit Reached: You have hit the Free Tier usage limit. Please try again in a few minutes or tomorrow.", "warning")
                        # Return whatever content we managed to generate so far, or redirect back
                        if daywise_content:
                            session['daywise_content'] = daywise_content
                            return render_template('daywise_preview.html', daywise_content=daywise_content)
                        else:
                            return render_template('text_generation.html')
                    else:
                        print(f"API Error: {error_msg}")
                        flash("❌ An error occurred while contacting AI. Please try again.", "danger")
                        return render_template('text_generation.html')

            # Success Path
            session['daywise_content'] = daywise_content
            flash("✅ Content generated successfully!", "success")
            return render_template('daywise_preview.html', daywise_content=daywise_content)

        except Exception as e:
            print(f"System Error: {e}")
            flash("System Error: Could not process request.", "danger")
            return render_template('text_generation.html')

    return render_template('text_generation.html')

@content_bp.route('/regenerate_single_post', methods=['POST'])
def regenerate_single_post():
    try:
        data = request.get_json()
        topic_context = data.get('topic_context')
        date = data.get('date')
        
        # Ideally, you stored the user's main "Prompt" or "Tone" in session 
        # when they first generated the schedule.
        # Example: session['last_user_prompt'] or session['user_tone']
        main_theme = session.get('last_user_prompt', 'General Professional content') 

        # Construct a specific prompt for this single day
        prompt = f"""
        Write a professional LinkedIn post for the date: {date}.
        Main Theme: {main_theme}
        Specific Focus for this post: {topic_context}
        
        Keep it engaging, include relevant emojis, and keep it under 1500 characters.
        Do not include "Here is a post" or any conversational filler. Just the post content.
        """

        # Call Gemini (Adjust this line to match your exact AI call method)
        response = client.models.generate_content(
            model="gemini-2.5-flash", 
            contents=prompt
        )
        
        new_text = response.text.strip()

        return jsonify({
            "success": True, 
            "new_content": new_text
        })

    except Exception as e:
        print(f"Regeneration Error: {e}")
        return jsonify({"success": False, "error": str(e)}), 500

# =========================================================
# 2. GENERATE IMAGE ROUTE
# =========================================================
@content_bp.route('/generate_image', methods=['POST'])
@login_required
def generate_image():
    post_text = request.form.get('post_text', "").strip()
    post_index = request.form.get('post_index', "").strip()

    if not post_text:
        flash("⚠️ No text found to generate an image.", "warning")
        return redirect(url_for('content_bp.generate_text'))

    try:
        # STEP 1: Extract visual concept
        extraction_prompt = f"Extract core visual theme in 5 words for image generation:\n{post_text[:300]}"
        
        concept_response = client.models.generate_content(
            model="gemini-2.5-flash", contents=extraction_prompt,
            config=types.GenerateContentConfig(max_output_tokens=30)
        )
        image_concept = concept_response.text.strip() if concept_response and concept_response.text else "professional business scene"

        # STEP 2: Generate Image
        image_prompt = f"Professional image: {image_concept}. Modern, minimal, business aesthetic."
        generated_image_b64 = None
        
        # Simple retry logic
        for _ in range(3):
            try:
                response = client.models.generate_content(
                    model="gemini-2.5-flash", contents=image_prompt,
                    config=types.GenerateContentConfig(response_modalities=["TEXT", "IMAGE"], candidate_count=1)
                )
                if response.candidates:
                    for part in response.candidates[0].content.parts:
                        if hasattr(part, "inline_data") and part.inline_data:
                            img = Image.open(io.BytesIO(part.inline_data.data))
                            buf = io.BytesIO()
                            img.save(buf, format="PNG")
                            generated_image_b64 = base64.b64encode(buf.getvalue()).decode("utf-8")
                            break
                if generated_image_b64: break
            except Exception:
                time.sleep(1)

        if not generated_image_b64:
            flash("⚠️ Could not generate image.", "warning")
            return redirect(url_for('content_bp.generate_text'))

        # STEP 3: Save Image
        # Use current_app.root_path to get correct static path
        save_dir = os.path.join(current_app.root_path, "static", "generated_image")
        os.makedirs(save_dir, exist_ok=True)

        filename = f"generated_{int(time.time())}_{post_index}.png"
        filepath = os.path.join(save_dir, filename)

        with open(filepath, "wb") as f:
            f.write(base64.b64decode(generated_image_b64))

        # STEP 4: Update Session
        daywise_content = session.get('daywise_content', [])
        idx = int(post_index) - 1
        if 0 <= idx < len(daywise_content):
            daywise_content[idx]["image"] = filename
            session['daywise_content'] = daywise_content
            session.modified = True
            flash("🎨 Image generated!", "success")
        
        return redirect(url_for('content_bp.generate_text'))

    except Exception as e:
        print(f"[ERROR] {e}")
        flash("Error generating image.", "danger")
        return redirect(url_for('content_bp.generate_text'))


# =========================================================
# 3. SAVE SCHEDULE ROUTE (Inserts topic to DB)
# =========================================================
@content_bp.route('/save_schedule', methods=['POST'])
@login_required
def save_schedule():
    # 1. Verification
    if 'linkedin_token' not in session:
        flash("Please connect to LinkedIn first.", "warning")
        return redirect(url_for('social_bp.connect_hub'))

    user_id = session.get('user_id') # From internal users table
    author_urn = session.get('linkedin_user_urn') # Platform URN
    total_posts = int(request.form.get('total_posts', 0))
    saved_count = 0
    
    conn = get_db_connection()
    cursor = conn.cursor()
    
    # Path for storing uploaded/copied images
    FINAL_UPLOAD_FOLDER = os.path.join(current_app.root_path, "static", "uploaded_post_img")
    os.makedirs(FINAL_UPLOAD_FOLDER, exist_ok=True)

    for i in range(1, total_posts + 1):
        # Extract data from the daywise_preview form
        post_date = request.form.get(f'post_date_{i}')
        post_content = request.form.get(f'post_content_{i}')
        post_topic = request.form.get(f'post_topic_{i}', '')

        # Image handling: AI generated name or Manual files
        gen_img_name = request.form.get(f'post_image_{i}', "").strip()
        manual_files = request.files.getlist(f'manual_image_{i}')

        if post_date and post_content:
            try:
                # 2. INSERT into 'posts_linkedin' table
                # Using columns: user_id, scheduled_at, content, topic_context, status, posted_urn
                cursor.execute("""
                    INSERT INTO posts_linkedin 
                    (user_id, scheduled_at, content, topic_context, status, posted_urn, created_at)
                    VALUES (%s, %s, %s, %s, 'scheduled', %s, NOW())
                """, (user_id, post_date, post_content.strip(), post_topic, author_urn))
                
                conn.commit()
                post_id = cursor.lastrowid # Get ID for image naming
                
                # 3. Process Images for the 'media_urls' column
                final_filenames = []
                
                # Check for manual file uploads first
                has_manual_files = any(f.filename for f in manual_files)
                if has_manual_files:
                    for file in manual_files:
                        if file and file.filename:
                            fname = secure_filename(file.filename)
                            new_name = f"manual_{datetime.now().strftime('%Y%m%d%H%M%S')}_{post_id}{os.path.splitext(fname)[1]}"
                            file.save(os.path.join(FINAL_UPLOAD_FOLDER, new_name))
                            final_filenames.append(new_name)
                
                # Fallback to AI-generated image if no manual upload
                elif gen_img_name:
                    src_path = os.path.join(current_app.root_path, "static", "generated_image", gen_img_name)
                    if os.path.exists(src_path):
                        new_name = f"ai_{datetime.now().strftime('%Y%m%d%H%M%S')}_{post_id}.png"
                        shutil.copy(src_path, os.path.join(FINAL_UPLOAD_FOLDER, new_name))
                        final_filenames.append(new_name)
                
                # 4. UPDATE 'media_urls' column with comma-separated filenames
                if final_filenames:
                    csv_images = ",".join(final_filenames)
                    cursor.execute("UPDATE posts_linkedin SET media_urls=%s WHERE id=%s", (csv_images, post_id))
                    conn.commit()

                saved_count += 1

            except Exception as e:
                print(f"[ERROR] Failed to save post {i}: {e}")
                continue

    cursor.close()
    conn.close()
    flash(f"✅ {saved_count} posts saved and scheduled successfully!", "success")
    return redirect(url_for('post_bp.view_posts'))


# =========================================================
# 4. CLEAR GENERATION
# =========================================================
@content_bp.route('/clear_and_generate')
@login_required
def clear_and_generate():
    """Clear previous generation and start fresh"""
    if 'daywise_content' in session:
        session.pop('daywise_content')
    return redirect(url_for('content_bp.generate_text'))