"""
Statute scaffold generator for Yuho.

Generates boilerplate .yh files with proper structure for
quick statute creation.
"""

import re
from pathlib import Path
from typing import Optional, List
from dataclasses import dataclass

import click


@dataclass
class ScaffoldConfig:
    """Configuration for scaffold generation."""
    section: str
    title: str
    with_definitions: bool = True
    with_actus_reus: bool = True
    with_mens_rea: bool = True
    with_penalty: bool = True
    with_illustrations: bool = True
    num_definitions: int = 1
    num_illustrations: int = 1
    template: str = "standard"  # standard, minimal, full


def normalize_section(section: str) -> str:
    """
    Normalize section number format.
    
    Examples:
        "299" -> "299"
        "s299" -> "299"
        "S299A" -> "299A"
        "section 299" -> "299"
    """
    # Remove common prefixes
    section = re.sub(r"^(?:s(?:ection)?\s*)", "", section, flags=re.IGNORECASE)
    return section.strip()


def generate_filename(section: str, title: str) -> str:
    """
    Generate a filename from section and title.
    
    Examples:
        ("299", "Culpable Homicide") -> "s299_culpable_homicide.yh"
    """
    # Normalize section
    section = normalize_section(section).lower()
    
    # Convert title to snake_case
    title_snake = re.sub(r"[^\w\s]", "", title.lower())
    title_snake = re.sub(r"\s+", "_", title_snake.strip())
    
    return f"s{section}_{title_snake}.yh"


def generate_standard_scaffold(config: ScaffoldConfig) -> str:
    """Generate standard scaffold with typical structure."""
    lines: List[str] = []
    
    section = normalize_section(config.section)
    
    # Header comment
    lines.append(f"// Statute: Section {section} - {config.title}")
    lines.append(f"// Generated by: yuho generate")
    lines.append("")
    
    # Statute declaration
    lines.append(f'statute "{section}" "{config.title}" {{')
    
    # Definitions
    if config.with_definitions:
        lines.append("")
        lines.append("    definitions {")
        for i in range(config.num_definitions):
            term = f"term_{i + 1}" if config.num_definitions > 1 else "key_term"
            lines.append(f'        "{term}" := "TODO: Define {term}";')
        lines.append("    }")
    
    # Elements
    lines.append("")
    lines.append("    elements {")
    
    if config.with_actus_reus:
        lines.append('        actus_reus act := "TODO: Describe the physical act or conduct";')
    
    if config.with_mens_rea:
        lines.append('        mens_rea intent := "TODO: Describe the required mental state";')
    
    lines.append("    }")
    
    # Penalty
    if config.with_penalty:
        lines.append("")
        lines.append("    penalty {")
        lines.append("        imprisonment := 10Y;  // TODO: Set appropriate term")
        lines.append("        fine := SGD 10000;    // TODO: Set appropriate fine")
        lines.append("    }")
    
    # Illustrations
    if config.with_illustrations:
        lines.append("")
        lines.append("    illustrations {")
        for i in range(config.num_illustrations):
            label = chr(ord('a') + i)
            lines.append(f'        ({label}) "TODO: Provide example {label} illustrating application";')
        lines.append("    }")
    
    lines.append("}")
    
    return "\n".join(lines)


def generate_minimal_scaffold(config: ScaffoldConfig) -> str:
    """Generate minimal scaffold with only required sections."""
    lines: List[str] = []
    
    section = normalize_section(config.section)
    
    lines.append(f'statute "{section}" "{config.title}" {{')
    lines.append("")
    lines.append("    elements {")
    lines.append('        actus_reus act := "TODO: Define";')
    lines.append("    }")
    lines.append("")
    lines.append("}")
    
    return "\n".join(lines)


