"""Tool commands: cost, quality, compare, profile, extractors, etc."""

import sys
from pathlib import Path

import click
from rich.panel import Panel
from rich.table import Table

from datarecipe.analyzer import DatasetAnalyzer
from datarecipe.cli._helpers import (
    console,
)


@click.command()
@click.option("--output", "-o", type=click.Path(), help="Output YAML file path")
def create(output: str):
    """Interactively create a dataset recipe.

    This command guides you through creating a recipe file step by step.
    """
    from rich.prompt import Confirm, FloatPrompt, IntPrompt, Prompt

    console.print("\n[bold cyan]📝 创建数据集配方 / Create Dataset Recipe[/bold cyan]\n")

    # Basic info
    name = Prompt.ask("数据集名称 / Dataset name")
    version = Prompt.ask("版本 / Version", default="1.0")

    # Source
    console.print("\n[bold]数据来源 / Data Source[/bold]")
    source_type = Prompt.ask(
        "来源类型 / Source type", choices=["huggingface", "github", "web", "local"], default="local"
    )
    source_id = Prompt.ask("来源标识 / Source ID (URL or ID)", default="")

    # Generation
    console.print("\n[bold]生成方式 / Generation Method[/bold]")
    synthetic_ratio = FloatPrompt.ask("合成数据比例 / Synthetic ratio (0.0-1.0)", default=0.0)
    human_ratio = 1.0 - synthetic_ratio

    teacher_models = []
    if synthetic_ratio > 0:
        models_input = Prompt.ask(
            "教师模型 / Teacher models (逗号分隔 / comma-separated)", default=""
        )
        if models_input:
            teacher_models = [m.strip() for m in models_input.split(",")]

    # Cost
    console.print("\n[bold]成本估算 / Cost Estimation[/bold]")
    has_cost = Confirm.ask("是否添加成本信息? / Add cost info?", default=False)
    cost_total = None
    cost_confidence = "low"
    if has_cost:
        cost_total = FloatPrompt.ask("预估总成本 (USD) / Estimated total cost", default=0)
        cost_confidence = Prompt.ask(
            "置信度 / Confidence", choices=["low", "medium", "high"], default="low"
        )

    # Reproducibility
    console.print("\n[bold]可复现性 / Reproducibility[/bold]")
    repro_score = IntPrompt.ask("可复现性评分 (1-10) / Score", default=5)

    available_input = Prompt.ask(
        "已提供的信息 / Available info (逗号分隔 / comma-separated)", default="description"
    )
    available = [a.strip() for a in available_input.split(",") if a.strip()]

    missing_input = Prompt.ask(
        "缺失的信息 / Missing info (逗号分隔 / comma-separated)",
        default="exact_prompts,filtering_criteria",
    )
    missing = [m.strip() for m in missing_input.split(",") if m.strip()]

    # Metadata
    console.print("\n[bold]元数据 / Metadata[/bold]")
    num_examples = IntPrompt.ask("样本数量 / Number of examples", default=0)
    languages_input = Prompt.ask("语言 / Languages (逗号分隔)", default="en")
    languages = [l.strip() for l in languages_input.split(",") if l.strip()]
    license_str = Prompt.ask("许可证 / License", default="unknown")

    tags_input = Prompt.ask("标签 / Tags (逗号分隔)", default="")
    tags = [t.strip() for t in tags_input.split(",") if t.strip()]

    # Build YAML content
    yaml_content = f"""# Recipe for {name}
# Generated by DataRecipe

name: {name}
version: "{version}"

source:
  type: {source_type}
  id: {source_id or name}

generation:
  synthetic_ratio: {synthetic_ratio}
  human_ratio: {human_ratio}
  teacher_models: {teacher_models}
  methods:"""

    if teacher_models:
        for model in teacher_models:
            yaml_content += f"""
    - type: distillation
      teacher_model: {model}"""

    if human_ratio > 0:
        yaml_content += """
    - type: human_annotation"""

    yaml_content += f"""

cost:
  estimated_total_usd: {cost_total if cost_total else "null"}
  confidence: {cost_confidence}

reproducibility:
  score: {repro_score}
  available: {available}
  missing: {missing}

metadata:
  num_examples: {num_examples if num_examples else "null"}
  languages: {languages}
  license: {license_str}
  tags: {tags}
"""

    # Output
    if output:
        output_path = Path(output)
        output_path.parent.mkdir(parents=True, exist_ok=True)
        output_path.write_text(yaml_content, encoding="utf-8")
        console.print(f"\n[green]✓ 配方已保存到 / Recipe saved to:[/green] {output}")
    else:
        # Default output path
        safe_name = name.replace("/", "-").replace(" ", "-").lower()
        output_path = Path(f"recipes/{safe_name}.yaml")
        output_path.parent.mkdir(parents=True, exist_ok=True)
        output_path.write_text(yaml_content, encoding="utf-8")
        console.print(f"\n[green]✓ 配方已保存到 / Recipe saved to:[/green] {output_path}")

    # Show preview
    console.print("\n[bold]预览 / Preview:[/bold]")
    console.print(yaml_content)


