import time
from typing import Optional

import requests
import typer

from ..utils.config import (
    API_BASE_URL,
    ID_STYLE,
    MAX_POLL_ATTEMPTS,
    POLL_INTERVAL,
    clear_organization_id,
)
from ..utils.utils import (
    get_authenticated_session,
    handle_http_error,
    open_browser,
    prompt,
    save_cookie,
    save_api_key,
    print_success,
    print_error,
    print_warning,
    print_info,
)

app = typer.Typer()


def signin(
    api_key: Optional[str] = typer.Option(None, "--api-key", "-k", help="API key for non-interactive signin"),
    email: Optional[str] = typer.Option(None, "--email", "-e", help="Email for non-interactive signin"),
    password: Optional[str] = typer.Option(None, "--password", "-p", help="Password for non-interactive signin (requires --email)"),
):
    """Sign in to the API."""
    try:
        session = get_authenticated_session()
        response = session.get(f"{API_BASE_URL}/v1/auth/session")
        if response.status_code == 200:
            print_success("Already signed in")
            return

        # Non-interactive: API key
        if api_key:
            signin_api_key(api_key)
            return

        # Non-interactive: email/password
        if email and password:
            signin_email_password(email, password)
            return

        if email and not password:
            print_error("--password is required when using --email")
            raise typer.Exit(code=1)

        if password and not email:
            print_error("--email is required when using --password")
            raise typer.Exit(code=1)

        # Interactive: prompt for authentication method
        print_info("Authentication methods:")
        print_info("  1: Web browser (default)")
        print_info("  2: Email/Password")
        print_info("  3: API Key")
        auth_method = prompt(
            "Choose authentication method [1/2/3]",
            default="1",
            validation=None
        )

        if auth_method == "1":
            signin_web()
            return
        elif auth_method == "3":
            signin_api_key()
            return

        # Default to email/password (interactive)
        email = prompt("Email")
        password = prompt("Password", hide_input=True)
        signin_email_password(email, password)
    except requests.HTTPError as e:
        handle_http_error(e)


def signin_email_password(email: str, password: str):
    """Sign in using email and password."""
    response = requests.post(
        f"{API_BASE_URL}/v1/auth/signin",
        json={"email": email, "password": password},
    )
    response.raise_for_status()
    if response.status_code == 204:
        set_cookie = response.headers.get("Set-Cookie")
        if set_cookie:
            cookie_value = set_cookie.split(";")[0]
            save_cookie(cookie_value)

            print_success("Successfully signed in!")
        else:
            print_warning("No Set-Cookie header received")
    else:
        try:
            print_error(response.json())
        except requests.exceptions.JSONDecodeError:
            print_error(f"Server response (not JSON): {response.text}")
            print_error(
                f"Status code: '[{ID_STYLE}]{response.status_code}[/{ID_STYLE}]'"
            )


def signin_api_key(api_key: str = None):
    """Sign in to the API using an API key."""
    try:
        if not api_key:
            api_key = prompt("Enter your API key")

        # Test the API key by making a request
        session = requests.Session()
        session.headers["Authorization"] = f"Bearer {api_key}"
        response = session.get(f"{API_BASE_URL}/v1/auth/session")
        response.raise_for_status()

        if response.status_code == 200:
            # Clear any existing cookie and save the API key
            save_cookie("")
            save_api_key(api_key)

            print_success("Successfully signed in with API key!")
        else:
            print_error("Invalid API key")
    except requests.HTTPError as e:
        print_error("Invalid API key or authentication failed")
        handle_http_error(e)
    except Exception as e:
        print_error(str(e))


def signout():
    """Sign out of the API."""
    try:
        get_authenticated_session()
        save_cookie("")
        save_api_key("")
        clear_organization_id()

        print_success("Successfully signed out")
    except requests.HTTPError as e:
        handle_http_error(e)


def signin_web():
    """Sign in to the API via browser."""
    try:
        response = requests.post(f"{API_BASE_URL}/v1/auth/cli-login")
        response.raise_for_status()
        data = response.json()

        login_token = data.get("login_token")
        login_url = data.get("login_url")
        if not login_token or not login_url:
            print_error("Server did not return a login token or URL.")
            return

        open_browser(login_url)
        print_info(
            "Please complete the login in your browser. Waiting for completion..."
        )

        for _ in range(MAX_POLL_ATTEMPTS):  # Poll for up to 2 minutes
            poll = requests.get(
                f"{API_BASE_URL}/v1/auth/cli-check-login", params={"token": login_token}
            )
            poll.raise_for_status()
            poll_data = poll.json()
            if poll_data.get("status") == "complete" and poll_data.get(
                "session_cookie"
            ):
                save_cookie(f"appSession={poll_data['session_cookie']}")
    
                print_success("Successfully signed in!")
                return
            time.sleep(POLL_INTERVAL)
        print_warning("Login not completed in time. Please try again.")
    except requests.HTTPError as e:
        handle_http_error(e)
    except Exception as e:
        print_error(str(e))
