#!/usr/bin/env python3.12
"""
Update or stamp Design.md with uniqueness metadata.

Features:
- Extracts domain from file path
- Generates content hash for uniqueness verification
- Validates seed against known styles
- Can auto-extract seed from Uniqueness Notes section
- Structured metadata stamp
"""
from __future__ import annotations

import argparse
import datetime
import hashlib
import json
import pathlib
import re
import sys
from typing import Optional, List, Dict, Any


def load_known_seeds(script_dir: pathlib.Path) -> List[Dict[str, Any]]:
    """Load known seed/styles from seeds.json."""
    seeds_file = script_dir / "seed-styles" / "seeds.json"
    if seeds_file.exists():
        try:
            return json.loads(seeds_file.read_text(encoding="utf-8"))
        except Exception:
            pass
    return []


def extract_domain_from_path(path: pathlib.Path) -> Optional[str]:
    """Extract domain from path like sites/example.com-v1/DESIGN.md."""
    parts = path.parts
    for part in parts:
        # Match pattern like example.com-v1
        if re.match(r"^[\w.-]+\.(com|org|net|io|dev|app|wiki|quest|day|monster|party|studio|tech|works|xyz|st|id|bar)-v\d+$", part):
            # Extract domain without version
            match = re.match(r"^([\w.-]+)-v\d+$", part)
            if match:
                return match.group(1)
    return None


def extract_seed_from_content(content: str) -> Optional[str]:
    """Extract seed/style from Uniqueness Notes section."""
    # Look for patterns like "seed: xxx" or "style: xxx" or "Seed/Style: xxx"
    # Support composite styles like "aesthetic: val, layout: val"
    patterns = [
        r"(?:seed|style)[:\s]+([a-z0-9-:, \t]+)",
        r"Seed/Style[:\s]+([a-z0-9-:, \t]+)",
        r"chosen.*?[:\s]+([a-z0-9-:, \t]+)",
    ]

    # Focus on Uniqueness Notes section
    uniqueness_match = re.search(r"##\s*Uniqueness Notes(.*?)(?=##|$)", content, re.DOTALL | re.IGNORECASE)
    search_text = uniqueness_match.group(1) if uniqueness_match else content

    for pattern in patterns:
        match = re.search(pattern, search_text, re.IGNORECASE)
        if match:
            return match.group(1).strip().lower()

    return None


def extract_aesthetic_from_content(content: str) -> Optional[str]:
    """Extract aesthetic description from Aesthetics section."""
    match = re.search(r"##\s*Aesthetics.*?\n(.*?)(?=##|$)", content, re.DOTALL | re.IGNORECASE)
    if match:
        text = match.group(1).strip()
        # Get first meaningful line
        for line in text.split("\n"):
            line = line.strip().strip("-").strip("*").strip()
            if line and len(line) > 10:
                # Truncate to reasonable length
                return line[:80] + "..." if len(line) > 80 else line
    return None


def generate_content_hash(content: str) -> str:
    """Generate a short hash of the design content for uniqueness verification."""
    # Remove existing stamps before hashing
    clean = re.sub(r"<!--\s*DESIGN STAMP.*?-->", "", content, flags=re.DOTALL)
    clean = re.sub(r"<!--\s*updated.*?-->", "", clean, flags=re.DOTALL)
    return hashlib.sha256(clean.encode()).hexdigest()[:12]


def validate_seed(seed: str, known_seeds: List[Dict[str, Any]]) -> bool:
    """Check if seed matches or is similar to known styles."""
    if not known_seeds:
        return True  # Can't validate without known seeds

    known_aesthetics = [s.get("aesthetic", "").lower() for s in known_seeds]
    seed_lower = seed.lower().replace("-", " ")

    # Check for partial matches
    for aesthetic in known_aesthetics:
        if aesthetic in seed_lower or seed_lower in aesthetic:
            return True

    # Accept any well-formatted seed (including composite styles)
    if re.match(r"^[a-z0-9-:,\s]+$", seed.lower()):
        return True

    return False


