"""
Schema Endpoints - Schema reconciliation and management.
"""

from fastapi import APIRouter, HTTPException
import polars as pl

from app.api.models import (
    SchemaReconcileRequest,
    SchemaReconcileResponse,
    SchemaDiffRequest,
    SchemaDiffResponse,
    SchemaResponse,
    SchemaDriftResponse,
    SchemaColumnResponse
)
from app.engines.polars_schema_reconciler import PolarsSchemaReconciler
from app.schema.advanced_schema_engine import AdvancedSchemaEngine, DataSchema
import structlog

logger = structlog.get_logger(__name__)

router = APIRouter()
schema_engine = AdvancedSchemaEngine()


@router.post("/schema/reconcile", response_model=SchemaReconcileResponse)
async def reconcile_schemas(request: SchemaReconcileRequest):
    """
    Reconcile schemas across multiple files.
    
    Uses fuzzy matching to align column names.
    """
    logger.info("schema_reconcile_request", files=len(request.files))
    
    try:
        # Load files as Polars DataFrames
        dfs = {}
        for name, path in request.files.items():
            df = pl.read_csv(path)
            dfs[name] = df
        
        # Reconcile
        reconciler = PolarsSchemaReconciler(fuzzy_threshold=request.fuzzy_threshold)
        drift, unified = reconciler.analyze_schemas(dfs)
        
        # Convert to response format
        drift_response = SchemaDriftResponse(
            missing_columns=drift.missing_columns,
            extra_columns=drift.extra_columns,
            type_drifts=drift.type_drifts,
            drift_score=schema_engine.calculate_drift_score([
                schema_engine.infer_schema(df, name=name)
                for name, df in dfs.items()
            ])
        )
        
        # Convert unified schema
        schema_response = SchemaResponse(
            name=unified.columns[0] if unified.columns else "unified",
            version="1.0.0",
            columns={
                col: SchemaColumnResponse(
                    name=col,
                    dtype=unified.column_types.get(col, "unknown"),
                    nullable=unified.nullable.get(col, True),
                    lineage=[m.canonical_name for m in unified.mappings if col in m.variations]
                )
                for col in unified.columns
            },
            created_at="",
            metadata={}
        )
        
        return SchemaReconcileResponse(
            unified_schema=schema_response,
            drift=drift_response,
            confidence_score=unified.confidence_score
        )
    
    except Exception as e:
        logger.error("schema_reconcile_error", error=str(e))
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/schema/diff", response_model=SchemaDiffResponse)
async def diff_schemas(request: SchemaDiffRequest):
    """
    Compare two schemas using DeepDiff.
    """
    logger.info("schema_diff_request")
    
    try:
        # Convert dicts to DataSchema objects
        schema1 = DataSchema(**request.schema1)
        schema2 = DataSchema(**request.schema2)
        
        # Diff using DeepDiff
        diff = schema_engine.diff_schemas(schema1, schema2)
        
        return SchemaDiffResponse(
            columns_added=diff['columns_added'],
            columns_removed=diff['columns_removed'],
            type_changes=diff['type_changes'],
            constraint_changes=diff.get('constraint_changes', {}),
            version_change=diff['version_change']
        )
    
    except Exception as e:
        logger.error("schema_diff_error", error=str(e))
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/schema/validate")
async def validate_schema(file_path: str, schema_dict: dict):
    """
    Validate a file against a schema.
    """
    logger.info("schema_validate_request", file=file_path)
    
    try:
        df = pl.read_csv(file_path)
        schema = DataSchema(**schema_dict)
        
        errors = schema_engine.validate_against_schema(df, schema, strict=True)
        
        return {
            'valid': len(errors) == 0,
            'errors': errors
        }
    
    except Exception as e:
        logger.error("schema_validate_error", error=str(e))
        raise HTTPException(status_code=500, detail=str(e))
