"""
Output and display utilities for audit results
"""

from typing import Dict


def print_column_summary(results: Dict):
    """Print summary statistics for all columns"""
    if 'column_summary' not in results or not results['column_summary']:
        return

    # Display table type if available
    if 'table_metadata' in results and 'table_type' in results['table_metadata']:
        table_type = results['table_metadata']['table_type']
        print(f"\n📑 Table Type: {table_type}")

    print("\n📋 Column Summary (All Columns):")
    print("=" * 115)
    print(f"{'Column Name':<30} {'Type':<30} {'Status':<12} {'Nulls':<15} {'Distinct':<15}")
    print("-" * 115)

    for col_name, col_data in results['column_summary'].items():
        # Handle N/A values for unloaded columns
        null_count = col_data['null_count']
        null_pct = col_data['null_pct']
        if null_count == 'N/A' or null_pct == 'N/A':
            null_display = "N/A"
        else:
            null_display = f"{null_count:,} ({null_pct:.1f}%)"

        # Handle None for distinct_count (complex types)
        distinct_count = col_data['distinct_count']
        if distinct_count == 'N/A':
            distinct_display = "N/A"
        elif distinct_count is not None:
            distinct_display = f"{distinct_count:,}"
        else:
            distinct_display = "N/A"

        status = col_data.get('status', 'UNKNOWN')

        # Color code status for terminal
        if status == 'OK':
            status_display = f"✓ {status}"
        elif status == 'ERROR':
            status_display = f"✗ {status}"
        else:
            status_display = f"- {status}"

        # Display the dtype - show conversion if it happened
        dtype_display = col_data['dtype']
        if 'converted_to' in col_data:
            # Show as "ORIGINAL → converted"
            dtype_display = f"{col_data['dtype']} → {col_data['converted_to']}"

        print(f"{col_name:<30} {dtype_display:<30} {status_display:<12} {null_display:<15} {distinct_display:<15}")

    print("=" * 115)

    print()


def _insights_to_dict(insights: list) -> dict:
    """Convert List[dict] to Dict for easy lookup

    Args:
        insights: List of insight dictionaries (serialized from InsightResult objects)

    Returns:
        Dictionary with insight types as keys and values
    """
    result = {}

    for insight in insights:
        insight_type = insight['type']
        value = insight['value']

        # Handle different insight types
        if insight_type in ['top_values', 'boolean_distribution', 'most_common_dates', 'most_common_hours', 'most_common_days', 'histogram']:
            # Lists of dicts
            result[insight_type] = value

        elif insight_type == 'quantiles':
            # Dict like {'p25': 1.0, 'p50': 2.0, 'p75': 3.0}
            result['quantiles'] = value

        elif insight_type in ['min_length', 'max_length', 'avg_length']:
            # Length stats - group under length_stats key
            if 'length_stats' not in result:
                result['length_stats'] = {}
            stat_name = insight_type.replace('_length', '')
            result['length_stats'][stat_name] = value

        else:
            # Simple scalar values (min, max, mean, std, median, min_date, max_date, date_range_days, timezone, etc.)
            result[insight_type] = value

    return result


