"""Interactive CLI for MixMail."""

from __future__ import annotations

import json
from pathlib import Path

from rich.console import Console
from rich.markdown import Markdown
from rich.panel import Panel
from rich.text import Text

from email_assistant.agent import EmailAgent
from email_assistant.config import (
    get_setup_paths,
    import_mail_credentials_file,
    save_llm_base_url,
    save_mail_credentials,
)

console = Console()


BANNER = r"""
 ███╗   ███╗██╗██╗  ██╗███╗   ███╗ █████╗ ██╗██╗     
 ████╗ ████║██║╚██╗██╔╝████╗ ████║██╔══██╗██║██║     
 ██╔████╔██║██║ ╚███╔╝ ██╔████╔██║███████║██║██║     
 ██║╚██╔╝██║██║ ██╔██╗ ██║╚██╔╝██║██╔══██║██║██║     
 ██║ ╚═╝ ██║██║██╔╝ ██╗██║ ╚═╝ ██║██║  ██║██║███████╗
 ╚═╝     ╚═╝╚═╝╚═╝  ╚═╝╚═╝     ╚═╝╚═╝  ╚═╝╚═╝╚══════╝
              MIXMAIL
"""


HELP_TEXT = """\
## How to use

Type **any natural-language query** about your emails. Examples:

- `find emails from recruiters last week`
- `show unread emails with attachments`
- `summarize emails from professor Smith`
- `find emails mentioning visa sponsorship`
- `list job interview emails`
- `summarize the latest thread from Amazon`

### Commands
| Command | Action |
|---------|--------|
| `help`  | Show this help message |
| `reset` | Clear conversation history |
| `/llm_url` | Set local LLM server URL (OpenAI-compatible) |
| `/mail_creds` | Paste Google OAuth JSON or import a credentials file |
| `/setup` | Show MixMail config file locations |
| `quit` / `exit` | Exit the assistant |
"""

LLM_URL_GUIDE = """\
Set your local LLM server URL.

Examples:
- `http://localhost:1200/v1`
- `http://127.0.0.1:1234/v1`
- `http://localhost:1200/v1/chat/completions` (accepted and normalized)

Type `cancel` to go back.
"""

MAIL_CREDS_GUIDE = """\
Paste the full Google OAuth desktop-app JSON.

Options:
- Paste raw JSON, then enter a blank line to save.
- Or paste a file path like `C:/path/to/client_secret.json`.
- Or type `file:C:/path/to/client_secret.json` to import an existing file.
- Or type `cancel` to go back.
"""


def _looks_like_credentials_path(value: str) -> bool:
    """Return True if the provided input looks like an existing JSON file path."""
    if not value:
        return False
    candidate = value[5:].strip() if value.lower().startswith("file:") else value
    return candidate.lower().endswith(".json") and Path(candidate).expanduser().exists()


def print_banner() -> None:
    """Display the startup banner."""
    console.print(
        Panel(
            Text(BANNER, style="bold cyan"),
            border_style="bright_blue",
            subtitle="Type [bold green]help[/] for tips · [bold red]quit[/] to exit",
        )
    )


def create_agent() -> EmailAgent | None:
    """Create an agent instance, showing configuration errors inline."""
    try:
        return EmailAgent()
    except ValueError as exc:
        console.print(f"\n[bold red]Configuration error:[/] {exc}")
        console.print(
            "\n[dim]Use [cyan]/mail_creds[/cyan] and [cyan]/llm_url[/cyan] "
            "inside MixMail to finish setup, or create the config files manually.[/dim]\n"
        )
        return None


def handle_llm_url_command() -> None:
    """Prompt the user for the local LLM base URL and save it."""
    console.print(Markdown(LLM_URL_GUIDE))
    llm_url = console.input("[bold blue]llm_url ❯[/] ").strip()
    if not llm_url or llm_url.lower() == "cancel":
        console.print("[dim]Cancelled.[/dim]\n")
        return

    try:
        env_path = save_llm_base_url(llm_url)
    except ValueError as exc:
        console.print(f"[bold red]Error:[/] {exc}\n")
        return

    console.print(
        f"[bold green]Saved local LLM URL.[/] Config updated at [cyan]{env_path}[/cyan].\n"
    )


