"""
Enhanced DataShaper CLI - Command-line interface for pipelines.

Commands:
- datashaper clean <folder> - Clean CSV files
- datashaper report <file> - Generate report
- datashaper merge <folder> - Merge files with reconciliation
- datashaper schema diff <v1> <v2> - Compare schemas
- datashaper benchmark <folder> - Run performance tests
"""

import click
import sys
from pathlib import Path
from typing import Optional
import polars as pl
from rich.console import Console
from rich.table import Table
from rich.progress import Progress
import time

# Add backend to path
sys.path.insert(0, str(Path(__file__).parent / "backend"))

from app.engines.polars_detector import PolarsDetector
from app.engines.polars_fixer import PolarsFixer
from app.engines.polars_schema_reconciler import PolarsSchemaReconciler
from app.schema.advanced_schema_engine import AdvancedSchemaEngine

console = Console()


@click.group()
@click.version_option(version="3.0.0")
def cli():
    """
    🚀 DataShaper AI - Enterprise Data Healing Engine
    
    Clean, harmonize, and fix messy CSV files with 10x speed using Polars.
    """
    pass


@cli.command()
@click.argument('folder', type=click.Path(exists=True))
@click.option('--workers', '-w', default=4, help='Number of parallel workers')
@click.option('--output', '-o', type=click.Path(), help='Output folder')
@click.option('--schema-out', type=click.Path(), help='Export schema JSON')
@click.option('--auto', is_flag=True, help='Auto-fix all issues')
@click.option('--flag-only', is_flag=True, help='Flag issues without fixing')
def clean(folder: str, workers: int, output: Optional[str], schema_out: Optional[str], auto: bool, flag_only: bool):
    """
    Clean CSV files in a folder.
    
    Example:
        datashaper clean data/ --workers 8 --schema-out schema.json
    """
    console.print(f"\n[bold cyan]🚀 DataShaper AI - Cleaning Data[/bold cyan]\n")
    
    folder_path = Path(folder)
    csv_files = list(folder_path.glob("*.csv"))
    
    if not csv_files:
        console.print("[red]❌ No CSV files found[/red]")
        return
    
    console.print(f"Found {len(csv_files)} CSV files\n")
    
    detector = PolarsDetector()
    fixer = PolarsFixer()
    total_issues = 0
    total_fixes = 0
    
    with Progress() as progress:
        task = progress.add_task("[cyan]Processing files...", total=len(csv_files))
        
        for csv_file in csv_files:
            try:
                # Load with Polars
                df = pl.read_csv(csv_file)
                
                # Detect issues
                issues = detector.detect_all(df)
                total_issues += len(issues)
                
                # Fix if requested
                if auto and not flag_only:
                    df = fixer.apply_all_safe_fixes(df)
                    total_fixes += len(issues)
                
                # Save if output specified
                if output and auto:
                    output_path = Path(output) / csv_file.name
                    output_path.parent.mkdir(parents=True, exist_ok=True)
                    df.write_csv(output_path)
                
                progress.update(task, advance=1)
            
            except Exception as e:
                console.print(f"[red]Error processing {csv_file.name}: {e}[/red]")
    
    # Summary
    console.print(f"\n[bold green]✅ Complete![/bold green]")
    console.print(f"Files processed: {len(csv_files)}")
    console.print(f"Issues found: {total_issues}")
    if auto:
        console.print(f"Fixes applied: {total_fixes}")
    
    # Export schema if requested
    if schema_out and csv_files:
        schema_engine = AdvancedSchemaEngine()
        df = pl.read_csv(csv_files[0])
        schema = schema_engine.infer_schema(df, name=folder_path.name)
        
        Path(schema_out).write_text(schema.to_json(), encoding='utf-8')
        console.print(f"\n[cyan]📋 Schema exported to {schema_out}[/cyan]")


@cli.command()
@click.argument('file', type=click.Path(exists=True))
@click.option('--format', '-f', type=click.Choice(['html', 'json']), default='html')
@click.option('--output', '-o', type=click.Path(), help='Output file')
def report(file: str, format: str, output: Optional[str]):
    """
    Generate report for a CSV file.
    
    Example:
        datashaper report data.csv --format html --output report.html
    """
    console.print(f"\n[bold cyan]📊 Generating Report[/bold cyan]\n")
    
    try:
        df = pl.read_csv(file)
        detector = PolarsDetector()
        issues = detector.detect_all(df)
        
        if format == 'json':
            import json
            report_data = {
                'file': str(file),
                'rows': df.height,
                'columns': len(df.columns),
                'issues': [
                    {
                        'type': issue.issue_type,
                        'severity': issue.severity,
                        'description': issue.description
                    }
                    for issue in issues
                ]
            }
            
            if output:
                Path(output).write_text(json.dumps(report_data, indent=2))
                console.print(f"[green]✅ JSON report saved to {output}[/green]")
            else:
                console.print(json.dumps(report_data, indent=2))
        
        else:  # html
            from app.reporting.enterprise_report import EnterpriseReportGenerator
            
            result_data = {
                'files_processed': 1,
                'issues_found': len(issues),
                'fixes_applied': 0,
                'quality_score': max(0, 100 - len(issues) * 5),
                'processing_time_seconds': 0.0,
                'issues': issues
            }
            
            schema_engine = AdvancedSchemaEngine()
            schema = schema_engine.infer_schema(df, name=Path(file).stem)
            
            generator = EnterpriseReportGenerator()
            html = generator.generate_report(
                result_data=result_data,
                schema_data=schema.to_dict()
            )
            
            output_path = output or f"{Path(file).stem}_report.html"
            Path(output_path).write_text(html, encoding='utf-8')
            
            console.print(f"[green]✅ HTML report saved to {output_path}[/green]")
    
    except Exception as e:
        console.print(f"[red]❌ Error: {e}[/red]")


