import os
from openai import OpenAI
import markdown2
import zipfile
from weasyprint import HTML
from pygments.formatters import HtmlFormatter
from dependencies.helper import *
from dotenv import load_dotenv
load_dotenv()

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
OUTPUT_FOLDER = os.getenv("OUTPUT_FOLDER", "./result")
working_dir = "imscc_temp"
content_dir = "wiki_content"

def generate_subtopics(topic):
    prompt_data = get_prompt('subtopics')
    prompt = prompt_data.format(topic=topic)
    response = clientCall(prompt)
    return [line.strip("- ") for line in response.split("\n") if line.strip()]

# Generate Course Objectives
def generate_course_objectives(topic):
    prompt_data = get_prompt('course_objectives')
    prompt = prompt_data.format(topic=topic)
    return clientCall(prompt)

# Generate the Course Outcomes
def generate_course_outcomes(topic):

    prompt_data = get_prompt('learning_outcomes')
    prompt = prompt_data.format(topic=topic)
    return clientCall(prompt)

# Generate a high-level Course Outline
def generate_course_outline(topic):
    prompt_data = get_prompt('course_outline')
    prompt = prompt_data.format(topic=topic)
    return clientCall(prompt)

# Establish the Course Outline
def establish_course_outline(topic):
    prompt_data = get_prompt('outline')
    prompt = prompt_data.format(topic=topic)
    return clientCall(prompt)

# Generation of Course Module Content (Detailed Outline)
def generate_detailed_course_outline(topic, modules):
    outline = ""
    for module in modules:
        prompt_data = get_prompt('high_level_outline')
        prompt = prompt_data.format(topic=topic, module=module)
        
        response = clientCall(prompt)
        outline += f"### {module}\n{response}\n\n"
        outline += generate_module_questions(topic, module)
    return outline


def explain_concepts(topic, subtopics):
    explanations = {}
    for sub in subtopics:
        prompt_data = get_prompt('course_concepts')
        prompt = prompt_data.format(topic=topic, sub=sub)
        explanations[sub] = clientCall(prompt)
        
    return explanations

def generate_module_questions(topic, module):
    """Generate multiple-choice questions for a specific module."""
    # This function assumes that the module is a string representing the module title.
    # You can modify the prompt to include more specific instructions if needed.
    
    prompt_data = get_prompt('module_questions')
    prompt = prompt_data.format(topic=topic, module=module)
    response = clientCall(prompt)
    return response

def generate_questions(subtopics):
    questions = {}
    for sub in subtopics:
        prompt_data = get_prompt('course_exercises')
        prompt = prompt_data.format(sub=sub)
        questions[sub] = clientCall(prompt)
        
    return questions

def generate_summary(topic):
    prompt_data = get_prompt('summary')
    prompt = prompt_data.format(topic=topic)
    return clientCall(prompt)

def generate_chaining_summary(topic, subtopics):
    prompt_data = get_prompt('chaining_summary')
    prompt = prompt_data.format(topic=topic, subtopics=', '.join(subtopics)) 
    return clientCall(prompt)

def generate_chaining_course_objectives(topic, subtopics):
    prompt_data = get_prompt('chaining_course_objectives')
    prompt = prompt_data.format(topic=topic, subtopics=', '.join(subtopics))
    return clientCall(prompt)

def generate_chaining_course_outcomes(topic, subtopics):
    prompt_data = get_prompt('chaining_course_outcomes')
    prompt = prompt_data.format(topic=topic, subtopics=', '.join(subtopics))
    return clientCall(prompt)

def generate_chaining_course_outline(topic, subtopics):
    no_of_modules = '5-10'
    prompt_data = get_prompt('chaining_course_outline')
    prompt = prompt_data.format(topic=topic, subtopics=', '.join(subtopics), no_of_modules=no_of_modules)
    return clientCall(prompt)

def clientCall(prompt):
    response = client.chat.completions.create(
        model=OPENAI_MODEL,
        messages=[{"role": "user", "content": prompt}]
    )
    return response.choices[0].message.content.strip()

def extract_module_titles(course_outline):
    lines = course_outline.strip().split("\n")
    titles = []
    for line in lines:
        if ". " in line:
            parts = line.split(". ", 1)
            if len(parts) > 1:
                titles.append(parts[1].split(":")[0].strip())
    return titles

def build_markdown(topic):
    subtopics = generate_subtopics(topic)
    print(f'## Course subtopics generated')
    explanations = explain_concepts(topic, subtopics)
    print(f'## Course explanations generated')
    questions = generate_questions(subtopics)
    print(f'## Course questions generated')
    md = f"# Course: {topic}\n\n"
    # Summary
    # summary = generate_summary(topic)
    summary = generate_chaining_summary(topic, subtopics)
    
    # print(f'## Course summary generated')
    md += f"## Summary\n{summary}\n\n"
    print(f'## Course Summary generated')

    # Objectives
    # objectives = generate_course_objectives(topic)
    objectives = generate_chaining_course_objectives(topic, subtopics)
    md += f"## Course Objectives\n{objectives}\n\n"
    print(f'## Course Objectives generated')
    # Outcomes
    # outcomes = generate_course_outcomes(topic)
    outcomes = generate_chaining_course_outcomes(topic, subtopics)
    md += f"## Course Outcomes\n{outcomes}\n\n"
    print(f'## Course Outcomes generated')
    # Outline
    # outline = generate_course_outline(topic)
    outline = generate_chaining_course_outline(topic, subtopics)
    md += f"## Course Outline\n{outline}\n\n"
    print(f'## Course Outline generated')
    # Detailed Modules
    module_titles = extract_module_titles(outline)
    detailed_modules = generate_detailed_course_outline(topic, module_titles)
    md += f"## Module Details\n{detailed_modules}"
    print(f'## Course Module Details generated')
    
    for sub in subtopics:
        md += f"## {sub}\n\n"
        md += f"{explanations[sub]}\n\n"
        md += f"### Quiz Questions\n{questions[sub]}\n\n"

    return md