def print_insights(results: Dict):
    """Print column insights"""
    if 'column_insights' not in results or not results['column_insights']:
        return

    print("\n💡 Column Insights:\n")

    for col_name, insights_list in results['column_insights'].items():
        print(f"📊 {col_name}:")

        # Convert list of InsightResult dicts to simple dict for easier access
        insights = _insights_to_dict(insights_list)

        # String insights
        if 'top_values' in insights:
            print(f"   Top {len(insights['top_values'])} Values:")
            for item in insights['top_values']:
                value_str = str(item['value'])[:50]  # Truncate long values
                print(f"      • '{value_str}' ({item['count']:,}x, {item['percentage']:.1f}%)")

        # Boolean insights
        if 'boolean_distribution' in insights:
            print(f"   Top {len(insights['boolean_distribution'])} Values:")
            for item in insights['boolean_distribution']:
                value_str = str(item['value'])
                print(f"      • '{value_str}' ({item['count']:,}x, {item['percentage']:.1f}%)")

        if 'length_stats' in insights:
            stats = insights['length_stats']
            stats_str = ", ".join([f"{k}={v}" for k, v in stats.items()])
            print(f"   Length: {stats_str}")

        # Numeric insights
        if 'min' in insights or 'max' in insights or 'mean' in insights:
            parts = []
            if 'min' in insights:
                parts.append(f"min={insights['min']:.2f}")
            if 'max' in insights:
                parts.append(f"max={insights['max']:.2f}")
            if 'mean' in insights:
                parts.append(f"mean={insights['mean']:.2f}")
            if 'median' in insights:
                parts.append(f"median={insights['median']:.2f}")
            print(f"   Stats: {', '.join(parts)}")

        if 'quantiles' in insights:
            q_str = ", ".join([f"{k}={v:.2f}" for k, v in insights['quantiles'].items()])
            print(f"   Quantiles: {q_str}")

        # DateTime insights
        if 'min_date' in insights or 'max_date' in insights:
            parts = []
            if 'min_date' in insights:
                parts.append(f"from {insights['min_date']}")
            if 'max_date' in insights:
                parts.append(f"to {insights['max_date']}")
            if 'date_range_days' in insights:
                parts.append(f"({insights['date_range_days']} days)")
            print(f"   Date Range: {' '.join(parts)}")

        if 'timezone' in insights:
            print(f"   Timezone: {insights['timezone']}")

        if 'most_common_dates' in insights:
            print(f"   Most Common Dates:")
            for item in insights['most_common_dates']:
                print(f"      • {item['date']} ({item['count']:,}x, {item['percentage']:.1f}%)")

        if 'most_common_days' in insights:
            print(f"   Most Common Days of Week:")
            for item in insights['most_common_days']:
                print(f"      • {item['day']} ({item['count']:,}x, {item['percentage']:.1f}%)")

        if 'most_common_hours' in insights:
            print(f"   Most Common Hours:")
            for item in insights['most_common_hours']:
                print(f"      • {item['hour']:02d}:00 ({item['count']:,}x, {item['percentage']:.1f}%)")

        print()


