"""
Dataset identification and management CLI commands.

Provides commands for:
- dataset list: Show all datasets with basic metadata
- dataset tag: Add/update description for a dataset
- dataset describe: Show detailed metadata (with --refresh option)
"""

from typing import Optional
from datetime import datetime

import typer
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich import box

from src.services.environment_service import EnvironmentService
from src.services.s3_data_service import S3DataService
from src.services.dataset_identification import DatasetMetadataService, MetadataComputationService

console = Console()
app = typer.Typer(
    name="dataset",
    help="Dataset identification and management commands",
    no_args_is_help=True
)


@app.command("list")
def list_datasets():
    """
    List all datasets with basic metadata.

    Shows dataset ID, creation date, description, and stages completed.
    Fast operation that uses cached metadata or infers information for legacy datasets.

    Example:
        czbg dataset list
    """
    try:
        # FAIL FAST: Validate AWS credentials
        env_service = EnvironmentService()
        env_service.validate_aws_credentials_and_access()

        # Initialize services
        s3_service = S3DataService()
        metadata_service = DatasetMetadataService(s3_service)

        # Get all datasets
        console.print("📊 [bold blue]Loading datasets...[/bold blue]")
        datasets = metadata_service.list_datasets()

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

        # Create table
        table = Table(
            title=f"📦 Datasets ({len(datasets)} found)",
            box=box.ROUNDED,
            show_header=True,
            header_style="bold blue"
        )

        table.add_column("Dataset ID", style="cyan", min_width=20)
        table.add_column("Created", style="green", min_width=12)
        table.add_column("Description", style="white", min_width=30, max_width=50)
        table.add_column("Stages", style="yellow", min_width=15)
        table.add_column("Last Updated", style="magenta", min_width=12)

        for dataset in datasets:
            # Format creation date
            created_str = dataset.created_at.strftime("%Y-%m-%d")

            # Format last updated
            updated_str = dataset.last_updated.strftime("%Y-%m-%d")

            # Format stages
            stages_str = ", ".join(dataset.stages_completed) if dataset.stages_completed else "None"

            # Truncate description if needed
            description = dataset.description
            if len(description) > 47:
                description = description[:44] + "..."

            # Style legacy datasets differently
            if "legacy dataset" in dataset.description.lower():
                table.add_row(
                    f"[dim]{dataset.dataset_id}[/dim]",
                    f"[dim]{created_str}[/dim]",
                    f"[dim italic]{description}[/dim italic]",
                    f"[dim]{stages_str}[/dim]",
                    f"[dim]{updated_str}[/dim]"
                )
            else:
                table.add_row(
                    dataset.dataset_id,
                    created_str,
                    description,
                    stages_str,
                    updated_str
                )

        console.print(table)
        console.print(f"\n[dim]💡 Use `czbg dataset describe <dataset-id>` for detailed information[/dim]")

    except ValueError as e:
        console.print(f"❌ {str(e)}")
        raise typer.Exit(1)
    except Exception as e:
        console.print(f"❌ Failed to list datasets: {e}")
        raise typer.Exit(1)


@app.command("tag")
def tag_dataset(
    dataset_id: str = typer.Argument(..., help="Dataset ID to tag"),
    description: str = typer.Option(..., "--description", help="Description for the dataset")
):
    """
    Add or update description for a dataset.

    This creates metadata for legacy datasets or updates existing metadata.
    The description helps identify the dataset's purpose and characteristics.

    Examples:
        czbg dataset tag 2025-01-15_14-30-22 --description "Q4 2024 multi-cloud demo with anomalies"
        czbg dataset tag 2025-01-16_09-15-30 --description "Production-like data for client demo"
    """
    try:
        # FAIL FAST: Validate AWS credentials
        env_service = EnvironmentService()
        env_service.validate_aws_credentials_and_access()

        # Initialize services
        s3_service = S3DataService()
        metadata_service = DatasetMetadataService(s3_service)

        # Check if dataset exists
        if not metadata_service.dataset_exists(dataset_id):
            console.print(f"❌ Dataset not found: {dataset_id}")
            raise typer.Exit(1)

        # Update description
        console.print(f"🏷️  [bold blue]Updating dataset description...[/bold blue]")
        metadata_service.update_basic_metadata(dataset_id, description=description)

        console.print(f"✅ [bold green]Dataset tagged successfully![/bold green]")
        console.print(f"📊 Dataset: {dataset_id}")
        console.print(f"📝 Description: {description}")

    except ValueError as e:
        console.print(f"❌ {str(e)}")
        raise typer.Exit(1)
    except Exception as e:
        console.print(f"❌ Failed to tag dataset: {e}")
        raise typer.Exit(1)