def export_to_html_and_pdf(markdown_content, output_base):
    # Convert markdown to HTML with fenced code and syntax highlight
    extras = ["fenced-code-blocks", "code-friendly", "tables"]
    html_content = markdown2.markdown(markdown_content, extras=extras)
    
    # Add Pygments CSS for code styling
    style = HtmlFormatter().get_style_defs('.codehilite')
    style += """
    body, h1, h2, h3, h4, h5, h6, pre, code {
        word-wrap: break-word;
        overflow-wrap: break-word;
        white-space: normal;
    }
    pre, code {
        white-space: pre-wrap;
    }
    """
    full_html = f"<style>{style}</style>\n{html_content}"

    if not os.path.exists(OUTPUT_FOLDER):
        os.makedirs(OUTPUT_FOLDER, exist_ok=True)

    output_base = os.path.join(OUTPUT_FOLDER, output_base)
    
    # Save HTML
    html_file = f"{output_base}.html"
    with open(html_file, "w", encoding="utf-8") as f:
        f.write(full_html)

    # Save PDF
    pdf_file = f"{output_base}.pdf"
    HTML(string=full_html).write_pdf(pdf_file)

    print(f"✅ Exported to {html_file} and {pdf_file}")

def generate_course_materials(topic):
    markdown_content = build_markdown(topic)
    base_filename = topic.replace(" ", "_")
    if not os.path.exists(OUTPUT_FOLDER):
        os.makedirs(OUTPUT_FOLDER, exist_ok=True)

    output_base = os.path.join(OUTPUT_FOLDER, base_filename)
    # Save markdown
    with open(f"{output_base}.md", "w", encoding="utf-8") as f:
        f.write(markdown_content)
    export_to_html_and_pdf(markdown_content, base_filename)
    return markdown_content

def generate_course_materials_from_db(course_data):
    topic = course_data.topic
    markdown_content = build_markdown(topic)
    course_data.content_description = markdown_content
    course_data.content_outcomes = generate_chaining_course_outcomes(topic, course_data.subtopics)
    course_data.content_objectives = generate_chaining_course_objectives(topic, course_data.subtopics)
    course_data.content_summary = generate_chaining_summary(topic, course_data.subtopics)
    course_data.content_outline = generate_chaining_course_outline(topic, course_data.subtopics)
    
    return markdown_content

def generate_imscc(topic):
    """
    Generate an IMSCC package from the article content.
    """
    article_title = truncate_filename(
            topic.replace(" ", "_").replace("/", "_")
        )
    article_dir = os.path.join(working_dir, article_title)
    wiki_content_dir = os.path.join(article_dir, content_dir)
    os.makedirs(working_dir, exist_ok=True)
    os.makedirs(wiki_content_dir, exist_ok=True)

    output_path = os.path.join(OUTPUT_FOLDER, f"{article_title}.imscc")

    markdown_path = os.path.join(OUTPUT_FOLDER, f"{article_title}.md")
    print(markdown_path)
    if not os.path.exists(markdown_path):
        raise HTTPException(status_code=404, detail="Markdown file not found. Please generate the course first.")
    
    save_sections_as_html(topic,wiki_content_dir)
    # Check if the polished article file exists
    
    # self.prepare_article_question()
    
    # Create the manifest
    create_manifest(
        course_title=article_title,
        content_dir=wiki_content_dir,#os.path.join(self.wiki_content_dir, content_dir),
        wiki_dir=content_dir,
        output_file=os.path.join(article_dir, "imsmanifest.xml")
    )

    with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zf:
        for root, _, files in os.walk(working_dir):
            for file in files:
                full_path = os.path.join(root, file)
                arcname = os.path.relpath(full_path, start=article_dir)
                zf.write(full_path, arcname)

    # Clean up (optional)
    # shutil.rmtree(working_dir)

    return output_path

def save_sections_as_html(topic,wiki_content_dir):
    """
    Reads a markdown file, splits it into sections, and saves each section as an HTML file.
    """
    
    content = get_course_content(topic)
    
    sections = split_markdown_sections(content)
    
    for section in sections:
        lines = section.splitlines()
        if not lines:
            continue  # Skip empty sections
        title_line = lines[0].strip("# ").strip()
        filename = f"{title_line.lower().replace(' ', '_')}.html"

        html = markdown_to_html(title_line, section)
        output_path = os.path.join(wiki_content_dir, filename)
        
        with open(output_path, "w", encoding="utf-8") as out:
            out.write(html)

    print(f"✅ Exported {len(sections)} sections to: {wiki_content_dir}")

def get_course_content(topic: str) -> str:
    base_filename = topic.replace(" ", "_")
    course_path = os.path.join(OUTPUT_FOLDER, f"{base_filename}.md")
    if not os.path.exists(course_path):
        raise HTTPException(status_code=404, detail="Course markdown file not found.")
    content = read_txt_file(course_path)
    return content

def markdown_to_html(title: str, content: str) -> str:
    extras = ["fenced-code-blocks", "code-friendly", "tables"]
    html_content = markdown2.markdown(content, extras=extras)
    
    # Add Pygments CSS for code styling
    style = HtmlFormatter().get_style_defs('.codehilite')
    style += """
    body, h1, h2, h3, h4, h5, h6, pre, code {
        word-wrap: break-word;
        overflow-wrap: break-word;
        white-space: normal;
    }
    pre, code {
        white-space: pre-wrap;
    }
    """
    full_html = f"<style>{style}</style>\n{html_content}"
    
    return full_html