@cli.command()
@click.argument('folder', type=click.Path(exists=True))
@click.option('--output', '-o', type=click.Path(), default='merged.csv')
@click.option('--reconcile', is_flag=True, help='Reconcile schemas with fuzzy matching')
def merge(folder: str, output: str, reconcile: bool):
    """
    Merge CSV files with optional schema reconciliation.
    
    Example:
        datashaper merge data/ --reconcile --output merged.csv
    """
    console.print(f"\n[bold cyan]🔗 Merging Files[/bold cyan]\n")
    
    folder_path = Path(folder)
    csv_files = list(folder_path.glob("*.csv"))
    
    if not csv_files:
        console.print("[red]❌ No CSV files found[/red]")
        return
    
    console.print(f"Found {len(csv_files)} files to merge\n")
    
    try:
        # Load all files
        dfs = {str(f.name): pl.read_csv(f) for f in csv_files}
        
        if reconcile:
            console.print("[cyan]🔍 Reconciling schemas...[/cyan]")
            reconciler = PolarsSchemaReconciler()
            drift, unified = reconciler.analyze_schemas(dfs)
            
            console.print(f"Drift score: {drift.missing_columns}")
            
            # Align schemas
            aligned_dfs = reconciler.reconcile_dataframes(dfs, unified)
            merged = pl.concat(list(aligned_dfs.values()), how='vertical')
        else:
            # Simple concat
            merged = pl.concat(list(dfs.values()), how='vertical')
        
        # Save
        merged.write_csv(output)
        
        console.print(f"\n[green]✅ Merged {len(dfs)} files into {output}[/green]")
        console.print(f"Total rows: {merged.height:,}")
        console.print(f"Columns: {len(merged.columns)}")
    
    except Exception as e:
        console.print(f"[red]❌ Error: {e}[/red]")


@cli.command(name='schema-diff')
@click.argument('schema1', type=click.Path(exists=True))
@click.argument('schema2', type=click.Path(exists=True))
def schema_diff(schema1: str, schema2: str):
    """
    Compare two schema JSON files.
    
    Example:
        datashaper schema-diff v1.json v2.json
    """
    console.print(f"\n[bold cyan]📋 Schema Diff[/bold cyan]\n")
    
    try:
        import json
        from app.schema.advanced_schema_engine import AdvancedSchemaEngine, DataSchema
        
        s1_data = json.loads(Path(schema1).read_text())
        s2_data = json.loads(Path(schema2).read_text())
        
        s1 = DataSchema(**s1_data)
        s2 = DataSchema(**s2_data)
        
        engine = AdvancedSchemaEngine()
        diff = engine.diff_schemas(s1, s2)
        
        # Display diff
        table = Table(title="Schema Differences")
        table.add_column("Type", style="cyan")
        table.add_column("Details", style="yellow")
        
        if diff['columns_added']:
            table.add_row("Added", ", ".join(diff['columns_added']))
        if diff['columns_removed']:
            table.add_row("Removed", ", ".join(diff['columns_removed']))
        if diff['type_changes']:
            for col, change in diff['type_changes'].items():
                table.add_row("Type Change", f"{col}: {change['old']} → {change['new']}")
        
        console.print(table)
        
        if not (diff['columns_added'] or diff['columns_removed'] or diff['type_changes']):
            console.print("[green]✅ Schemas are identical[/green]")
    
    except Exception as e:
        console.print(f"[red]❌ Error: {e}[/red]")


@cli.command()
@click.argument('folder', type=click.Path(exists=True))
@click.option('--size', default='100MB', help='Dataset size for benchmark')
def benchmark(folder: str, size: str):
    """
    Run performance benchmark.
    
    Example:
        datashaper benchmark data/ --size 1GB
    """
    console.print(f"\n[bold cyan]⚡ Performance Benchmark[/bold cyan]\n")
    
    folder_path = Path(folder)
    csv_files = list(folder_path.glob("*.csv"))
    
    if not csv_files:
        console.print("[red]❌ No CSV files found[/red]")
        return
    
    total_rows = 0
    start_time = time.time()
    
    detector = PolarsDetector()
    fixer = PolarsFixer()
    
    for csv_file in csv_files:
        df = pl.read_csv(csv_file)
        total_rows += df.height
        
        issues = detector.detect_all(df)
        df_fixed = fixer.apply_all_safe_fixes(df)
    
    end_time = time.time()
    duration = end_time - start_time
    
    # Results
    table = Table(title="Benchmark Results")
    table.add_column("Metric", style="cyan")
    table.add_column("Value", style="green")
    
    table.add_row("Files", str(len(csv_files)))
    table.add_row("Total Rows", f"{total_rows:,}")
    table.add_row("Processing Time", f"{duration:.2f}s")
    table.add_row("Rows/Second", f"{int(total_rows / duration):,}")
    table.add_row("Engine", "Polars (10x faster)")
    
    console.print(table)


if __name__ == '__main__':
    cli()