@app.command("describe")
def describe_dataset(
    dataset_id: str = typer.Argument(..., help="Dataset ID to describe"),
    refresh: bool = typer.Option(False, "--refresh", help="Compute fresh metadata from parquet files (slower)")
):
    """
    Show detailed metadata for a dataset.

    By default, uses cached detailed metadata if available. Use --refresh to
    recompute metadata by analyzing the actual parquet files in S3.

    Examples:
        czbg dataset describe 2025-01-15_14-30-22
        czbg dataset describe 2025-01-15_14-30-22 --refresh
    """
    try:
        # FAIL FAST: Validate AWS credentials
        env_service = EnvironmentService()
        env_service.validate_aws_credentials_and_access()

        # Initialize services
        s3_service = S3DataService()
        metadata_service = DatasetMetadataService(s3_service)
        computation_service = MetadataComputationService(s3_service)

        # Check if dataset exists
        if not metadata_service.dataset_exists(dataset_id):
            console.print(f"❌ Dataset not found: {dataset_id}")
            raise typer.Exit(1)

        console.print(f"📊 [bold blue]Loading dataset metadata...[/bold blue]")

        # Get basic metadata (always fresh due to dynamic stage checking)
        basic_metadata = metadata_service.get_basic_metadata(dataset_id)

        # Show basic information first
        _display_basic_metadata(basic_metadata)

        if not basic_metadata.stages_completed:
            console.print("\n[yellow]No completed stages found. Dataset may be empty or still processing.[/yellow]")
            return

        # Check if we need to compute detailed metadata
        should_compute_detailed = refresh or _should_compute_detailed_metadata(basic_metadata)

        if should_compute_detailed:
            console.print(f"\n🔄 [yellow]Computing detailed metadata (this may take 10-60 seconds)...[/yellow]")

            try:
                detailed_metadata = computation_service.compute_detailed_metadata(basic_metadata)
                console.print(f"[dim]Computation completed, attempting to save cache...[/dim]")

                # Save the computed metadata for caching
                _save_detailed_metadata_cache(s3_service, dataset_id, detailed_metadata)

                console.print("✅ [green]Detailed metadata computed[/green]")
            except Exception as e:
                console.print(f"[red]Error during computation: {str(e)}[/red]")
                raise
        else:
            # Try to load cached detailed metadata
            console.print(f"\n🗂️  [blue]Loading cached metadata...[/blue]")
            detailed_metadata = _load_cached_detailed_metadata(s3_service, metadata_service, dataset_id)

            if not detailed_metadata:
                console.print(f"🔄 [yellow]No cached metadata found or cache expired. Computing fresh metadata...[/yellow]")
                console.print(f"[dim]Starting computation process...[/dim]")
                detailed_metadata = computation_service.compute_detailed_metadata(basic_metadata)
                console.print(f"[dim]Computation completed! Now saving to S3 cache...[/dim]")
                _save_detailed_metadata_cache(s3_service, dataset_id, detailed_metadata)
                console.print("✅ [green]Detailed metadata computed and cached[/green]")
            else:
                console.print("✅ [green]Using cached detailed metadata[/green]")

        # Display detailed information
        _display_detailed_metadata(detailed_metadata)

    except ValueError as e:
        console.print(f"❌ {str(e)}")
        raise typer.Exit(1)
    except Exception as e:
        console.print(f"❌ Failed to describe dataset: {e}")
        raise typer.Exit(1)


def _display_basic_metadata(metadata):
    """Display basic metadata information."""
    console.print(f"\n[bold cyan]📦 Dataset: {metadata.dataset_id}[/bold cyan]")
    console.print(f"[bold]Description:[/bold] {metadata.description}")
    console.print(f"[bold]Created:[/bold] {metadata.created_at.strftime('%Y-%m-%d %H:%M:%S')}")
    console.print(f"[bold]Reference Data Version:[/bold] {metadata.reference_data_version}")

    # Show stages with nice formatting
    if metadata.stages_completed:
        stages_str = " → ".join(metadata.stages_completed)
        console.print(f"[bold]Stages Completed:[/bold] {stages_str}")
    else:
        console.print(f"[bold]Stages Completed:[/bold] [dim]None[/dim]")

    console.print(f"[bold]Last Updated:[/bold] {metadata.last_updated.strftime('%Y-%m-%d %H:%M:%S')}")