@click.command()
@click.argument("dataset_id")
@click.option("--model", "-m", default="gpt-4o", help="LLM model for cost estimation")
@click.option("--examples", "-n", type=int, help="Target number of examples")
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
def cost(dataset_id: str, model: str, examples: int, as_json: bool):
    """Calculate production cost estimate for a dataset.

    DATASET_ID is the identifier of the dataset to analyze.
    """
    from datarecipe.cost_calculator import CostCalculator

    analyzer = DatasetAnalyzer()
    calculator = CostCalculator()

    with console.status(f"[cyan]Analyzing {dataset_id}...[/cyan]"):
        try:
            recipe = analyzer.analyze(dataset_id)
        except Exception as e:
            console.print(f"[red]Error:[/red] {e}")
            sys.exit(1)

    target_size = examples or recipe.num_examples or 10000

    with console.status("[cyan]Calculating costs...[/cyan]"):
        cost_breakdown = calculator.estimate_from_recipe(recipe, target_size, model)

    if as_json:
        import json

        console.print(json.dumps(cost_breakdown.to_dict(), indent=2))
    else:
        console.print(f"\n[bold cyan]Cost Estimate for {dataset_id}[/bold cyan]")
        console.print(f"Target size: {target_size:,} examples")
        console.print(f"Model: {model}")
        console.print("")

        table = Table(title="Cost Breakdown")
        table.add_column("Category", style="cyan")
        table.add_column("Low", justify="right")
        table.add_column("Expected", justify="right", style="green")
        table.add_column("High", justify="right")

        table.add_row(
            "API Calls",
            f"${cost_breakdown.api_cost.low:,.0f}",
            f"${cost_breakdown.api_cost.expected:,.0f}",
            f"${cost_breakdown.api_cost.high:,.0f}",
        )
        table.add_row(
            "Human Annotation",
            f"${cost_breakdown.human_annotation_cost.low:,.0f}",
            f"${cost_breakdown.human_annotation_cost.expected:,.0f}",
            f"${cost_breakdown.human_annotation_cost.high:,.0f}",
        )
        table.add_row(
            "Compute",
            f"${cost_breakdown.compute_cost.low:,.0f}",
            f"${cost_breakdown.compute_cost.expected:,.0f}",
            f"${cost_breakdown.compute_cost.high:,.0f}",
        )
        table.add_row(
            "[bold]Total[/bold]",
            f"[bold]${cost_breakdown.total.low:,.0f}[/bold]",
            f"[bold green]${cost_breakdown.total.expected:,.0f}[/bold green]",
            f"[bold]${cost_breakdown.total.high:,.0f}[/bold]",
        )

        console.print(table)

        if cost_breakdown.assumptions:
            console.print("\n[bold]Assumptions:[/bold]")
            for assumption in cost_breakdown.assumptions:
                console.print(f"  - {assumption}")


@click.command()
@click.argument("dataset_id")
@click.option("--sample-size", "-n", type=int, default=1000, help="Number of examples to sample")
@click.option("--text-field", "-f", default="text", help="Field containing text to analyze")
@click.option("--detect-ai", is_flag=True, help="Run AI content detection")
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
def quality(dataset_id: str, sample_size: int, text_field: str, detect_ai: bool, as_json: bool):
    """Analyze quality metrics for a dataset.

    DATASET_ID is the identifier of the dataset to analyze.
    """
    from datarecipe.quality_metrics import QualityAnalyzer

    quality_analyzer = QualityAnalyzer()

    with console.status(f"[cyan]Analyzing quality of {dataset_id}...[/cyan]"):
        try:
            report = quality_analyzer.analyze_from_huggingface(
                dataset_id,
                text_field=text_field,
                sample_size=sample_size,
                detect_ai=detect_ai,
            )
        except Exception as e:
            console.print(f"[red]Error:[/red] {e}")
            sys.exit(1)

    if as_json:
        import json

        console.print(json.dumps(report.to_dict(), indent=2))
    else:
        console.print(f"\n[bold cyan]Quality Report for {dataset_id}[/bold cyan]")
        console.print(f"Sample size: {report.sample_size:,}")
        console.print("")

        # Overall score
        score = report.overall_score
        score_bar = "[" + "#" * int(score / 10) + "-" * (10 - int(score / 10)) + "]"
        console.print(f"[bold]Overall Score: {score:.0f}/100 {score_bar}[/bold]")
        console.print("")

        # Metrics tables
        table = Table(title="Diversity Metrics")
        table.add_column("Metric", style="cyan")
        table.add_column("Value", justify="right")
        table.add_row("Unique Token Ratio", f"{report.diversity.unique_token_ratio:.4f}")
        table.add_row("Vocabulary Size", f"{report.diversity.vocabulary_size:,}")
        table.add_row("Semantic Diversity", f"{report.diversity.semantic_diversity:.4f}")
        console.print(table)
        console.print("")

        table = Table(title="Consistency Metrics")
        table.add_column("Metric", style="cyan")
        table.add_column("Value", justify="right")
        table.add_row("Format Consistency", f"{report.consistency.format_consistency:.4f}")
        table.add_row("Structure Score", f"{report.consistency.structure_score:.4f}")
        table.add_row("Field Completeness", f"{report.consistency.field_completeness:.4f}")
        console.print(table)
        console.print("")

        table = Table(title="Complexity Metrics")
        table.add_column("Metric", style="cyan")
        table.add_column("Value", justify="right")
        table.add_row("Avg Length", f"{report.complexity.avg_length:.0f} chars")
        table.add_row("Avg Tokens", f"{report.complexity.avg_tokens:.0f}")
        table.add_row("Vocabulary Richness", f"{report.complexity.vocabulary_richness:.4f}")
        table.add_row("Readability Score", f"{report.complexity.readability_score:.0f}")
        console.print(table)

        if detect_ai and report.ai_detection:
            console.print("")
            table = Table(title="AI Detection")
            table.add_column("Metric", style="cyan")
            table.add_column("Value", justify="right")
            table.add_row("AI Probability", f"{report.ai_detection.ai_probability:.2%}")
            table.add_row("Confidence", f"{report.ai_detection.confidence:.2%}")
            if report.ai_detection.indicators:
                table.add_row("Indicators", ", ".join(report.ai_detection.indicators[:3]))
            console.print(table)

        if report.recommendations:
            console.print("\n[bold]Recommendations:[/bold]")
            for rec in report.recommendations:
                console.print(f"  - {rec}")

        if report.warnings:
            console.print("\n[yellow]Warnings:[/yellow]")
            for warning in report.warnings:
                console.print(f"  - {warning}")


