"""
Reference data validation commands.
"""

from pathlib import Path

import polars as pl
import typer

from ..common import BaseCommand, ValidationError, display_summary_table


class ReferenceValidationCommand(BaseCommand):
    """Reference data validation command."""

    # Constants from original reference.py
    COLUMN_SYNONYMS = {
        "cloud_provider": ["CloudProvider", "Cloud Provider"],
        "service": ["Service"],
        "usage_family": ["UsageFamily", "Usage Family"],
        "resource_type": ["ResourceType", "Resource Type"],
        "operation": ["Operation"],
        "usage_type": ["UsageType", "Usage Type"],
        "instance_type": ["InstanceType", "Instance Type"],
    }

    REQUIRED_COLUMNS = list(COLUMN_SYNONYMS.keys())

    ALLOWED_PROVIDERS = {
        "AWS",
        "Azure",
        "GCP",
        "Snowflake",
        "Datadog",
        "Databricks",
        "New Relic",
        "MongoDB",
        "AWS Marketplace",
        "Azure Marketplace",
        "Confluent",
        "Fastly",
        "OCI",
        "Oracle Cloud",
        "Sumologic",
    }

    def validate_reference_file(
        self, file_path: str, fix_issues: bool = False, verbose: bool = False
    ):
        """Validate reference data file."""
        try:
            ref_path = Path(file_path)
            self.validate_file_exists(ref_path, "reference file")

            if verbose:
                self.console.print(f"[blue]Loading reference file: {ref_path}[/blue]")

            # Load the CSV file
            try:
                df = pl.read_csv(ref_path)
            except Exception as e:
                raise ValidationError(f"Failed to read CSV file: {str(e)}")

            # Validate schema
            validation_results = self._validate_reference_schema(df)

            # Display validation results
            self._display_validation_results(validation_results, ref_path)

            # Apply fixes if requested
            if fix_issues and validation_results["has_issues"]:
                if self.confirm_action("Apply automatic fixes to the reference file?"):
                    fixed_df = self._fix_reference_issues(df)
                    self._save_fixed_file(fixed_df, ref_path)

        except Exception as e:
            self.handle_exception(e, "reference validation", verbose)

    def _validate_reference_schema(self, df: pl.DataFrame) -> dict:
        """Validate the reference data schema."""
        results = {
            "has_issues": False,
            "total_rows": len(df),
            "columns": df.columns,
            "missing_columns": [],
            "extra_columns": [],
            "synonym_columns": [],
            "invalid_providers": [],
            "duplicates": 0,
        }

        # Check for missing required columns
        present_columns = set(df.columns)
        required_columns = set(self.REQUIRED_COLUMNS)
        results["missing_columns"] = list(required_columns - present_columns)

        # Check for column synonyms that need renaming
        known_bad_columns = {}
        for canonical, synonyms in self.COLUMN_SYNONYMS.items():
            for synonym in synonyms:
                known_bad_columns[synonym] = canonical

        for col in df.columns:
            if col in known_bad_columns:
                results["synonym_columns"].append(
                    {"current": col, "should_be": known_bad_columns[col]}
                )

        # Check for extra columns
        canonical_and_synonyms = set(self.REQUIRED_COLUMNS)
        for synonyms in self.COLUMN_SYNONYMS.values():
            canonical_and_synonyms.update(synonyms)

        results["extra_columns"] = list(present_columns - canonical_and_synonyms)

        # Check for invalid cloud providers
        if "cloud_provider" in df.columns:
            unique_providers = (
                df.select("cloud_provider").unique().to_series().to_list()
            )
            results["invalid_providers"] = [
                p
                for p in unique_providers
                if p not in self.ALLOWED_PROVIDERS and p is not None
            ]

        # Check for duplicates
        duplicated = df.is_duplicated()
        results["duplicates"] = duplicated.sum()

        # Determine if there are issues
        results["has_issues"] = (
            len(results["missing_columns"]) > 0
            or len(results["synonym_columns"]) > 0
            or len(results["invalid_providers"]) > 0
            or results["duplicates"] > 0
        )

        return results

    def _display_validation_results(self, results: dict, file_path: Path):
        """Display validation results."""
        if results["has_issues"]:
            self.console.print(
                f"[yellow]Validation found issues in: {file_path}[/yellow]"
            )
        else:
            self.console.print(f"[green]✓ Reference file is valid: {file_path}[/green]")

        # Display summary
        summary_data = [
            {"metric": "Total rows", "value": results["total_rows"]},
            {"metric": "Total columns", "value": len(results["columns"])},
            {"metric": "Missing columns", "value": len(results["missing_columns"])},
            {"metric": "Synonym columns", "value": len(results["synonym_columns"])},
            {"metric": "Extra columns", "value": len(results["extra_columns"])},
            {"metric": "Invalid providers", "value": len(results["invalid_providers"])},
            {"metric": "Duplicate rows", "value": results["duplicates"]},
        ]

        display_summary_table(
            self.console, "Validation Summary", summary_data, ["metric", "value"]
        )

        # Display detailed issues
        if results["missing_columns"]:
            self.console.print(
                f"[red]Missing required columns: {', '.join(results['missing_columns'])}[/red]"
            )

        if results["synonym_columns"]:
            self.console.print("[yellow]Columns that should be renamed:[/yellow]")
            for col_info in results["synonym_columns"]:
                self.console.print(
                    f"  • '{col_info['current']}' → '{col_info['should_be']}'"
                )

        if results["invalid_providers"]:
            self.console.print(
                f"[red]Invalid cloud providers: {', '.join(results['invalid_providers'])}[/red]"
            )
            self.console.print(
                f"[blue]Valid providers: {', '.join(sorted(self.ALLOWED_PROVIDERS))}[/blue]"
            )

    def _fix_reference_issues(self, df: pl.DataFrame) -> pl.DataFrame:
        """Apply automatic fixes to reference data."""
        # This would implement the fixing logic from the original reference.py
        # For now, return the original dataframe
        return df

    def _save_fixed_file(self, df: pl.DataFrame, original_path: Path):
        """Save fixed reference file."""
        backup_path = original_path.with_suffix(".csv.backup")
        fixed_path = original_path.with_suffix(".fixed.csv")

        # Create backup
        original_path.rename(backup_path)

        # Save fixed file
        df.write_csv(fixed_path)

        self.display_success(
            "Reference file fixed and saved",
            {
                "Original backed up to": str(backup_path),
                "Fixed file saved as": str(fixed_path),
            },
        )


# Create Typer app
app = typer.Typer(help="Reference data validation commands")
validation_cmd = ReferenceValidationCommand()


@app.command()
def file(
    file_path: str = typer.Argument(..., help="Path to reference CSV file"),
    fix_issues: bool = typer.Option(
        False, "--fix", help="Attempt to fix validation issues"
    ),
    verbose: bool = typer.Option(
        False, "--verbose", "-v", help="Enable verbose output"
    ),
):
    """Validate reference data file."""
    validation_cmd.validate_reference_file(file_path, fix_issues, verbose)