def format_stamp(
    domain: Optional[str],
    seed: str,
    aesthetic: Optional[str],
    content_hash: str,
    timestamp: str,
) -> str:
    """Format the metadata stamp."""
    lines = [
        "",
        "<!-- DESIGN STAMP",
        f"  timestamp: {timestamp}",
    ]

    if domain:
        lines.append(f"  domain: {domain}")

    lines.append(f"  seed: {seed}")

    if aesthetic:
        lines.append(f"  aesthetic: {aesthetic}")

    lines.append(f"  content_hash: {content_hash}")
    lines.append("-->")
    lines.append("")

    return "\n".join(lines)


def remove_old_stamps(content: str) -> str:
    """Remove old stamps from content."""
    # Remove old simple stamp format
    content = re.sub(r"\n*<!--\s*updated\s+[^>]+-->\s*\n*", "\n", content)
    # Remove new DESIGN STAMP format
    content = re.sub(r"\n*<!--\s*DESIGN STAMP.*?-->\s*\n*", "\n", content, flags=re.DOTALL)
    return content.rstrip()


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Stamp Design.md with uniqueness metadata",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  %(prog)s sites/example.com-v1/DESIGN.md --seed "glassmorphism-minimal"
  %(prog)s sites/example.com-v1/DESIGN.md --auto  # Extract seed from content
  %(prog)s sites/example.com-v1/DESIGN.md --validate  # Check without writing
        """
    )
    parser.add_argument("path", help="Path to Design.md")
    parser.add_argument("--seed", default="", help="Uniqueness seed (style identifier)")
    parser.add_argument("--auto", action="store_true", help="Auto-extract seed from content")
    parser.add_argument("--validate", action="store_true", help="Validate only, don't write")
    parser.add_argument("--force", action="store_true", help="Force update even if already stamped")
    args = parser.parse_args()

    path = pathlib.Path(args.path).resolve()
    script_dir = pathlib.Path(__file__).parent.resolve()

    if not path.exists():
        print(f"ERROR:design_not_found:{path}")
        return 2

    content = path.read_text(encoding="utf-8")
    known_seeds = load_known_seeds(script_dir)

    # Extract metadata
    domain = extract_domain_from_path(path)
    timestamp = datetime.datetime.now().isoformat(timespec="seconds")

    # Determine seed
    seed = args.seed
    if args.auto or not seed:
        extracted = extract_seed_from_content(content)
        if extracted:
            seed = extracted
            print(f"Auto-extracted seed: {seed}")
        elif not seed:
            print("WARNING: No seed provided and couldn't auto-extract", file=sys.stderr)
            seed = "unspecified"

    # Validate seed format
    seed = seed.lower().strip()
    if not validate_seed(seed, known_seeds):
        print(f"WARNING: Seed '{seed}' doesn't match known styles", file=sys.stderr)

    # Extract aesthetic description
    aesthetic = extract_aesthetic_from_content(content)

    # Generate content hash
    clean_content = remove_old_stamps(content)
    content_hash = generate_content_hash(clean_content)

    # Check if already stamped with same hash
    if not args.force and f"content_hash: {content_hash}" in content:
        print(f"Already stamped with same content hash: {content_hash}")
        return 0

    if args.validate:
        print("Validation results:")
        print(f"  Domain: {domain or 'unknown'}")
        print(f"  Seed: {seed}")
        print(f"  Aesthetic: {aesthetic or 'not found'}")
        print(f"  Content hash: {content_hash}")
        return 0

    # Format and append stamp
    stamp = format_stamp(domain, seed, aesthetic, content_hash, timestamp)
    new_content = clean_content + stamp

    path.write_text(new_content, encoding="utf-8")

    print(f"Stamped: {path}")
    print(f"  Domain: {domain or 'unknown'}")
    print(f"  Seed: {seed}")
    print(f"  Hash: {content_hash}")

    return 0


if __name__ == "__main__":
    raise SystemExit(main())