@click.command()
@click.argument("dataset_ids", nargs=-1)
@click.option("--file", "-f", type=click.Path(exists=True), help="File with dataset IDs")
@click.option("--parallel", "-p", type=int, default=4, help="Number of parallel workers")
@click.option("--output", "-o", type=click.Path(), help="Output directory for results")
@click.option(
    "--format",
    "fmt",
    type=click.Choice(["yaml", "json", "markdown"]),
    default="yaml",
    help="Output format",
)
def batch(dataset_ids: tuple, file: str, parallel: int, output: str, fmt: str):
    """Analyze multiple datasets in parallel.

    DATASET_IDS are the identifiers of datasets to analyze.
    Use -f to read dataset IDs from a file.
    """
    from datarecipe.batch_analyzer import BatchAnalyzer

    # Collect dataset IDs
    ids = list(dataset_ids)
    if file:
        batch_analyzer = BatchAnalyzer(max_workers=parallel)
        result = batch_analyzer.analyze_from_file(file)
    elif ids:
        batch_analyzer = BatchAnalyzer(max_workers=parallel)

        def progress_callback(dataset_id, completed, total):
            console.print(f"  [{completed}/{total}] Analyzed: {dataset_id}")

        batch_analyzer.progress_callback = progress_callback
        result = batch_analyzer.analyze_batch(ids)
    else:
        console.print("[red]Error:[/red] Provide dataset IDs or use -f to specify a file")
        sys.exit(1)

    console.print("\n[bold cyan]Batch Analysis Complete[/bold cyan]")
    console.print(f"  Total: {len(result.results)}")
    console.print(f"  [green]Successful: {result.successful}[/green]")
    console.print(f"  [red]Failed: {result.failed}[/red]")
    console.print(f"  Duration: {result.total_duration_seconds:.1f}s")

    if result.failed > 0:
        console.print("\n[yellow]Failed datasets:[/yellow]")
        for r in result.get_failed():
            console.print(f"  - {r.dataset_id}: {r.error}")

    if output:
        created = batch_analyzer.export_results(result, output, fmt)
        console.print(f"\n[green]Results exported to {output}[/green]")
        console.print(f"  Created {len(created)} files")


@click.command()
@click.argument("dataset_ids", nargs=-1, required=True)
@click.option(
    "--format",
    "fmt",
    type=click.Choice(["table", "markdown"]),
    default="table",
    help="Output format",
)
@click.option("--include-quality", is_flag=True, help="Include quality analysis (slower)")
@click.option("--output", "-o", type=click.Path(), help="Output file")
def compare(dataset_ids: tuple, fmt: str, include_quality: bool, output: str):
    """Compare multiple datasets side by side.

    DATASET_IDS are 2 or more dataset identifiers to compare.
    """
    from datarecipe.comparator import DatasetComparator

    if len(dataset_ids) < 2:
        console.print("[red]Error:[/red] Please provide at least 2 datasets to compare")
        sys.exit(1)

    comparator = DatasetComparator(include_quality=include_quality)

    with console.status(f"[cyan]Comparing {len(dataset_ids)} datasets...[/cyan]"):
        try:
            report = comparator.compare_by_ids(list(dataset_ids))
        except Exception as e:
            console.print(f"[red]Error:[/red] {e}")
            sys.exit(1)

    if fmt == "markdown":
        content = report.to_markdown()
    else:
        content = report.to_table()

    if output:
        output_path = Path(output)
        output_path.parent.mkdir(parents=True, exist_ok=True)
        output_path.write_text(content, encoding="utf-8")
        console.print(f"[green]Report saved to {output}[/green]")
    else:
        print(content)

    # Show recommendations
    if report.recommendations and fmt == "table":
        console.print("\n[bold cyan]Recommendations:[/bold cyan]")
        for rec in report.recommendations:
            console.print(f"  - {rec}")


