# Copyright (c) CloudZero - ALL RIGHTS RESERVED - PROPRIETARY AND CONFIDENTIAL
# Unauthorized copying of this file and/or project, via any medium is strictly prohibited.
# Direct all questions to legal@cloudzero.com
#

"""
Documents Feature - V4 Implementation

This module provides CLI functionality for managing organization documents
using the v4 API with Okta authentication and pre-signed URLs.
"""

from pathlib import Path

from rich.console import Console
from rich.progress import BarColumn, Progress, SpinnerColumn, TextColumn, TimeRemainingColumn
from rich.table import Table

from src.api.v4_documents import (
    delete_document as api_delete_document,
)
from src.api.v4_documents import (
    download_file as api_download_file,
)
from src.api.v4_documents import (
    list_documents as api_list_documents,
)
from src.api.v4_documents import (
    upload_file as api_upload_file,
)
from src.exceptions import APIError
from src.utils.console import eprint

console = Console()


def list_documents_for_org(org_id: str, debug: bool = False) -> None:
    """
    List documents for an organization.

    Args:
        org_id: Organization ID
        debug: Whether to show debug information
    """
    try:
        if debug:
            console.print(f"\n[yellow]DEBUG: Listing documents for organization {org_id}[/yellow]")

        with Progress(
            SpinnerColumn(), TextColumn("[progress.description]{task.description}"), console=console, transient=True
        ) as progress:
            task = progress.add_task("Fetching documents...", total=None)
            documents = api_list_documents(org_id, debug=debug)
            progress.remove_task(task)

        if not documents:
            console.print(f"\n[yellow]No documents found for organization {org_id}[/yellow]")
            return

        # Create table for displaying documents
        table = Table(title=f"Documents for Organization: {org_id}")
        table.add_column("Filename", style="cyan", no_wrap=True)
        table.add_column("Size", justify="right", style="magenta")
        table.add_column("Last Modified", style="green")
        table.add_column("ETag", style="dim", max_width=20)

        # Add documents to table
        for doc in documents:
            # Format file size in human readable format
            size_bytes = doc.size
            if size_bytes < 1024:
                size_str = f"{size_bytes} B"
            elif size_bytes < 1024 * 1024:
                size_str = f"{size_bytes / 1024:.1f} KB"
            else:
                size_str = f"{size_bytes / (1024 * 1024):.1f} MB"

            # Format datetime (remove microseconds for cleaner display)
            last_modified = doc.last_modified
            if "." in last_modified:
                last_modified = last_modified.split(".")[0]
            if last_modified.endswith("Z"):
                last_modified = last_modified[:-1] + " UTC"

            table.add_row(
                doc.filename, size_str, last_modified, doc.etag[:16] + "..." if len(doc.etag) > 16 else doc.etag
            )

        console.print(f"\n[green]Found {len(documents)} documents:[/green]")
        console.print(table)

    except APIError as e:
        eprint(f"Error listing documents: {e}")
    except Exception as e:
        eprint(f"Unexpected error: {e}")
        if debug:
            console.print_exception()


def upload_document_to_org(org_id: str, file_path: str, debug: bool = False) -> None:
    """
    Upload a document to an organization.

    Args:
        org_id: Organization ID
        file_path: Path to file to upload
        debug: Whether to show debug information
    """
    try:
        file_path_obj = Path(file_path)

        if not file_path_obj.exists():
            eprint(f"File not found: {file_path}")
            return

        if not file_path_obj.is_file():
            eprint(f"Path is not a file: {file_path}")
            return

        file_size = file_path_obj.stat().st_size
        filename = file_path_obj.name

        console.print(f"\n[cyan]Uploading '{filename}' to organization {org_id}[/cyan]")
        console.print(f"File size: {file_size:,} bytes")

        if debug:
            console.print(f"[yellow]DEBUG: File path: {file_path}[/yellow]")

        # Upload with progress tracking
        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            BarColumn(bar_width=None),
            "[progress.percentage]{task.percentage:>3.1f}%",
            "•",
            TimeRemainingColumn(),
            console=console,
        ) as progress:
            upload_task = progress.add_task("Uploading...", total=file_size)

            def progress_callback(bytes_uploaded: int):
                progress.update(upload_task, completed=bytes_uploaded)

            success = api_upload_file(
                organization_id=org_id, file_path=file_path, progress_callback=progress_callback, debug=debug
            )

            if success:
                progress.update(upload_task, completed=file_size)

        console.print(f"[green]✅ Successfully uploaded '{filename}'[/green]")

    except APIError as e:
        eprint(f"Error uploading document: {e}")
    except Exception as e:
        eprint(f"Unexpected error: {e}")
        if debug:
            console.print_exception()


