from __future__ import annotations

from pathlib import Path
from typing import List, Dict, Optional
from .llm import refine_component
from string import Template


TEMPLATE_TSX = Template("""// Auto-generated by UFR-DS (prototype)
import React from 'react';

export type { ReactNode } from 'react';

export interface ${name}Props {
  variant?: ${variant_union};
  ${prop_fields}
  children?: React.ReactNode;
}

export function ${name}({ variant = ${variant_default}, ${prop_params} children }: ${name}Props) {
  // TODO: Replace with real implementation mapped from your design system
  const className = 'ufr-${kebab}' + (variant ? ' variant-' + variant : '');
  return (
    <div className={className}>
      {/* Render children and map props into structure as needed */}
      {children}
    </div>
  );
}
""")


def kebab_case(s: str) -> str:
    out = []
    for c in s:
        if c.isupper():
            if out:
                out.append('-')
            out.append(c.lower())
        else:
            out.append(c)
    return ''.join(out)


def write_component(out_dir: Path, name: str, variant_values: List[str], props: List[str], *, llm_provider: Optional[str] = None) -> Path:
    out_dir.mkdir(parents=True, exist_ok=True)
    file = out_dir / f"{name}.tsx"
    if not variant_values:
        variant_values = ["default"]
    # sanitize and dedupe
    variant_values = [str(v) for v in variant_values if v]
    variant_union = " | ".join(sorted({f"'{v}'" for v in variant_values})) or "'default'"
    variant_default = f"'{variant_values[0]}'"
    # Prepare props
    prop_fields = "\n  ".join(f"{p}?: any;" for p in props)
    if prop_fields:
        prop_fields = prop_fields + "\n  "
    prop_params = ", ".join(props)
    if prop_params:
        prop_params = prop_params + ", "
    content = TEMPLATE_TSX.substitute(
        name=name,
        variant_union=variant_union,
        variant_default=variant_default,
        prop_fields=prop_fields,
        prop_params=prop_params,
        kebab=kebab_case(name),
    )
    # Optional LLM refinement
    refined = refine_component(name, variant_values, props, content, provider=llm_provider) if llm_provider else None
    file.write_text(refined or content, encoding="utf-8")
    return file


def generate_from_suggestions(suggestions: List[dict], out_dir: str | Path, *, llm_provider: Optional[str] = None) -> Dict[str, str]:
    out = {}
    out_path = Path(out_dir)
    for s in suggestions:
        name = s.get("family") or "Component"
        variants = list(s.get("suggested_variant_values") or [])
        props = list(s.get("top_props") or [])
        path = write_component(out_path, name, variants, props, llm_provider=llm_provider)
        out[name] = str(path)
    # Write an index.ts for convenience
    if out:
        index = out_path / "index.ts"
        exports = "\n".join([f"export * from './{k}';" for k in out.keys()])
        index.write_text(exports + "\n", encoding='utf-8')
    return out