@click.command()
@click.argument("dataset_id")
@click.option("--output", "-o", type=click.Path(), help="Output file for profile")
@click.option(
    "--region",
    "-r",
    default="china",
    help="Region for cost estimation (china, us, europe, india, sea)",
)
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
@click.option("--markdown", "--md", "as_markdown", is_flag=True, help="Output as Markdown")
def profile(dataset_id: str, output: str, region: str, as_json: bool, as_markdown: bool):
    """Generate annotator profile for a dataset.

    Analyzes a dataset and generates requirements for annotation team,
    including skills, experience level, education, and workload estimation.

    DATASET_ID is the identifier of the dataset to analyze.
    """
    from datarecipe.profiler import AnnotatorProfiler, profile_to_markdown

    analyzer = DatasetAnalyzer()
    profiler = AnnotatorProfiler()

    with console.status(f"[cyan]Analyzing {dataset_id}...[/cyan]"):
        try:
            recipe = analyzer.analyze(dataset_id)
        except Exception as e:
            console.print(f"[red]Error:[/red] {e}")
            sys.exit(1)

    with console.status("[cyan]Generating annotator profile...[/cyan]"):
        annotator_profile = profiler.generate_profile(recipe, region=region)

    if as_json:
        import json

        console.print(json.dumps(annotator_profile.to_dict(), indent=2))
    elif as_markdown:
        md_content = profile_to_markdown(annotator_profile, recipe.name)
        print(md_content)
    else:
        # Display as formatted table
        console.print(f"\n[bold cyan]Annotator Profile for {dataset_id}[/bold cyan]")
        console.print("")

        # Skills table
        table = Table(title="Required Skills")
        table.add_column("Skill", style="cyan")
        table.add_column("Level", justify="center")
        table.add_column("Priority", justify="center")

        for skill in annotator_profile.skill_requirements:
            priority = "required" if skill.required else "preferred"
            priority_color = {"required": "red", "preferred": "yellow"}.get(priority, "white")
            table.add_row(
                skill.name, skill.level, f"[{priority_color}]{priority}[/{priority_color}]"
            )
        console.print(table)
        console.print("")

        # Requirements summary
        console.print("[bold]Requirements:[/bold]")
        console.print(f"  Experience Level: {annotator_profile.experience_level.value}")
        console.print(f"  Education: {annotator_profile.education_level.value}")
        if annotator_profile.domain_knowledge:
            console.print(f"  Domain Expertise: {', '.join(annotator_profile.domain_knowledge)}")
        if annotator_profile.language_requirements:
            console.print(f"  Languages: {', '.join(annotator_profile.language_requirements)}")
        console.print("")

        # Workload estimation
        hourly_rate = (
            annotator_profile.hourly_rate_range.get("min", 15)
            + annotator_profile.hourly_rate_range.get("max", 45)
        ) / 2
        estimated_labor_cost = annotator_profile.estimated_person_days * 8 * hourly_rate
        console.print("[bold]Workload Estimation:[/bold]")
        console.print(f"  Team Size: {annotator_profile.team_size} annotators")
        console.print(f"  Person-Days: {annotator_profile.estimated_person_days:.0f}")
        console.print(f"  Hours per Example: {annotator_profile.estimated_hours_per_example:.2f}")
        console.print(f"  Hourly Rate: ${hourly_rate:.2f}")
        console.print(f"  Estimated Labor Cost: ${estimated_labor_cost:,.0f}")

    # Export if requested
    if output:
        output_path = Path(output)
        output_path.parent.mkdir(parents=True, exist_ok=True)
        if output.endswith(".md"):
            md_content = profile_to_markdown(annotator_profile, recipe.name)
            output_path.write_text(md_content, encoding="utf-8")
            console.print(f"\n[green]Profile exported to:[/green] {output}")
        elif output.endswith(".json"):
            import json

            output_path.write_text(
                json.dumps(annotator_profile.to_dict(), indent=2), encoding="utf-8"
            )
            console.print(f"\n[green]Profile exported to:[/green] {output}")
        else:
            # Default to YAML
            import yaml

            output_path.write_text(
                yaml.dump(
                    annotator_profile.to_dict(), allow_unicode=True, default_flow_style=False
                ),
                encoding="utf-8",
            )
            console.print(f"\n[green]Profile exported to:[/green] {output}")