def get_document_from_org(org_id: str, dest_directory: str | None = None, debug: bool = False) -> None:
    """
    Get/download documents from an organization.

    Note: This is a general download interface. Since we don't know which specific
    file to download, we'll list available documents and let the user know how to download.

    Args:
        org_id: Organization ID
        dest_directory: Destination directory for downloads
        debug: Whether to show debug information
    """
    try:
        console.print(f"\n[cyan]Available documents in organization {org_id}:[/cyan]")

        # List documents first
        with Progress(
            SpinnerColumn(), TextColumn("[progress.description]{task.description}"), console=console, transient=True
        ) as progress:
            task = progress.add_task("Fetching documents...", total=None)
            documents = api_list_documents(org_id, debug=debug)
            progress.remove_task(task)

        if not documents:
            console.print(f"[yellow]No documents found for organization {org_id}[/yellow]")
            return

        # Show available documents
        table = Table(title="Available Documents")
        table.add_column("Filename", style="cyan")
        table.add_column("Size", justify="right", style="magenta")
        table.add_column("Download Command", style="green")

        for doc in documents:
            # Format file size
            size_bytes = doc.size
            if size_bytes < 1024:
                size_str = f"{size_bytes} B"
            elif size_bytes < 1024 * 1024:
                size_str = f"{size_bytes / 1024:.1f} KB"
            else:
                size_str = f"{size_bytes / (1024 * 1024):.1f} MB"

            # Create download command
            dest_arg = f" --dest {dest_directory}" if dest_directory else ""
            download_cmd = f"czops documents download {org_id} {doc.filename}{dest_arg}"

            table.add_row(doc.filename, size_str, download_cmd)

        console.print(table)
        console.print("\n[yellow]ℹ️  To download a specific document, use:[/yellow]")
        console.print("[dim]czops documents download <ORG-ID> <FILENAME> [--dest <DIRECTORY>][/dim]")

    except APIError as e:
        eprint(f"Error listing documents: {e}")
    except Exception as e:
        eprint(f"Unexpected error: {e}")
        if debug:
            console.print_exception()


def download_document_from_org(
    org_id: str, filename: str, dest_directory: str | None = None, debug: bool = False
) -> None:
    """
    Download a specific document from an organization.

    Args:
        org_id: Organization ID
        filename: Document filename to download
        dest_directory: Destination directory for download
        debug: Whether to show debug information
    """
    try:
        console.print(f"\n[cyan]Downloading '{filename}' from organization {org_id}[/cyan]")

        if debug:
            console.print(f"[yellow]DEBUG: Destination: {dest_directory or 'current directory'}[/yellow]")

        with Progress(
            SpinnerColumn(), TextColumn("[progress.description]{task.description}"), console=console, transient=True
        ) as progress:
            task = progress.add_task("Downloading...", total=None)

            local_path = api_download_file(
                organization_id=org_id, filename=filename, destination_path=dest_directory, debug=debug
            )

            progress.remove_task(task)

        console.print(f"[green]✅ Successfully downloaded to: {local_path}[/green]")

    except APIError as e:
        if "not found" in str(e).lower():
            eprint(f"Document '{filename}' not found in organization {org_id}")
            console.print(f"\n[yellow]💡 Use 'czops documents list {org_id}' to see available documents[/yellow]")
        else:
            eprint(f"Error downloading document: {e}")
    except Exception as e:
        eprint(f"Unexpected error: {e}")
        if debug:
            console.print_exception()


def delete_document_from_org(org_id: str, filename: str, debug: bool = False) -> None:
    """
    Delete a document from an organization.

    Args:
        org_id: Organization ID
        filename: Document filename to delete
        debug: Whether to show debug information
    """
    try:
        console.print(f"\n[red]Deleting '{filename}' from organization {org_id}[/red]")

        # Confirm deletion
        if (
            not console.input("[yellow]Are you sure you want to delete this document? [y/N]: [/yellow]")
            .lower()
            .startswith("y")
        ):
            console.print("[dim]Deletion cancelled.[/dim]")
            return

        with Progress(
            SpinnerColumn(), TextColumn("[progress.description]{task.description}"), console=console, transient=True
        ) as progress:
            task = progress.add_task("Deleting...", total=None)

            success = api_delete_document(organization_id=org_id, filename=filename, debug=debug)

            progress.remove_task(task)

        if success:
            console.print(f"[green]✅ Successfully deleted '{filename}'[/green]")

    except APIError as e:
        if "not found" in str(e).lower():
            eprint(f"Document '{filename}' not found in organization {org_id}")
            console.print(f"\n[yellow]💡 Use 'czops documents list {org_id}' to see available documents[/yellow]")
        else:
            eprint(f"Error deleting document: {e}")
    except Exception as e:
        eprint(f"Unexpected error: {e}")
        if debug:
            console.print_exception()