def handle_mail_creds_command() -> None:
    """Prompt the user to paste or import Google OAuth credentials JSON."""
    console.print(Markdown(MAIL_CREDS_GUIDE))
    first_line = console.input("[bold blue]mail_creds ❯[/] ").strip()
    if not first_line or first_line.lower() == "cancel":
        console.print("[dim]Cancelled.[/dim]\n")
        return

    if _looks_like_credentials_path(first_line):
        source_path = (
            first_line[5:].strip()
            if first_line.lower().startswith("file:")
            else first_line
        )
        try:
            destination = import_mail_credentials_file(source_path)
        except FileNotFoundError as exc:
            console.print(f"[bold red]Error:[/] {exc}\n")
            return
        console.print(
            f"[bold green]Imported Gmail credentials.[/] Saved to [cyan]{destination}[/cyan].\n"
        )
        return

    lines = [first_line]
    while True:
        next_line = console.input("[bold blue]...[/] ")
        if not next_line.strip():
            break
        lines.append(next_line)

    credentials_text = "\n".join(lines)
    try:
        json.loads(credentials_text)
    except json.JSONDecodeError as exc:
        console.print(f"[bold red]Invalid JSON:[/] {exc}\n")
        return

    destination = save_mail_credentials(credentials_text)
    console.print(
        f"[bold green]Saved Gmail credentials.[/] Saved to [cyan]{destination}[/cyan].\n"
    )


def handle_setup_command() -> None:
    """Show MixMail's active config file locations."""
    paths = get_setup_paths()
    message = (
        f"[bold]MixMail config home:[/] [cyan]{paths['app_home']}[/cyan]\n"
        f"[bold]Environment file:[/] [cyan]{paths['env_path']}[/cyan]\n"
        f"[bold]Local LLM URL:[/] [cyan]{paths['llm_base_url']}[/cyan]\n"
        f"[bold]Gmail credentials:[/] [cyan]{paths['credentials_path']}[/cyan]\n"
        f"[bold]OAuth token:[/] [cyan]{paths['token_path']}[/cyan]"
    )
    console.print(Panel(message, border_style="blue", title="Setup"))
    console.print()


def main() -> None:
    """Run the interactive CLI loop."""
    print_banner()
    agent = create_agent()
    if agent is not None:
        console.print(
            "\n[bold green]✓[/] Agent ready. "
            "MixMail is connected to Gmail & the local LLM.\n"
        )

    while True:
        try:
            user_input = console.input("[bold blue]You ❯[/] ").strip()
        except (EOFError, KeyboardInterrupt):
            console.print("\n[dim]Goodbye! 👋[/dim]")
            break

        if not user_input:
            continue

        lower = user_input.lower()
        if lower in {"quit", "exit", "q"}:
            console.print("[dim]Goodbye! 👋[/dim]")
            break
        if lower == "help":
            console.print(Markdown(HELP_TEXT))
            continue
        if lower == "/llm_url":
            handle_llm_url_command()
            agent = create_agent()
            if agent is not None:
                console.print(
                    "[bold green]✓[/] MixMail is ready after updating the local LLM URL.\n"
                )
            continue
        if lower == "/mail_creds":
            handle_mail_creds_command()
            agent = create_agent()
            if agent is not None:
                console.print(
                    "[bold green]✓[/] MixMail is ready after updating Gmail credentials.\n"
                )
            continue
        if lower == "/setup":
            handle_setup_command()
            continue
        if lower.startswith("/"):
            console.print(
                "[bold yellow]Unknown command.[/] "
                "Use [cyan]help[/cyan] to see available commands.\n"
            )
            continue
        if lower == "reset":
            if agent is None:
                console.print("[dim]MixMail is not configured yet.[/dim]\n")
            else:
                agent.reset()
                console.print("[dim]Conversation history cleared.[/dim]\n")
            continue

        if agent is None:
            console.print(
                "[dim]Finish setup with [cyan]/mail_creds[/cyan] and [cyan]/llm_url[/cyan], then try again.[/dim]\n"
            )
            continue

        with console.status("[bold cyan]Thinking…[/]", spinner="dots"):
            try:
                response = agent.ask(user_input)
            except Exception as exc:  # noqa: BLE001
                console.print(f"\n[bold red]Error:[/] {exc}\n")
                continue

        console.print()
        console.print(
            Panel(
                Markdown(response),
                border_style="green",
                title="[bold green]Agent[/]",
                title_align="left",
                padding=(1, 2),
            )
        )
        console.print()


if __name__ == "__main__":
    main()