def print_results(results: Dict):
    """Pretty print audit results"""
    # First print column summary for all columns
    print_column_summary(results)

    # Print insights if available
    print_insights(results)

    has_issues = any(col_data['issues'] for col_data in results['columns'].values())

    if not has_issues:
        print("✅ No issues found!\n")
        return

    print("🔍 Issues Found:\n")

    for col_name, col_data in results['columns'].items():
        if not col_data['issues']:
            continue

        # Use dtype from column_summary if available (shows database type), otherwise use Polars type
        display_dtype = results['column_summary'][col_name]['dtype'] if col_name in results.get('column_summary', {}) else col_data['dtype']

        print(f"📊 Column: {col_name} ({display_dtype})")
        print(f"   Nulls: {col_data['null_count']:,} ({col_data['null_pct']:.1f}%)")
        print(f"   Distinct values: {col_data.get('distinct_count', 'N/A'):,}")

        for issue in col_data['issues']:
            issue_type = issue['type']

            if issue_type == 'TRAILING_CHARACTERS':
                pattern = issue.get('pattern', 'N/A')
                print(f"   ⚠️  TRAILING CHARACTERS ('{pattern}'): {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Examples: {issue['examples']}")

            elif issue_type == 'LEADING_CHARACTERS':
                pattern = issue.get('pattern', 'N/A')
                print(f"   ⚠️  LEADING CHARACTERS ('{pattern}'): {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Examples: {issue['examples'][:3]}")

            elif issue_type == 'CASE_DUPLICATES':
                print(f"   ⚠️  CASE DUPLICATES: {issue['count']} unique values with case variations")
                for example in issue['examples']:
                    print(f"      {example}")

            elif issue_type == 'REGEX_PATTERN':
                mode_label = "MATCH" if issue.get('mode') == 'match' else "CONTAINS"
                print(f"   ⚠️  REGEX PATTERN ({mode_label}): {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Pattern: {issue.get('pattern', 'N/A')}")
                if issue.get('description'):
                    print(f"      💡 {issue['description']}")
                print(f"      Examples: {issue['examples'][:3]}")

            elif issue_type == 'NUMERIC_STRINGS':
                print(f"   ⚠️  NUMERIC STRINGS: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples']}")

            elif issue_type == 'CONSTANT_HOUR':
                print(f"   ⚠️  CONSTANT HOUR: {issue['pct']:.1f}% at hour {issue['hour']}")
                print(f"      💡 {issue['suggestion']}")

            elif issue_type == 'ALWAYS_MIDNIGHT':
                print(f"   ⚠️  ALWAYS MIDNIGHT: {issue['pct']:.1f}% of timestamps")
                print(f"      💡 {issue['suggestion']}")

            elif issue_type == 'DATES_TOO_OLD':
                print(f"   ⚠️  DATES TOO OLD: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Oldest year: {issue['min_year_found']} (threshold: {issue['threshold_year']})")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:3]}")

            elif issue_type == 'DATES_TOO_FUTURE':
                print(f"   ⚠️  DATES TOO FUTURE: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Latest year: {issue['max_year_found']} (threshold: {issue['threshold_year']})")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:3]}")

            elif issue_type == 'SUSPICIOUS_YEAR':
                print(f"   ⚠️  SUSPICIOUS YEAR {issue['year']}: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:3]}")

            # Date range violations
            elif issue_type == 'DATE_NOT_AFTER':
                print(f"   ⚠️  DATES NOT AFTER: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Expected: date {issue['operator']} {issue['threshold']}")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:5]}")

            elif issue_type == 'DATE_NOT_AFTER_OR_EQUAL':
                print(f"   ⚠️  DATES NOT AFTER OR EQUAL: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Expected: date {issue['operator']} {issue['threshold']}")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:5]}")

            elif issue_type == 'DATE_NOT_BEFORE':
                print(f"   ⚠️  DATES NOT BEFORE: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Expected: date {issue['operator']} {issue['threshold']}")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:5]}")

            elif issue_type == 'DATE_NOT_BEFORE_OR_EQUAL':
                print(f"   ⚠️  DATES NOT BEFORE OR EQUAL: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Expected: date {issue['operator']} {issue['threshold']}")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:5]}")

            # Numeric range violations
            elif issue_type == 'VALUE_BELOW_MIN':
                print(f"   ⚠️  VALUES BELOW MIN: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Expected: value {issue['operator']} {issue['threshold']}")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:5]}")

            elif issue_type == 'VALUE_ABOVE_MAX':
                print(f"   ⚠️  VALUES ABOVE MAX: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Expected: value {issue['operator']} {issue['threshold']}")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:5]}")

            elif issue_type == 'VALUE_NOT_GREATER_THAN':
                print(f"   ⚠️  VALUES NOT GREATER THAN: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Expected: value {issue['operator']} {issue['threshold']}")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:5]}")

            elif issue_type == 'VALUE_NOT_GREATER_OR_EQUAL':
                print(f"   ⚠️  VALUES NOT GREATER OR EQUAL: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Expected: value {issue['operator']} {issue['threshold']}")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:5]}")

            elif issue_type == 'VALUE_NOT_LESS_THAN':
                print(f"   ⚠️  VALUES NOT LESS THAN: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Expected: value {issue['operator']} {issue['threshold']}")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:5]}")

            elif issue_type == 'VALUE_NOT_LESS_OR_EQUAL':
                print(f"   ⚠️  VALUES NOT LESS OR EQUAL: {issue['count']:,} rows ({issue['pct']:.1f}%)")
                print(f"      Expected: value {issue['operator']} {issue['threshold']}")
                print(f"      💡 {issue['suggestion']}")
                print(f"      Examples: {issue['examples'][:5]}")

        print()


def get_summary_stats(results: Dict) -> Dict:
    """
    Get high-level summary statistics from audit results

    Args:
        results: Audit results dictionary

    Returns:
        Dictionary with summary statistics
    """
    total_issues = sum(len(col_data['issues']) for col_data in results['columns'].values())
    columns_with_issues = len(results['columns'])

    issue_types = {}
    for col_data in results['columns'].values():
        for issue in col_data['issues']:
            issue_type = issue['type']
            issue_types[issue_type] = issue_types.get(issue_type, 0) + 1

    return {
        'table_name': results['table_name'],
        'total_rows': results['total_rows'],
        'analyzed_rows': results['analyzed_rows'],
        'sampled': results['sampled'],
        'total_issues': total_issues,
        'columns_with_issues': columns_with_issues,
        'issue_breakdown': issue_types,
        'timestamp': results.get('timestamp', ''),
        'duration_seconds': results.get('duration_seconds', 0)
    }