def _display_detailed_metadata(detailed_metadata):
    """Display detailed metadata with cost and row breakdowns."""
    cost_breakdown = detailed_metadata.provider_cost_breakdown
    row_breakdown = detailed_metadata.provider_row_breakdown
    insights = detailed_metadata.summary_insights

    # Provider cost breakdown
    if cost_breakdown.provider_costs:
        console.print(f"\n[bold blue]💰 Provider Cost Breakdown:[/bold blue]")

        cost_table = Table(show_header=True, header_style="bold blue", box=box.ROUNDED)
        cost_table.add_column("Provider", style="cyan")
        cost_table.add_column("Total Cost", style="green", justify="right")

        for provider in insights.top_providers_by_cost:
            if provider in cost_breakdown.provider_costs:
                costs = cost_breakdown.provider_costs[provider]
                yearly_total = costs.get("yearly_total", 0)

                cost_table.add_row(
                    provider,
                    f"${yearly_total:,.0f}"
                )

        console.print(cost_table)

    # Provider row breakdown summary
    if row_breakdown.provider_rows:
        console.print(f"\n[bold blue]📊 Provider Row Counts:[/bold blue]")

        row_table = Table(show_header=True, header_style="bold blue", box=box.ROUNDED)
        row_table.add_column("Provider", style="cyan")
        row_table.add_column("Max Monthly Rows", style="green", justify="right")
        row_table.add_column("Total Months", style="yellow", justify="right")

        for provider in insights.top_providers_by_max_monthly_rows:
            if provider in row_breakdown.provider_rows:
                rows = row_breakdown.provider_rows[provider]
                max_monthly = max(rows.values()) if rows else 0
                month_count = len([k for k in rows.keys() if k != "unknown"])

                row_table.add_row(
                    provider,
                    f"{max_monthly:,}",
                    str(month_count)
                )

        console.print(row_table)

    # Summary insights
    if any([insights.top_providers_by_cost, insights.date_ranges_by_provider]):
        console.print(f"\n[bold blue]📈 Summary Insights:[/bold blue]")

        if insights.top_providers_by_cost:
            console.print(f"[bold]Top Providers by Cost:[/bold] {', '.join(insights.top_providers_by_cost)}")

        if insights.date_ranges_by_provider:
            console.print(f"[bold]Date Ranges:[/bold]")
            for provider, date_range in insights.date_ranges_by_provider.items():
                console.print(f"  • {provider}: {date_range}")

    # Show when metadata was computed
    computed_time = detailed_metadata.metadata_computed_at.strftime('%Y-%m-%d %H:%M:%S')
    console.print(f"\n[dim]💡 Metadata computed: {computed_time}[/dim]")
    console.print(f"[dim]💡 Use --refresh to recompute from source data[/dim]")


def _should_compute_detailed_metadata(basic_metadata) -> bool:
    """Determine if detailed metadata should be computed based on cache freshness."""
    # Only compute if we have stages AND no fresh cache exists
    if len(basic_metadata.stages_completed) == 0:
        return False

    # Check if fresh cache exists
    # This is checked here to avoid duplicate cache loading logic
    return False  # Let the cache loading logic handle the decision


def _save_detailed_metadata_cache(s3_service, dataset_id: str, detailed_metadata):
    """Save detailed metadata cache to S3."""
    import json
    from datetime import datetime
    from rich.console import Console

    console = Console()

    cache_path = f"czbillgen/datasets/{dataset_id}/_detailed_cache.json"

    # Convert to JSON-serializable format (use UTC for consistency)
    cache_data = {
        "metadata_computed_at": detailed_metadata.metadata_computed_at.isoformat() + "Z",
        "cache_created_at": datetime.utcnow().isoformat() + "Z",
        "provider_cost_breakdown": detailed_metadata.provider_cost_breakdown.provider_costs,
        "provider_row_breakdown": detailed_metadata.provider_row_breakdown.provider_rows,
        "summary_insights": {
            "top_providers_by_cost": detailed_metadata.summary_insights.top_providers_by_cost,
            "top_providers_by_max_monthly_rows": detailed_metadata.summary_insights.top_providers_by_max_monthly_rows,
            "date_ranges_by_provider": detailed_metadata.summary_insights.date_ranges_by_provider
        }
    }

    try:
        json_content = json.dumps(cache_data, indent=2)
        s3_service.upload_text_content(cache_path, json_content)
        console.print(f"[dim]Cache saved to: {cache_path}[/dim]")
    except Exception as e:
        # Cache save failure shouldn't block the operation
        console.print(f"[dim]Cache save failed: {str(e)}[/dim]")
        pass


