"""Authentication CLI for Platform-2Step MCP.

This CLI provides interactive authentication for the MCP server, which runs
non-interactively via stdio transport. The CLI handles OAuth 2.0 Device Flow
authentication and caches tokens for use by the MCP server.

Usage:
    platform-mcp-auth login   # Authenticate with device flow
    platform-mcp-auth status  # Check token status
    platform-mcp-auth logout  # Clear cached tokens
"""

import argparse
import sys
from datetime import datetime

from .auth import (
    AuthClient,
    AuthError,
    DeviceFlowDeniedError,
    DeviceFlowExpiredError,
    InvalidCompletionCodeError,
    TokenStorage,
)
from .config import Settings


def _get_bff_url() -> str:
    """Get BFF URL from environment or raise helpful error."""
    try:
        settings = Settings()
        return settings.bff_url
    except Exception as e:
        print(f"Configuration error: {e}", file=sys.stderr)
        print(
            "\nSet the environment variable:",
            file=sys.stderr,
        )
        print(
            "  export PLATFORM_2STEPS_BFF_URL=https://ap-api.agendaprodev.com/platform-2steps-bff",
            file=sys.stderr,
        )
        sys.exit(1)


def cmd_login(args: argparse.Namespace) -> int:
    """Handle the login command - authenticate with device flow."""
    bff_url = _get_bff_url()

    print(f"Connecting to {bff_url}...")

    auth_client = AuthClient(bff_url=bff_url)

    try:
        # Check if already authenticated with valid tokens
        storage = TokenStorage()
        existing_tokens = storage.load()
        if existing_tokens and not existing_tokens.is_expired():
            print("\nYou are already authenticated.")
            _print_token_info(existing_tokens)

            if not args.force:
                print("\nUse --force to re-authenticate.")
                return 0

            print("\nRe-authenticating...")
            # Clear cached tokens so authenticate() starts fresh
            storage.clear()
            auth_client.clear_tokens()

        # Perform device flow authentication
        tokens = auth_client.authenticate()

        print("\n" + "=" * 60)
        print("Authentication successful!")
        print("=" * 60)
        _print_token_info(tokens)
        print("\nThe MCP server will now use these cached tokens.")
        print("You can start Claude Desktop or other MCP clients.")

        return 0

    except DeviceFlowExpiredError:
        print("\nError: The device code expired. Please try again.", file=sys.stderr)
        return 1
    except DeviceFlowDeniedError:
        print("\nError: Authorization was denied.", file=sys.stderr)
        return 1
    except InvalidCompletionCodeError:
        print("\nError: Invalid completion code. Please try again.", file=sys.stderr)
        return 1
    except AuthError as e:
        print(f"\nAuthentication error: {e}", file=sys.stderr)
        return 1
    except KeyboardInterrupt:
        print("\n\nAuthentication cancelled.", file=sys.stderr)
        return 130
    finally:
        auth_client.close()


def cmd_status(args: argparse.Namespace) -> int:
    """Handle the status command - check token status."""
    storage = TokenStorage()
    tokens = storage.load()

    if tokens is None:
        print("Not authenticated.")
        print("\nRun 'platform-mcp-auth login' to authenticate.")
        return 1

    if tokens.is_expired():
        print("Token expired.")
        _print_token_info(tokens)
        print("\nRun 'platform-mcp-auth login' to re-authenticate.")
        return 1

    print("Authenticated.")
    _print_token_info(tokens)

    if tokens.is_expiring_soon(minutes=30):
        print("\nWarning: Token will expire soon. Consider re-authenticating.")

    return 0


def cmd_logout(args: argparse.Namespace) -> int:
    """Handle the logout command - clear cached tokens."""
    storage = TokenStorage()

    if not storage.exists():
        print("No stored tokens found.")
        return 0

    # Clear local tokens
    storage.clear()
    print("Tokens cleared successfully.")

    return 0


def _print_token_info(tokens) -> None:
    """Print token information."""
    now = datetime.utcnow()
    expires_at = tokens.expires_at

    if expires_at > now:
        remaining = expires_at - now
        hours, remainder = divmod(int(remaining.total_seconds()), 3600)
        minutes, seconds = divmod(remainder, 60)

        if hours > 0:
            time_str = f"{hours}h {minutes}m"
        elif minutes > 0:
            time_str = f"{minutes}m {seconds}s"
        else:
            time_str = f"{seconds}s"

        print(f"\nToken expires in: {time_str}")
    else:
        print("\nToken status: Expired")

    if tokens.scope:
        print(f"Scope: {tokens.scope}")
    if tokens.id_token:
        print("Has ID token: Yes")
    print(f"Has refresh token: {'Yes' if tokens.refresh_token else 'No'}")


def main() -> None:
    """Main entry point for the authentication CLI."""
    parser = argparse.ArgumentParser(
        prog="platform-mcp-auth",
        description="Authentication CLI for Platform-2Step MCP",
        epilog=(
            "This CLI handles interactive authentication for the MCP server.\n"
            "Run 'platform-mcp-auth login' before starting the MCP server."
        ),
    )

    subparsers = parser.add_subparsers(
        dest="command",
        title="commands",
        description="Available commands",
        metavar="COMMAND",
    )

    # Login command
    login_parser = subparsers.add_parser(
        "login",
        help="Authenticate with device flow",
        description=(
            "Start the OAuth 2.0 Device Flow authentication. "
            "You will be prompted to visit a URL and enter a code."
        ),
    )
    login_parser.add_argument(
        "--force",
        "-f",
        action="store_true",
        help="Force re-authentication even if valid tokens exist",
    )

    # Status command
    subparsers.add_parser(
        "status",
        help="Check token status",
        description="Check if you have valid cached tokens.",
    )

    # Logout command
    subparsers.add_parser(
        "logout",
        help="Clear cached tokens",
        description="Remove cached tokens from disk.",
    )

    args = parser.parse_args()

    if args.command is None:
        parser.print_help()
        sys.exit(0)

    # Dispatch to command handler
    handlers = {
        "login": cmd_login,
        "status": cmd_status,
        "logout": cmd_logout,
    }

    handler = handlers.get(args.command)
    if handler:
        sys.exit(handler(args))
    else:
        parser.print_help()
        sys.exit(1)


if __name__ == "__main__":
    main()