@click.command()
@click.argument("dataset_id")
@click.option(
    "--output",
    "-o",
    type=click.Path(),
    help="Output directory (default: ./projects/<dataset_name>)",
)
@click.option(
    "--provider", "-p", default="local", help="Deployment provider (local, judgeguild, etc.)"
)
@click.option("--region", "-r", default="china", help="Region for cost estimation")
@click.option("--submit", is_flag=True, help="Submit to provider after generating config")
def deploy(dataset_id: str, output: str, provider: str, region: str, submit: bool):
    """Generate production deployment for a dataset.

    Creates a complete project structure with annotation guidelines,
    quality rules, acceptance criteria, and timeline for data production.

    DATASET_ID is the identifier of the dataset to analyze.

    If --output is not specified, files are saved to ./projects/<dataset_name>/10_生产部署/
    """
    from datarecipe.deployer import ProductionDeployer
    from datarecipe.profiler import AnnotatorProfiler
    from datarecipe.schema import DataRecipe

    # 默认输出目录
    if not output:
        from datarecipe.core.project_layout import safe_name as _safe_name

        output = f"./projects/{_safe_name(dataset_id)}"
        console.print(f"[dim]Output directory: {output}[/dim]")

    analyzer = DatasetAnalyzer()
    deployer = ProductionDeployer()
    profiler = AnnotatorProfiler()

    with console.status(f"[cyan]Analyzing {dataset_id}...[/cyan]"):
        try:
            recipe = analyzer.analyze(dataset_id)
        except Exception as e:
            console.print(f"[red]Error:[/red] {e}")
            sys.exit(1)

    with console.status("[cyan]Generating annotator profile...[/cyan]"):
        profile = profiler.generate_profile(recipe, region=region)

    # Convert Recipe to DataRecipe
    data_recipe = DataRecipe(
        name=recipe.name,
        version=recipe.version,
        source_type=recipe.source_type,
        source_id=recipe.source_id,
        num_examples=recipe.num_examples,
        languages=recipe.languages or [],
        license=recipe.license,
        description=recipe.description,
        generation_type=recipe.generation_type,
        synthetic_ratio=recipe.synthetic_ratio,
        human_ratio=recipe.human_ratio,
        generation_methods=recipe.generation_methods or [],
        teacher_models=recipe.teacher_models or [],
        tags=recipe.tags or [],
    )

    with console.status("[cyan]Generating production config...[/cyan]"):
        config = deployer.generate_config(data_recipe, profile=profile)

    # Deploy to provider
    submit_action = submit or provider == "local"
    status_msg = (
        f"[cyan]Deploying to {provider}...[/cyan]"
        if submit_action
        else f"[cyan]Generating deployment package for {provider} (no auto submission)...[/cyan]"
    )
    with console.status(status_msg):
        result = deployer.deploy(
            data_recipe,
            output,
            provider=provider,
            config=config,
            profile=profile,
            submit=submit,
        )

    if result.success:
        console.print("\n[bold green]Deployment successful![/bold green]")
        if result.project_handle:
            console.print(f"  Project ID: {result.project_handle.project_id}")
        console.print(f"  Output: {output}")
        if result.details:
            console.print(f"  Details: {result.details}")

        # Show created files
        output_path = Path(output)
        if output_path.exists():
            files = list(output_path.rglob("*"))
            files = [f for f in files if f.is_file()]
            console.print(f"\n[bold]Created files ({len(files)}):[/bold]")
            for f in files[:10]:
                console.print(f"  - {f.relative_to(output_path)}")
            if len(files) > 10:
                console.print(f"  ... and {len(files) - 10} more")

        console.print("\n[bold cyan]Next steps:[/bold cyan]")
        console.print(f"  1. cd {output}")
        console.print("  2. Review annotation_guide.md")
        console.print("  3. Review quality_rules.yaml")
        console.print("  4. See README.md for detailed instructions")
        if provider != "local" and not submit:
            console.print(
                "  5. 使用 provider 平台手动提交项目 (本次未自动提交，需确认配置后再执行)"
            )
    else:
        console.print(f"\n[red]Deployment failed:[/red] {result.error}")
        sys.exit(1)


@click.group()
def providers():
    """Manage deployment providers."""
    pass


@providers.command("list")
def providers_list():
    """List available deployment providers."""
    from datarecipe.providers import list_providers

    provider_list = list_providers()

    table = Table(title="Available Providers")
    table.add_column("Name", style="cyan")
    table.add_column("Description")

    for p in provider_list:
        table.add_row(p["name"], p["description"])

    console.print(table)

    console.print(
        "\n[dim]Install additional providers with: pip install datarecipe-<provider>[/dim]"
    )