def _load_cached_detailed_metadata(s3_service, metadata_service, dataset_id):
    """Load detailed metadata from cache if available and fresh."""
    import json
    from rich.console import Console
    from src.services.dataset_identification.models import DetailedMetadata, ProviderCostBreakdown, ProviderRowBreakdown, SummaryInsights

    console = Console()

    cache_path = f"czbillgen/datasets/{dataset_id}/_detailed_cache.json"

    try:
        console.print(f"[dim]Looking for cache at: {cache_path}[/dim]")
        cache_content = s3_service.read_text_file(cache_path)
        console.print(f"[dim]Cache file found, size: {len(cache_content)} bytes[/dim]")

        cache_data = json.loads(cache_content)
        console.print(f"[dim]Cache JSON parsed successfully[/dim]")

        # Check if cache is reasonably fresh (less than 24 hours old)
        from datetime import datetime, timedelta

        # Use cache_created_at if available, fallback to metadata_computed_at
        cache_timestamp = cache_data.get("cache_created_at", cache_data["metadata_computed_at"])
        cache_created_at = datetime.fromisoformat(cache_timestamp.replace('Z', '+00:00'))

        # Compare UTC times for consistency
        now_utc = datetime.utcnow().replace(tzinfo=cache_created_at.tzinfo)
        cache_age = now_utc - cache_created_at
        console.print(f"[dim]Cache age: {cache_age.total_seconds():.0f} seconds ({cache_age.total_seconds()/3600:.1f} hours)[/dim]")

        if cache_age > timedelta(hours=24):
            console.print(f"[dim]Cache expired (older than 24 hours)[/dim]")
            return None  # Cache too old

        # Get the original computation timestamp for display
        computed_at = datetime.fromisoformat(cache_data["metadata_computed_at"].replace('Z', '+00:00'))

        # Reconstruct detailed metadata
        basic_metadata = metadata_service.get_basic_metadata(dataset_id)

        detailed_metadata = DetailedMetadata(
            basic=basic_metadata,
            metadata_computed_at=computed_at,
            provider_cost_breakdown=ProviderCostBreakdown(
                provider_costs=cache_data["provider_cost_breakdown"]
            ),
            provider_row_breakdown=ProviderRowBreakdown(
                provider_rows=cache_data["provider_row_breakdown"]
            ),
            summary_insights=SummaryInsights(
                top_providers_by_cost=cache_data["summary_insights"]["top_providers_by_cost"],
                top_providers_by_max_monthly_rows=cache_data["summary_insights"]["top_providers_by_max_monthly_rows"],
                date_ranges_by_provider=cache_data["summary_insights"]["date_ranges_by_provider"]
            )
        )

        console.print(f"[dim]Cache loaded successfully![/dim]")
        return detailed_metadata

    except FileNotFoundError as e:
        console.print(f"[dim]Cache file not found: {str(e)}[/dim]")
        return None
    except json.JSONDecodeError as e:
        console.print(f"[dim]Cache JSON parsing failed: {str(e)}[/dim]")
        return None
    except Exception as e:
        console.print(f"[dim]Cache loading failed with unexpected error: {str(e)}[/dim]")
        return None