def generate_full_scaffold(config: ScaffoldConfig) -> str:
    """Generate full scaffold with all possible sections."""
    lines: List[str] = []
    
    section = normalize_section(config.section)
    
    # Header
    lines.append("// ============================================================================")
    lines.append(f"// SECTION {section}: {config.title.upper()}")
    lines.append("// ============================================================================")
    lines.append("//")
    lines.append("// Description: TODO: Provide overview of this statute")
    lines.append("// Source: TODO: Reference source legislation")
    lines.append("// Effective: TODO: Date")
    lines.append("//")
    lines.append("")
    
    lines.append(f'statute "{section}" "{config.title}" {{')
    
    # Definitions
    lines.append("")
    lines.append("    // Define key legal terms used in this statute")
    lines.append("    definitions {")
    lines.append('        "perpetrator" := "The person who commits the act";')
    lines.append('        "victim" := "The person against whom the act is committed";')
    lines.append('        "property" := "Any movable or immovable asset";')
    lines.append("    }")
    
    # Elements
    lines.append("")
    lines.append("    // Elements that must be proven for conviction")
    lines.append("    elements {")
    lines.append('        actus_reus physical_act := "TODO: The physical conduct or act";')
    lines.append('        actus_reus result := "TODO: The result or consequence (if any)";')
    lines.append('        mens_rea intention := "TODO: The required mental state";')
    lines.append('        circumstance context := "TODO: Circumstances that must exist";')
    lines.append("    }")
    
    # Exceptions / Defenses
    lines.append("")
    lines.append("    // Exceptions or defenses to liability")
    lines.append("    // exceptions {")
    lines.append("    //     defense := TODO;")
    lines.append("    // }")
    
    # Penalty
    lines.append("")
    lines.append("    // Punishment upon conviction")
    lines.append("    penalty {")
    lines.append("        imprisonment := 2Y to 10Y;")
    lines.append("        fine := SGD 5000 to SGD 50000;")
    lines.append('        supplementary := "Or both imprisonment and fine";')
    lines.append("    }")
    
    # Illustrations
    lines.append("")
    lines.append("    // Examples illustrating application of this statute")
    lines.append("    illustrations {")
    lines.append('        (a) "Example showing when the offense IS committed: TODO";')
    lines.append('        (b) "Example showing when the offense is NOT committed: TODO";')
    lines.append('        (c) "Borderline case for consideration: TODO";')
    lines.append("    }")
    
    # Cross-references
    lines.append("")
    lines.append("    // Related statutes")
    lines.append("    // references {")
    lines.append("    //     see \"300\";  // Related offense")
    lines.append("    //     see \"301\";  // Enhanced penalty provision")
    lines.append("    // }")
    
    lines.append("}")
    
    return "\n".join(lines)


def generate_scaffold(config: ScaffoldConfig) -> str:
    """
    Generate scaffold based on template type.
    
    Args:
        config: Scaffold configuration
        
    Returns:
        Generated Yuho source code
    """
    generators = {
        "standard": generate_standard_scaffold,
        "minimal": generate_minimal_scaffold,
        "full": generate_full_scaffold,
    }
    
    generator = generators.get(config.template, generate_standard_scaffold)
    return generator(config)


def run_generate(
    section: str,
    title: str,
    output: Optional[str] = None,
    template: str = "standard",
    no_definitions: bool = False,
    no_penalty: bool = False,
    no_illustrations: bool = False,
    force: bool = False,
    verbose: bool = False,
    color: bool = True,
) -> None:
    """
    Run scaffold generator.
    
    Args:
        section: Section number (e.g., "299", "s300A")
        title: Statute title
        output: Output file path (None = auto-generate)
        template: Template type (standard, minimal, full)
        no_definitions: Skip definitions block
        no_penalty: Skip penalty block
        no_illustrations: Skip illustrations block
        force: Overwrite existing file
        verbose: Verbose output
        color: Use colors
    """
    # Validate template
    valid_templates = ["standard", "minimal", "full"]
    if template not in valid_templates:
        click.echo(f"Error: Unknown template '{template}'", err=True)
        click.echo(f"Available: {', '.join(valid_templates)}", err=True)
        raise SystemExit(1)
    
    # Build config
    config = ScaffoldConfig(
        section=section,
        title=title,
        template=template,
        with_definitions=not no_definitions,
        with_penalty=not no_penalty,
        with_illustrations=not no_illustrations,
    )
    
    # Full template ignores individual flags
    if template == "full":
        config.with_definitions = True
        config.with_penalty = True
        config.with_illustrations = True
    
    # Generate
    code = generate_scaffold(config)
    
    # Determine output path
    if output:
        path = Path(output)
    else:
        filename = generate_filename(section, title)
        path = Path(filename)
    
    # Check existing
    if path.exists() and not force:
        click.echo(f"Error: File already exists: {path}", err=True)
        click.echo("Use --force to overwrite", err=True)
        raise SystemExit(1)
    
    # Write
    path.write_text(code + "\n")
    
    # Output
    if verbose:
        click.echo(click.style("Generated scaffold:", fg="cyan", bold=True))
        click.echo("")
        click.echo(code)
        click.echo("")
    
    click.echo(click.style(f"✓ Created: {path}", fg="green"))
    
    # Show tips
    click.echo("")
    click.echo(click.style("Next steps:", fg="yellow"))
    click.echo(f"  1. Edit {path} to fill in TODO sections")
    click.echo(f"  2. Run: yuho check {path}")
    click.echo(f"  3. Run: yuho transpile {path} --target english")