@click.command()
@click.argument("dataset_id")
@click.option(
    "--output", "-o", type=click.Path(), required=True, help="Output directory for project"
)
@click.option("--target-size", "-n", type=int, help="Target number of examples")
@click.option(
    "--format",
    "fmt",
    type=click.Choice(["huggingface", "jsonl", "parquet"]),
    default="huggingface",
    help="Output format",
)
def workflow(dataset_id: str, output: str, target_size: int, fmt: str):
    """Generate a production workflow for reproducing a dataset.

    Creates a complete project structure with scripts, configuration,
    and documentation for producing a dataset similar to DATASET_ID.
    """
    from datarecipe.workflow import WorkflowGenerator

    analyzer = DatasetAnalyzer()
    generator = WorkflowGenerator()

    with console.status(f"[cyan]Analyzing {dataset_id}...[/cyan]"):
        try:
            recipe = analyzer.analyze(dataset_id)
        except Exception as e:
            console.print(f"[red]Error:[/red] {e}")
            sys.exit(1)

    with console.status("[cyan]Generating workflow...[/cyan]"):
        wf = generator.generate(recipe, target_size, fmt)

    # Export project
    created_files = wf.export_project(output)

    console.print("\n[bold green]Workflow generated successfully![/bold green]")
    console.print(f"  Project: {output}")
    console.print(f"  Target size: {wf.target_size:,} examples")
    console.print(f"  Estimated cost: ${wf.estimated_total_cost:,.0f}")
    console.print(f"  Steps: {len(wf.steps)}")

    console.print(f"\n[bold]Created files ({len(created_files)}):[/bold]")
    for f in created_files[:10]:
        console.print(f"  - {f}")
    if len(created_files) > 10:
        console.print(f"  ... and {len(created_files) - 10} more")

    console.print("\n[bold cyan]Next steps:[/bold cyan]")
    console.print(f"  1. cd {output}")
    console.print("  2. pip install -r requirements.txt")
    console.print("  3. cp .env.example .env && edit .env")
    console.print("  4. See README.md for detailed instructions")


# =============================================================================
# New Commands: Pattern Extraction & Generation
# =============================================================================


@click.command("extract-rubrics")
@click.argument("dataset_id")
@click.option("--output", "-o", default=None, help="Output file path (JSON)")
@click.option("--sample-size", "-n", default=1000, help="Number of samples to analyze")
def extract_rubrics(dataset_id: str, output: str, sample_size: int):
    """Extract rubrics/evaluation patterns from a dataset."""
    from datarecipe.extractors import RubricsAnalyzer

    console.print(f"\n[bold]Extracting rubrics patterns from {dataset_id}...[/bold]\n")

    try:
        # Load dataset
        from datasets import load_dataset

        ds = load_dataset(dataset_id, split="train", streaming=True)

        # Collect rubrics
        rubrics = []
        for i, item in enumerate(ds):
            if i >= sample_size:
                break
            # Try common rubrics field names
            for field in ["rubrics", "rubric", "criteria", "evaluation"]:
                if field in item:
                    value = item[field]
                    if isinstance(value, list):
                        rubrics.extend(value)
                    elif isinstance(value, str):
                        rubrics.append(value)

        if not rubrics:
            console.print("[yellow]No rubrics found in dataset.[/yellow]")
            console.print("Tried fields: rubrics, rubric, criteria, evaluation")
            return

        # Analyze
        analyzer = RubricsAnalyzer()
        result = analyzer.analyze(rubrics, task_count=sample_size)

        # Display summary
        console.print(Panel(result.summary(), title="Rubrics Analysis"))
        console.print("\n[bold]Top Structured Templates:[/bold]")
        for entry in result.structured_templates[:5]:
            console.print(
                f"• [{entry.get('category', 'general')}] {entry.get('action') or ''} → {entry.get('target') or ''}"
                + (f" | 条件: {entry.get('condition')}" if entry.get("condition") else "")
            )

        # Export if requested
        if output:
            import json

            if output.endswith(".json"):
                data_path = output
                yaml_path = output.replace(".json", "_templates.yaml")
                md_path = output.replace(".json", "_templates.md")
            else:
                data_path = f"{output}.json"
                yaml_path = f"{output}_templates.yaml"
                md_path = f"{output}_templates.md"

            with open(data_path, "w", encoding="utf-8") as f:
                json.dump(analyzer.to_dict(result), f, indent=2, ensure_ascii=False)
            with open(yaml_path, "w", encoding="utf-8") as f:
                f.write(analyzer.to_yaml_templates(result))
            with open(md_path, "w", encoding="utf-8") as f:
                f.write(analyzer.to_markdown_templates(result))

            console.print(f"\n[green]Exported analysis to {data_path}[/green]")
            console.print(f"[green]Exported templates to {yaml_path} & {md_path}[/green]")

    except Exception as e:
        console.print(f"[red]Error: {e}[/red]")