@app.command("explore")
def explore_dataset(
    dataset_id: Optional[str] = typer.Option(None, "--dataset", help="Dataset to explore"),
    stage: Optional[str] = typer.Option(None, "--stage", help="Stage to explore (generate, k8s, metadata, usage, discount)"),
    provider: Optional[str] = typer.Option(None, "--provider", help="Provider to explore (AWS, GCP, Azure)")
):
    """
    Progressive drill-down exploration of dataset structure.

    Similar to the legacy list-datasets command, this provides detailed
    exploration of dataset files and structure with filtering options.

    Examples:
        czbg dataset explore
        czbg dataset explore --dataset 2025-01-15_14-30-22
        czbg dataset explore --dataset 2025-01-15_14-30-22 --stage usage --provider AWS
    """
    try:
        # FAIL FAST: Validate AWS credentials
        env_service = EnvironmentService()
        env_service.validate_aws_credentials_and_access()

        # Initialize services
        s3_service = S3DataService()
        metadata_service = DatasetMetadataService(s3_service)

        if not dataset_id:
            # Show all datasets for selection
            _explore_dataset_selection(metadata_service)
        elif not stage:
            # Show stages for selected dataset
            _explore_stage_selection(s3_service, metadata_service, dataset_id)
        elif not provider:
            # Show providers for selected dataset and stage
            _explore_provider_selection(s3_service, dataset_id, stage)
        else:
            # Show detailed file structure
            _explore_file_structure(s3_service, dataset_id, stage, provider)

    except ValueError as e:
        console.print(f"❌ {str(e)}")
        raise typer.Exit(1)
    except Exception as e:
        console.print(f"❌ Failed to explore dataset: {e}")
        raise typer.Exit(1)


def _explore_dataset_selection(metadata_service):
    """Show dataset selection interface."""
    console.print("🔍 [bold blue]Available Datasets[/bold blue]")

    datasets = metadata_service.list_datasets()

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

    # Create selection table
    table = Table(show_header=True, header_style="bold blue", box=box.ROUNDED)
    table.add_column("#", style="dim", width=3)
    table.add_column("Dataset ID", style="cyan", min_width=20)
    table.add_column("Description", style="white", min_width=30)
    table.add_column("Stages", style="yellow", min_width=15)
    table.add_column("Created", style="green", min_width=10)

    for i, dataset in enumerate(datasets[:20], 1):  # Show top 20
        created_str = dataset.created_at.strftime("%m-%d")
        stages_str = ", ".join(dataset.stages_completed) if dataset.stages_completed else "None"

        # Truncate description
        description = dataset.description
        if len(description) > 35:
            description = description[:32] + "..."

        table.add_row(
            str(i),
            dataset.dataset_id,
            description,
            stages_str,
            created_str
        )

    console.print(table)
    console.print(f"\n[dim]💡 Use: czbg dataset explore --dataset <dataset-id>[/dim]")


def _explore_stage_selection(s3_service, metadata_service, dataset_id):
    """Show stage selection for a dataset."""
    if not metadata_service.dataset_exists(dataset_id):
        console.print(f"❌ Dataset not found: {dataset_id}")
        return

    basic_metadata = metadata_service.get_basic_metadata(dataset_id)

    console.print(f"🔍 [bold blue]Dataset: {dataset_id}[/bold blue]")
    console.print(f"[bold]Description:[/bold] {basic_metadata.description}")

    if not basic_metadata.stages_completed:
        console.print("[yellow]No completed stages found.[/yellow]")
        return

    # Create stage table
    table = Table(show_header=True, header_style="bold blue", box=box.ROUNDED)
    table.add_column("Stage", style="cyan", min_width=12)
    table.add_column("Status", style="green")
    table.add_column("File Count", style="yellow", justify="right")
    table.add_column("Size", style="magenta", justify="right")

    for stage in ["generate", "k8s", "metadata", "usage", "discount", "tax"]:
        if stage in basic_metadata.stages_completed:
            # Get file count and size info
            stage_path = f"czbillgen/datasets/{dataset_id}/{stage}/"
            try:
                files = s3_service.list_files(stage_path, max_files=100)
                file_count = len(files)

                # Get size estimate (simplified)
                size_estimate = "~" + _format_size_estimate(file_count)

                table.add_row(stage, "✅ Complete", str(file_count), size_estimate)
            except Exception:
                table.add_row(stage, "✅ Complete", "?", "?")
        else:
            table.add_row(f"[dim]{stage}[/dim]", "[dim]Not completed[/dim]", "[dim]-[/dim]", "[dim]-[/dim]")

    console.print(table)
    console.print(f"\n[dim]💡 Use: czbg dataset explore --dataset {dataset_id} --stage <stage>[/dim]")


