"""File management commands."""

import asyncio
import mimetypes
from pathlib import Path

import click
from rich.console import Console
from rich.table import Table

from iseq_flow.api import APIError, FlowAPIClient

console = Console()


def format_size(size: int | None) -> str:
    """Format file size for display."""
    if size is None:
        return "-"

    for unit in ["B", "KB", "MB", "GB", "TB"]:
        if size < 1024:
            return f"{size:.1f} {unit}" if unit != "B" else f"{size} {unit}"
        size /= 1024
    return f"{size:.1f} PB"


@click.group()
def files():
    """File operations (ls, download, upload)."""
    pass


@files.command("ls")
@click.option("--project", "-p", required=True, help="Project ID")
@click.option("--path", default="", help="Path within bucket")
def list_files(project: str, path: str):
    """List files and folders in a project."""

    async def _list():
        client = FlowAPIClient()
        return await client.list_files(project, path)

    try:
        result = asyncio.run(_list())

        # Display bucket info
        console.print(f"[dim]Bucket:[/dim] {result.bucket_name}")
        if result.path:
            console.print(f"[dim]Path:[/dim] {result.path}")
        console.print()

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

        # Create table
        table = Table(show_header=True, header_style="bold")
        table.add_column("Type", width=6)
        table.add_column("Name")
        table.add_column("Size", justify="right")
        table.add_column("Modified")

        # Add folders first
        for folder in result.folders:
            table.add_row(
                "[blue]DIR[/blue]",
                f"[blue]{folder.display_name}/[/blue]",
                "-",
                "-",
            )

        # Add files
        for file in result.files:
            table.add_row(
                "[green]FILE[/green]",
                file.display_name,
                format_size(file.size),
                file.last_modified[:19] if file.last_modified else "-",
            )

        console.print(table)
        console.print()
        console.print(f"[dim]{len(result.folders)} folders, {len(result.files)} files[/dim]")

    except APIError as e:
        console.print(f"[red]Error:[/red] {e}")
        raise SystemExit(1)


@files.command()
@click.option("--project", "-p", required=True, help="Project ID")
@click.option("--path", required=True, help="Remote file path")
@click.option("--output", "-o", help="Local output path (default: filename from path)")
def download(project: str, path: str, output: str | None):
    """Download a file from the project."""

    async def _download():
        client = FlowAPIClient()

        # Get signed URL
        console.print("[dim]Getting download URL...[/dim]")
        url = await client.get_download_url(project, path)

        # Determine output path
        output_path = output or Path(path).name

        # Download file
        console.print(f"[dim]Downloading to {output_path}...[/dim]")
        await client.download_file(url, output_path)

        return output_path

    try:
        output_path = asyncio.run(_download())
        console.print(f"[green]Downloaded:[/green] {output_path}")

    except APIError as e:
        console.print(f"[red]Error:[/red] {e}")
        raise SystemExit(1)


@files.command()
@click.option("--project", "-p", required=True, help="Project ID")
@click.option("--path", required=True, help="Remote destination path")
@click.argument("file", type=click.Path(exists=True))
def upload(project: str, path: str, file: str):
    """Upload a file to the project."""

    async def _upload():
        client = FlowAPIClient()

        # Detect content type
        content_type, _ = mimetypes.guess_type(file)
        content_type = content_type or "application/octet-stream"

        # Get signed URL
        console.print("[dim]Getting upload URL...[/dim]")
        url = await client.get_upload_url(project, path, content_type)

        # Upload file
        file_size = Path(file).stat().st_size
        console.print(f"[dim]Uploading {format_size(file_size)}...[/dim]")
        await client.upload_file(url, file, content_type)

    try:
        asyncio.run(_upload())
        console.print(f"[green]Uploaded:[/green] {file} -> {path}")

    except APIError as e:
        console.print(f"[red]Error:[/red] {e}")
        raise SystemExit(1)
    except FileNotFoundError:
        console.print(f"[red]Error:[/red] File not found: {file}")
        raise SystemExit(1)