@click.command("extract-prompts")
@click.argument("dataset_id")
@click.option("--output", "-o", default=None, help="Output file path (JSON)")
@click.option("--sample-size", "-n", default=500, help="Number of samples to analyze")
def extract_prompts(dataset_id: str, output: str, sample_size: int):
    """Extract system prompt templates from a dataset."""
    from datarecipe.extractors import PromptExtractor

    console.print(f"\n[bold]Extracting prompt templates from {dataset_id}...[/bold]\n")

    try:
        from datasets import load_dataset

        ds = load_dataset(dataset_id, split="train", streaming=True)

        # Collect messages with progress
        messages = []
        console.print(f"[dim]Collecting messages from {sample_size} samples...[/dim]")
        for i, item in enumerate(ds):
            if i >= sample_size:
                break
            if i > 0 and i % 100 == 0:
                console.print(
                    f"[dim]  Processed {i}/{sample_size} samples ({len(messages)} messages)[/dim]"
                )
            # Try common message field names
            for field in ["messages", "conversation", "turns"]:
                if field in item and isinstance(item[field], list):
                    messages.extend(item[field])

        if not messages:
            console.print("[yellow]No messages found in dataset.[/yellow]")
            return

        console.print(f"[dim]Collected {len(messages)} messages, deduplicating...[/dim]")

        # Extract
        extractor = PromptExtractor()
        library = extractor.extract(messages)
        console.print("[green]✓ Deduplication complete[/green]")

        # Display summary
        console.print(Panel(library.summary(), title="Prompt Library"))

        # Export if output specified
        if output:
            import json

            data = extractor.to_dict(library)
            with open(output, "w", encoding="utf-8") as f:
                json.dump(data, f, indent=2, ensure_ascii=False)
            console.print(f"\n[green]Exported to {output}[/green]")

    except Exception as e:
        console.print(f"[red]Error: {e}[/red]")


@click.command("detect-strategy")
@click.argument("dataset_id")
@click.option("--output", "-o", default=None, help="Output file path (JSON)")
@click.option("--sample-size", "-n", default=100, help="Number of samples to analyze")
def detect_strategy(dataset_id: str, output: str, sample_size: int):
    """Detect context construction strategy in a dataset."""
    from datarecipe.analyzers import ContextStrategyDetector

    console.print(f"\n[bold]Detecting context strategy in {dataset_id}...[/bold]\n")

    try:
        from datasets import load_dataset

        ds = load_dataset(dataset_id, split="train", streaming=True)

        # Collect contexts
        contexts = []
        for i, item in enumerate(ds):
            if i >= sample_size:
                break
            # Try common context field names
            for field in ["context", "input", "text", "content", "document"]:
                if field in item and isinstance(item[field], str):
                    contexts.append(item[field])
                    break
            # Also check messages
            if "messages" in item and isinstance(item["messages"], list):
                for msg in item["messages"]:
                    if isinstance(msg, dict) and msg.get("role") == "user":
                        contexts.append(msg.get("content", ""))

        if not contexts:
            console.print("[yellow]No contexts found in dataset.[/yellow]")
            return

        # Detect
        detector = ContextStrategyDetector()
        result = detector.analyze(contexts)

        # Display summary
        console.print(Panel(result.summary(), title="Context Strategy"))

        # Export if output specified
        if output:
            import json

            data = detector.to_dict(result)
            with open(output, "w", encoding="utf-8") as f:
                json.dump(data, f, indent=2, ensure_ascii=False)
            console.print(f"\n[green]Exported to {output}[/green]")

    except Exception as e:
        console.print(f"[red]Error: {e}[/red]")


@click.command("allocate")
@click.option("--size", "-s", default=10000, help="Target dataset size")
@click.option("--region", "-r", default="china", help="Region for cost calculation")
@click.option("--output", "-o", default=None, help="Output file path (JSON/Markdown)")
@click.option("--format", "fmt", type=click.Choice(["table", "json", "markdown"]), default="table")
def allocate(size: int, region: str, output: str, fmt: str):
    """Generate human-machine task allocation."""
    from datarecipe.generators import HumanMachineSplitter, TaskType

    console.print("\n[bold]Generating human-machine allocation...[/bold]")
    console.print(f"Target size: {size:,} | Region: {region}\n")

    splitter = HumanMachineSplitter(region=region)
    result = splitter.analyze(
        dataset_size=size,
        task_types=[
            TaskType.CONTEXT_CREATION,
            TaskType.TASK_DESIGN,
            TaskType.RUBRICS_WRITING,
            TaskType.DATA_GENERATION,
            TaskType.QUALITY_REVIEW,
        ],
    )

    if fmt == "table":
        console.print(Panel(result.summary(), title="Allocation Summary"))
        console.print("\n" + result.to_markdown_table())
    elif fmt == "markdown":
        console.print(result.summary())
        console.print("\n" + result.to_markdown_table())
    else:
        import json

        data = splitter.to_dict(result)
        console.print(json.dumps(data, indent=2))

    if output:
        import json

        with open(output, "w", encoding="utf-8") as f:
            if output.endswith(".json"):
                json.dump(splitter.to_dict(result), f, indent=2, ensure_ascii=False)
            else:
                f.write(result.summary() + "\n\n" + result.to_markdown_table())
        console.print(f"\n[green]Exported to {output}[/green]")