def _explore_provider_selection(s3_service, dataset_id, stage):
    """Show provider selection for a dataset stage."""
    console.print(f"🔍 [bold blue]Dataset: {dataset_id} | Stage: {stage}[/bold blue]")

    stage_path = f"czbillgen/datasets/{dataset_id}/{stage}/"

    try:
        folders = s3_service.list_folders(stage_path)

        if not folders:
            console.print("[yellow]No providers found in this stage.[/yellow]")
            return

        # Create provider table
        table = Table(show_header=True, header_style="bold blue", box=box.ROUNDED)
        table.add_column("Provider", style="cyan", min_width=10)
        table.add_column("File Count", style="yellow", justify="right")
        table.add_column("Sample Files", style="white", min_width=40)

        for folder in folders:
            provider = folder.rstrip('/').split('/')[-1].upper()

            if not provider:
                continue

            try:
                provider_files = s3_service.list_files(folder, max_files=5)
                file_count = len(provider_files)

                # Show sample files
                sample_files = []
                for file_path in provider_files[:3]:
                    filename = file_path.split('/')[-1]
                    if filename:
                        sample_files.append(filename)

                sample_str = ", ".join(sample_files)
                if len(provider_files) > 3:
                    sample_str += "..."

                table.add_row(provider, str(file_count), sample_str)

            except Exception:
                table.add_row(provider, "?", "Error reading files")

        console.print(table)
        console.print(f"\n[dim]💡 Use: czbg dataset explore --dataset {dataset_id} --stage {stage} --provider <provider>[/dim]")

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


def _explore_file_structure(s3_service, dataset_id, stage, provider):
    """Show detailed file structure for dataset/stage/provider."""
    console.print(f"🔍 [bold blue]Dataset: {dataset_id} | Stage: {stage} | Provider: {provider}[/bold blue]")

    # Try different case variations to find the correct provider folder
    stage_path = f"czbillgen/datasets/{dataset_id}/{stage}/"
    folders = s3_service.list_folders(stage_path)

    # Find matching provider folder (case-insensitive)
    actual_provider_folder = None
    for folder in folders:
        folder_name = folder.rstrip('/').split('/')[-1]
        if folder_name.upper() == provider.upper():
            actual_provider_folder = folder_name
            break

    if not actual_provider_folder:
        console.print(f"[yellow]Provider '{provider}' not found in stage '{stage}'.[/yellow]")
        return

    provider_path = f"czbillgen/datasets/{dataset_id}/{stage}/{actual_provider_folder}/"

    try:
        files = s3_service.list_files(provider_path, max_files=50)

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

        # Group files by type
        parquet_files = [f for f in files if f.endswith('.parquet')]
        other_files = [f for f in files if not f.endswith('.parquet')]

        if parquet_files:
            console.print(f"\n[bold blue]📊 Parquet Files ({len(parquet_files)}):[/bold blue]")

            table = Table(show_header=True, header_style="bold blue", box=box.ROUNDED)
            table.add_column("File", style="cyan", min_width=30)
            table.add_column("Rows", style="yellow", justify="right")
            table.add_column("Estimated Size", style="green", justify="right")

            for file_path in parquet_files[:20]:  # Show first 20
                filename = file_path.split('/')[-1]

                try:
                    # Get row count
                    row_count = s3_service.get_parquet_row_count(file_path)
                    size_est = _format_size_estimate_from_rows(row_count)

                    table.add_row(filename, f"{row_count:,}", size_est)
                except Exception:
                    table.add_row(filename, "?", "?")

            console.print(table)

            if len(parquet_files) > 20:
                console.print(f"[dim]... and {len(parquet_files) - 20} more files[/dim]")

        if other_files:
            console.print(f"\n[bold blue]📄 Other Files ({len(other_files)}):[/bold blue]")
            for file_path in other_files[:10]:
                filename = file_path.split('/')[-1]
                console.print(f"  • {filename}")

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


def _format_size_estimate(file_count: int) -> str:
    """Format size estimate based on file count."""
    if file_count == 0:
        return "0 MB"
    elif file_count < 10:
        return f"{file_count * 5} MB"
    elif file_count < 100:
        return f"{file_count // 10} GB"
    else:
        return f"{file_count // 100} GB"


def _format_size_estimate_from_rows(row_count: int) -> str:
    """Format size estimate based on row count."""
    if row_count == 0:
        return "0 MB"
    elif row_count < 1000:
        return "< 1 MB"
    elif row_count < 100000:
        return f"{row_count // 1000} MB"
    else:
        return f"{row_count // 100000} GB"


def _format_timespan(hours: float) -> str:
    """Format hours into human readable timespan."""
    if hours < 1:
        return f"{int(hours * 60)}m"
    elif hours < 24:
        return f"{hours:.1f}h"
    else:
        days = hours / 24
        return f"{days:.1f}d"