import argparse
import sys
import os
import requests
import time
from rich.console import Console
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, DownloadColumn, TransferSpeedColumn
from rich.panel import Panel
from rich.text import Text
from rich import print as rprint

# Default API URL
DEFAULT_API_URL = "https://my-repo-la5t.onrender.com"
API_BASE_URL = os.environ.get("SVC_API_URL", DEFAULT_API_URL).rstrip("/")

console = Console()

def validate_file(file_path):
    if not os.path.exists(file_path):
        console.print(f"[bold red]Error:[/bold red] File '{file_path}' does not exist.")
        sys.exit(1)
    
    if os.path.isdir(file_path):
        console.print(f"[bold red]Error:[/bold red] '{file_path}' is a directory. Only single files are supported.")
        sys.exit(1)
        
    if not os.access(file_path, os.R_OK):
        console.print(f"[bold red]Error:[/bold red] Permission denied reading '{file_path}'.")
        sys.exit(1)

def handle_upload(args):
    file_path = args.file_path
    validate_file(file_path)
    
    filename = os.path.basename(file_path)
    file_size = os.path.getsize(file_path)
    
    # 1. Init Upload with Spinner
    with console.status(f"[bold green]Initializing upload for[/bold green] {filename}...", spinner="dots"):
        try:
            init_payload = {"filename": filename, "size_bytes": file_size}
            res = requests.post(f"{API_BASE_URL}/api/upload", json=init_payload)
            res.raise_for_status()
            data = res.json()
            upload_url = data["upload_url"]
            file_uuid = data["file_uuid"]
        except Exception as e:
            console.print(f"[bold red]Server Error during init:[/bold red] {e}")
            sys.exit(1)

    # 2. Upload with Progress Bar
    try:
        with open(file_path, 'rb') as f:
            with Progress(
                SpinnerColumn(),
                TextColumn("[progress.description]{task.description}"),
                BarColumn(),
                TransferSpeedColumn(),
                DownloadColumn(),
                console=console
            ) as progress:
                task = progress.add_task(f"[cyan]Uploading[/cyan]", total=file_size)
                
                # Manual chunked upload logic to feed progress bar
                # Note: requests.put takes a data generator.
                # To bind it to rich progress, we wrap the file object.
                
                class ProgressFile:
                    def __init__(self, file):
                        self.file = file
                    def read(self, size):
                        data = self.file.read(size)
                        progress.update(task, advance=len(data))
                        return data

                put_res = requests.put(
                    upload_url, 
                    data=ProgressFile(f), 
                    headers={"Content-Type": "application/octet-stream"}
                )
                put_res.raise_for_status()

    except Exception as e:
        console.print(f"[bold red]Upload failed:[/bold red] {e}")
        sys.exit(1)
        
    # 3. Finalize
    with console.status("[bold green]Finalizing...[/bold green]", spinner="dots"):
        try:
            finalize_payload = {"file_uuid": file_uuid, "filename": filename}
            fin_res = requests.post(f"{API_BASE_URL}/api/finalize", json=finalize_payload)
            fin_res.raise_for_status()
            code = fin_res.json()["code"]
        except Exception as e:
            console.print(f"[bold red]Finalization failed:[/bold red] {e}")
            sys.exit(1)

    # Success Output
    panel = Panel(
        Text.assemble(
            ("Share Code: ", "bold cyan"),
            (f"{code}\n", "bold yellow reverse"),
            ("\nTo download run:\n", "dim"),
            (f"svc get {code}", "bold white")
        ),
        title="[bold green]Upload Successful[/bold green]",
        expand=False
    )
    console.print(panel)

def handle_get(args):
    code = args.code
    
    # 1. Resolve Code
    with console.status(f"[bold cyan]Looking up code[/bold cyan] {code}...", spinner="dots"):
        try:
            res = requests.get(f"{API_BASE_URL}/api/resolve/{code}")
            if res.status_code == 404:
                console.print(f"[bold red]Error:[/bold red] Code '{code}' not found or expired.")
                sys.exit(1)
            res.raise_for_status()
            data = res.json()
            download_url = data["download_url"]
            original_filename = data["filename"]
        except Exception as e:
            console.print(f"[bold red]Lookup failed:[/bold red] {e}")
            sys.exit(1)

    # Check existence
    if os.path.exists(original_filename):
        console.print(f"[bold yellow]Warning:[/bold yellow] '{original_filename}' already exists and will be overwritten.")

    # 2. Download with Progress
    try:
        with requests.get(download_url, stream=True) as r:
            r.raise_for_status()
            total_size = int(r.headers.get("content-length", 0))
            
            with Progress(
                SpinnerColumn(),
                TextColumn("[progress.description]{task.description}"),
                BarColumn(),
                TransferSpeedColumn(),
                DownloadColumn(),
                console=console
            ) as progress:
                task = progress.add_task(f"[green]Downloading {original_filename}[/green]", total=total_size)
                
                with open(original_filename, 'wb') as f:
                    for chunk in r.iter_content(chunk_size=8192):
                        f.write(chunk)
                        progress.update(task, advance=len(chunk))
                        
    except Exception as e:
        console.print(f"[bold red]Download failed:[/bold red] {e}")
        sys.exit(1)

    console.print(f"[bold green]✔[/bold green] Saved to [bold]{os.path.abspath(original_filename)}[/bold]")


def main():
    parser = argparse.ArgumentParser(description="sendviacli (svc) - Secure, fast, single-file sharing.")
    subparsers = parser.add_subparsers(dest="command")
    
    upload_parser = subparsers.add_parser("upload")
    upload_parser.add_argument("file_path")
    
    get_parser = subparsers.add_parser("get")
    get_parser.add_argument("code")
    
    args = parser.parse_args()
    
    if args.command == "upload":
        handle_upload(args)
    elif args.command == "get":
        handle_get(args)
    else:
        # Show help nicely
        console.print("[bold cyan]sendviacli (svc)[/bold cyan] - File sharing made simple.")
        console.print("Start by uploading a file: [bold]svc upload <file>[/bold]")
        sys.exit(0)

if __name__ == "__main__":
    main()