@click.command("enhanced-guide")
@click.argument("dataset_id")
@click.option("--output", "-o", default=None, help="Output file path")
@click.option("--size", "-s", default=10000, help="Target dataset size")
@click.option("--region", "-r", default="china", help="Region for cost calculation")
def enhanced_guide(dataset_id: str, output: str, size: int, region: str):
    """Generate enhanced production guide with patterns and allocation."""
    from datarecipe.analyzers import ContextStrategyDetector
    from datarecipe.extractors import PromptExtractor, RubricsAnalyzer
    from datarecipe.generators import EnhancedGuideGenerator, HumanMachineSplitter, TaskType

    console.print(f"\n[bold]Generating enhanced guide for {dataset_id}...[/bold]\n")

    try:
        # Try to load and analyze the dataset
        rubrics_result = None
        prompt_library = None
        strategy_result = None

        try:
            from datasets import load_dataset

            ds = load_dataset(dataset_id, split="train", streaming=True)

            rubrics = []
            messages = []
            contexts = []

            for i, item in enumerate(ds):
                if i >= 500:
                    break
                # Collect rubrics
                for field in ["rubrics", "rubric", "criteria"]:
                    if field in item:
                        value = item[field]
                        if isinstance(value, list):
                            rubrics.extend(value)
                        elif isinstance(value, str):
                            rubrics.append(value)
                # Collect messages
                if "messages" in item and isinstance(item["messages"], list):
                    messages.extend(item["messages"])
                # Collect contexts
                for field in ["context", "input", "text"]:
                    if field in item and isinstance(item[field], str):
                        contexts.append(item[field])
                        break

            if rubrics:
                analyzer = RubricsAnalyzer()
                rubrics_result = analyzer.analyze(rubrics)
                console.print(f"[green]✓ Analyzed {len(rubrics)} rubrics[/green]")

            if messages:
                console.print(f"[dim]  Deduplicating {len(messages)} messages...[/dim]")
                extractor = PromptExtractor()
                prompt_library = extractor.extract(messages)
                console.print(
                    f"[green]✓ Extracted {prompt_library.unique_count} unique prompts[/green]"
                )

            if contexts:
                detector = ContextStrategyDetector()
                strategy_result = detector.analyze(contexts[:100])
                console.print(
                    f"[green]✓ Detected strategy: {strategy_result.primary_strategy.value}[/green]"
                )

        except Exception as e:
            console.print(f"[yellow]Could not analyze dataset: {e}[/yellow]")

        # Generate allocation
        splitter = HumanMachineSplitter(region=region)
        allocation = splitter.analyze(
            dataset_size=size,
            task_types=[
                TaskType.CONTEXT_CREATION,
                TaskType.TASK_DESIGN,
                TaskType.RUBRICS_WRITING,
                TaskType.QUALITY_REVIEW,
            ],
        )

        # Generate guide
        generator = EnhancedGuideGenerator()
        guide = generator.generate(
            dataset_name=dataset_id,
            target_size=size,
            rubrics_analysis=rubrics_result,
            prompt_library=prompt_library,
            context_strategy=strategy_result,
            allocation=allocation,
            region=region,
        )

        # Output
        markdown = generator.to_markdown(guide)

        if output:
            with open(output, "w", encoding="utf-8") as f:
                f.write(markdown)
            console.print(f"\n[green]Guide saved to {output}[/green]")
        else:
            console.print("\n" + markdown)

    except Exception as e:
        console.print(f"[red]Error: {e}[/red]")
        import traceback

        traceback.print_exc()


@click.command("generate")
@click.option(
    "--type", "gen_type", type=click.Choice(["rubrics", "prompts", "contexts"]), default="rubrics"
)
@click.option("--count", "-n", default=10, help="Number of items to generate")
@click.option("--context", "-c", default="the topic", help="Context/topic for generation")
@click.option("--output", "-o", default=None, help="Output file path (JSONL)")
def generate(gen_type: str, count: int, context: str, output: str):
    """Generate data based on patterns."""
    from datarecipe.generators import PatternGenerator

    console.print(f"\n[bold]Generating {count} {gen_type}...[/bold]\n")

    generator = PatternGenerator()

    if gen_type == "rubrics":
        result = generator.generate_rubrics(context=context, count=count)
    elif gen_type == "prompts":
        result = generator.generate_prompts(domain=context, count=count)
    elif gen_type == "contexts":
        result = generator.generate_contexts(count=count)
    else:
        console.print(f"[red]Unknown type: {gen_type}[/red]")
        return

    # Display
    console.print(Panel(result.summary(), title="Generation Result"))
    console.print("")

    for item in result.items[:5]:
        console.print(f"[cyan]{item.data_type}[/cyan]: {item.content[:100]}...")
        console.print("")

    if len(result.items) > 5:
        console.print(f"... and {len(result.items) - 5} more")

    # Export
    if output:
        generator.export_jsonl(result, output)
        console.print(f"\n[green]Exported to {output}[/green]")
