import re
import os
from typing import List, Dict, Optional
from src.core.models import Challenge


class ChallengeLoader:
    def __init__(self, challenges_dir: str = "src/challenges/"):
        self.challenges_dir = challenges_dir

    def load_all(self) -> Dict[str, Challenge]:
        challenges = {}
        if not os.path.exists(self.challenges_dir):
            return challenges

        for filename in os.listdir(self.challenges_dir):
            if filename.endswith(".md"):
                path = os.path.join(self.challenges_dir, filename)
                challenge = self.parse_file(path)
                if challenge:
                    key = filename.replace(".md", "")
                    challenges[key] = challenge
        return challenges

    def parse_file(self, path: str) -> Optional[Challenge]:
        with open(path, "r", encoding="utf-8") as f:
            content = f.read()

        # Parse YAML frontmatter if present
        fm_data = {}
        if content.startswith("---"):
            parts = content.split("---", 2)
            if len(parts) >= 3:
                fm_raw = parts[1]
                content = parts[2]
                for line in fm_raw.splitlines():
                    if ":" in line:
                        k, v = line.split(":", 1)
                        fm_data[k.strip().lower()] = v.strip()

        name = fm_data.get("name")
        difficulty = fm_data.get("difficulty")
        language = fm_data.get("language")
        subject = fm_data.get("subject") or fm_data.get("topic")

        # Regex extraction fallback for markdown headers
        if not name:
            name_match = re.search(r"# (?:Challenge: )?(.*)", content)
            name = name_match.group(1).strip() if name_match else None

        if not difficulty:
            diff_match = re.search(r"\*\*Difficulty:\*\* (.*)", content)
            difficulty = diff_match.group(1).strip() if diff_match else "Medium"

        if not language:
            lang_match = re.search(r"\*\*Language:\*\* (.*)", content)
            language = lang_match.group(1).strip() if lang_match else "Python"

        if not subject:
            subj_match = re.search(r"\*\*(?:Subject|Topic):\*\* (.*)", content)
            subject = subj_match.group(1).strip() if subj_match else "General Concepts"

        desc_match = re.search(r"## Description\n(.*?)(?=\n##|$)", content, re.DOTALL)
        req_match = re.search(r"## Requirements\n(.*?)(?=\n##|$)", content, re.DOTALL)
        hint_match = re.search(r"## Hints\n(.*?)(?=\n##|$)", content, re.DOTALL)
        valid_match = re.search(r"## Validation\n-\s*\*\*Check:\*\* (.*)", content)
        exp_match = re.search(r"\*\*Expected Output:\*\* (.*)", content)

        if not name:
            return None

        description = desc_match.group(1).strip() if desc_match else ""

        requirements = (
            [
                r.strip("- ").strip()
                for r in req_match.group(1).strip().split("\n")
                if r.strip("- ")
            ]
            if req_match
            else []
        )

        hints = (
            [
                h.strip("- ").strip()
                for h in hint_match.group(1).strip().split("\n")
                if h.strip("- ")
            ]
            if hint_match
            else []
        )

        validation_check = valid_match.group(1).strip() if valid_match else ""
        expected_output = exp_match.group(1).strip() if exp_match else ""

        return Challenge(
            name=name,
            difficulty=difficulty,
            language=language,
            subject=subject,
            description=description,
            requirements=requirements,
            hints=hints,
            validation_check=validation_check,
            expected_output=expected_output,
        )
