import re
import sys
from pathlib import Path

from django.conf import settings
from django.core.management.base import BaseCommand, CommandError

from api.models import Aspect, Hero, Item

# Add data directory to path for imports
sys.path.insert(0, str(Path(settings.BASE_DIR) / "data"))
from facets import HERO_FACETS


def _strip_comments(text: str) -> str:
    """Remove single-line and block comments from TypeScript data."""
    text = re.sub(r"/\*.*?\*/", "", text, flags=re.S)
    lines = []
    for line in text.splitlines():
        stripped = line.strip()
        if stripped.startswith("//"):
            continue
        lines.append(line)
    return "\n".join(lines)


def _extract_objects(text: str, require_primary: bool = False):
    cleaned = _strip_comments(text)
    objects = []

    for match in re.finditer(r"\{[^}]*\}", cleaned):
        chunk = match.group(0)
        entry = {}
        id_match = re.search(r"['\"]?id['\"]?\s*:\s*(['\"])(.*?)\1", chunk)
        name_match = re.search(r"['\"]?name['\"]?\s*:\s*(['\"])(.*?)\1", chunk)
        if not (id_match and name_match):
            continue
        entry["slug"] = id_match.group(2)
        entry["name"] = name_match.group(2)

        if require_primary:
            primary_match = re.search(r"['\"]?primary['\"]?\s*:\s*(['\"])(.*?)\1", chunk)
            if not primary_match:
                continue
            entry["primary"] = primary_match.group(2)

        if len(entry) == (3 if require_primary else 2):
            objects.append(entry)

    return objects


class Command(BaseCommand):
    help = "Load heroes, items and facets from data files into the database."

    def handle(self, *args, **options):
        base_dir = Path(settings.BASE_DIR)
        heroes_path = base_dir / "data" / "heroes.ts"
        items_path = base_dir / "data" / "items.ts"

        if not heroes_path.exists() or not items_path.exists():
            raise CommandError("Missing data files in the ./data directory.")

        heroes = _extract_objects(heroes_path.read_text(encoding="utf-8"), require_primary=True)
        items = _extract_objects(items_path.read_text(encoding="utf-8"), require_primary=False)

        if not heroes:
            raise CommandError("Failed to parse heroes.ts")
        if not items:
            raise CommandError("Failed to parse items.ts")

        hero_created = item_created = aspect_created = 0

        for hero in heroes:
            hero_obj, created = Hero.objects.update_or_create(
                name=hero["name"],
                defaults={
                    "primary": hero["primary"],
                },
            )
            hero_created += int(created)

            # Load facets for this hero
            facets = HERO_FACETS.get(hero["name"], [])
            for facet_name in facets:
                _, facet_created = Aspect.objects.update_or_create(
                    hero=hero_obj,
                    name=facet_name,
                )
                aspect_created += int(facet_created)

        for item in items:
            _, created = Item.objects.update_or_create(
                name=item["name"],
            )
            item_created += int(created)

        self.stdout.write(
            self.style.SUCCESS(
                f"Loaded {len(heroes)} heroes ({hero_created} new), "
                f"{len(items)} items ({item_created} new), "
                f"and {aspect_created} new facets."
            )
        )
