"""Organization management commands."""

import os
from pathlib import Path
from typing import Annotated

import typer
from rich.table import Table

from paracord.utils.console import (
    console,
    print_header,
    print_success,
    print_error,
    print_warning,
    print_info,
)
from paracord.auth.config import (
    get_current_environment,
    get_authenticated_orgs,
    get_org_for_path,
    set_org_for_path,
    clear_org_for_path,
    get_org_credentials,
    get_user_email,
)

org_app = typer.Typer(
    name="org",
    help="Manage organizations for the current directory.",
    invoke_without_command=True,
)


def interactive_org_picker(orgs: dict, env: str) -> str | None:
    """Interactively pick an organization from the list.

    Returns the selected org_id or None if cancelled.
    """
    if not orgs:
        return None

    org_list = [(org_id, creds["name"]) for org_id, creds in orgs.items()]

    console.print("\n[bold]Select an organization for this directory:[/bold]\n")

    for i, (org_id, name) in enumerate(org_list, 1):
        console.print(f"  [cyan]{i}[/cyan]. {name}")

    console.print(f"  [dim]0[/dim]. Cancel\n")

    try:
        choice = typer.prompt("Enter number", type=int, default=1)

        if choice == 0:
            return None

        if 1 <= choice <= len(org_list):
            return org_list[choice - 1][0]  # Return org_id

        print_error(f"Invalid choice: {choice}")
        return None
    except (KeyboardInterrupt, typer.Abort):
        return None


@org_app.callback(invoke_without_command=True)
def org_default(ctx: typer.Context) -> None:
    """Show or set the organization for the current directory.

    If no org is set for this directory, prompts to select one interactively.
    """
    # If a subcommand was invoked, don't run this callback logic
    if ctx.invoked_subcommand is not None:
        return

    env = get_current_environment()
    cwd = Path.cwd()

    # Check if there's already an org set for this directory
    org_id = get_org_for_path(cwd)

    if org_id:
        org_creds = get_org_credentials(env, org_id)
        if org_creds:
            print_header("Current Organization")
            console.print(f"  Organization: [bold]{org_creds['name']}[/bold]")
            console.print(f"  Directory: {cwd}")
            if env == "development":
                console.print(f"  Environment: {env}")
            return
        else:
            # Org is mapped but credentials are gone - clear the mapping
            print_warning(f"Organization credentials not found for mapped org: {org_id}")
            clear_org_for_path(cwd)

    # No org set - check if any orgs are authenticated
    orgs = get_authenticated_orgs(env)

    if not orgs:
        print_warning("No organizations authenticated.")
        console.print("  Run [command]paracord login[/command] to authenticate with an organization.")
        raise typer.Exit(1)

    # If only one org, use it automatically
    if len(orgs) == 1:
        org_id, org_creds = next(iter(orgs.items()))
        set_org_for_path(cwd, org_id)
        print_success(f"Using organization: {org_creds['name']}")
        console.print(f"  Directory: {cwd}")
        return

    # Multiple orgs - interactive picker
    selected_org_id = interactive_org_picker(orgs, env)

    if selected_org_id:
        set_org_for_path(cwd, selected_org_id)
        org_creds = get_org_credentials(env, selected_org_id)
        print_success(f"Set organization for this directory: {org_creds['name']}")
    else:
        print_warning("No organization selected.")
        raise typer.Exit(1)


@org_app.command(name="list")
def list_orgs() -> None:
    """List all authenticated organizations."""
    env = get_current_environment()
    orgs = get_authenticated_orgs(env)
    user_email = get_user_email()
    cwd = Path.cwd()
    current_org_id = get_org_for_path(cwd)

    print_header("Authenticated Organizations")

    if user_email:
        console.print(f"User: {user_email}")

    if env == "development":
        console.print(f"Environment: {env}")

    if not orgs:
        console.print("\n[warning]No organizations authenticated.[/warning]")
        console.print("  Run [command]paracord login[/command] to authenticate.")
        return

    console.print()

    table = Table(border_style="dim")
    table.add_column("Organization", style="bold")
    table.add_column("Current", justify="center")

    for org_id, creds in orgs.items():
        is_current = org_id == current_org_id
        current_marker = "[green]*[/green]" if is_current else ""
        table.add_row(creds["name"], current_marker)

    console.print(table)

    if current_org_id:
        console.print(f"\n[dim]* = active for current directory[/dim]")
    else:
        console.print(f"\n[dim]Run [command]paracord org[/command] to set organization for this directory[/dim]")


@org_app.command(name="set")
def set_org(
    name: Annotated[
        str,
        typer.Argument(help="Organization name to set for this directory"),
    ],
) -> None:
    """Set the organization for the current directory."""
    env = get_current_environment()
    orgs = get_authenticated_orgs(env)
    cwd = Path.cwd()

    if not orgs:
        print_error("No organizations authenticated.")
        console.print("  Run [command]paracord login[/command] to authenticate first.")
        raise typer.Exit(1)

    # Find org by name (case-insensitive)
    name_lower = name.lower()
    matching_org = None

    for org_id, creds in orgs.items():
        if creds["name"].lower() == name_lower:
            matching_org = (org_id, creds)
            break

    if not matching_org:
        # Try partial match
        for org_id, creds in orgs.items():
            if name_lower in creds["name"].lower():
                matching_org = (org_id, creds)
                break

    if not matching_org:
        print_error(f"Organization not found: {name}")
        console.print("\nAuthenticated organizations:")
        for creds in orgs.values():
            console.print(f"  - {creds['name']}")
        raise typer.Exit(1)

    org_id, org_creds = matching_org
    set_org_for_path(cwd, org_id)
    print_success(f"Set organization for this directory: {org_creds['name']}")


@org_app.command(name="clear")
def clear_org() -> None:
    """Clear the organization setting for the current directory."""
    cwd = Path.cwd()

    if clear_org_for_path(cwd):
        print_success("Cleared organization for this directory.")
    else:
        print_info("No organization was set for this directory.")
