"""CLI for Mistake Journal."""

import sys
from datetime import datetime, timedelta
from pathlib import Path

import click
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.prompt import Prompt, IntPrompt, Confirm

from .journal import Journal
from .models import MISTAKE_TAGS

console = Console()


@click.group()
@click.version_option()
def main():
    """Mistake Journal - Learn from your trading mistakes."""
    pass


@main.command()
@click.option("--symbol", "-s", help="Asset symbol")
@click.option("--action", "-a", type=click.Choice(["buy", "sell"]))
@click.option("--price", "-p", type=float)
@click.option("--size", type=float, help="Position size in USD")
@click.option("--emotion", "-e", type=int, help="Emotion level 1-5")
def log(symbol, action, price, size, emotion):
    """Log a new trade entry."""
    journal = Journal()

    console.print(Panel("[bold]NEW TRADE ENTRY[/bold]", style="cyan"))

    # Gather info interactively if not provided
    if not symbol:
        symbol = Prompt.ask("Symbol")
    if not action:
        action = Prompt.ask("Action", choices=["buy", "sell"])
    if not price:
        price = float(Prompt.ask("Entry price"))
    if not size:
        size = float(Prompt.ask("Position size ($)"))

    console.print("\n[bold]PRE-TRADE STATE[/bold]")
    console.print("[dim]How are you feeling? 1=Fearful 2=Anxious 3=Neutral 4=Confident 5=Euphoric[/dim]")

    if not emotion:
        emotion = IntPrompt.ask("Emotion level", default=3)
    emotion = max(1, min(5, emotion))

    reasoning = Prompt.ask("Why did you enter this trade?")
    had_plan = Confirm.ask("Did you have a plan before entering?", default=False)
    stop_loss = Confirm.ask("Stop loss set?", default=False)
    take_profit = Confirm.ask("Take profit target?", default=False)

    # Tags
    console.print("\n[dim]Available tags:[/dim]")
    for tag, desc in list(MISTAKE_TAGS.items())[:5]:
        console.print(f"  [cyan]{tag}[/cyan]: {desc}")
    console.print("  [dim]...and more. Enter custom tags too.[/dim]")

    tags_input = Prompt.ask("Tags (comma-separated)", default="")
    tags = [t.strip().lower() for t in tags_input.split(",") if t.strip()]

    notes = Prompt.ask("Notes", default="")

    # Log it
    trade_id = journal.log_trade(
        symbol=symbol,
        action=action,
        price=price,
        size=size,
        emotion=emotion,
        reasoning=reasoning,
        had_plan=had_plan,
        stop_loss_set=stop_loss,
        take_profit_set=take_profit,
        tags=tags,
        notes=notes,
    )

    console.print(f"\n[green]Entry logged! ID: {trade_id}[/green]")
    console.print(f"Close this trade later with: [cyan]mistake-journal close --id {trade_id}[/cyan]")


@main.command()
@click.option("--id", "trade_id", type=int, required=True, help="Trade ID to close")
def close(trade_id):
    """Close an open trade."""
    journal = Journal()
    trade = journal.get_trade(trade_id)

    if not trade:
        console.print(f"[red]Trade #{trade_id} not found[/red]")
        return

    if trade.is_closed:
        console.print(f"[yellow]Trade #{trade_id} is already closed[/yellow]")
        return

    console.print(Panel(f"[bold]CLOSING TRADE #{trade_id} ({trade.symbol})[/bold]", style="cyan"))
    console.print(f"Entry: ${trade.entry_price:,.2f} | Size: ${trade.size:,.2f}")

    exit_price = float(Prompt.ask("Exit price"))

    # Calculate P&L preview
    if trade.action == "buy":
        pnl = trade.size * (exit_price - trade.entry_price) / trade.entry_price
        pnl_pct = (exit_price - trade.entry_price) / trade.entry_price * 100
    else:
        pnl = trade.size * (trade.entry_price - exit_price) / trade.entry_price
        pnl_pct = (trade.entry_price - exit_price) / trade.entry_price * 100

    color = "green" if pnl > 0 else "red"
    console.print(f"\n[{color}]OUTCOME: ${pnl:+,.2f} ({pnl_pct:+.1f}%)[/{color}]")

    console.print("\n[bold]POST-TRADE REFLECTION[/bold]")
    reflection = Prompt.ask("What went wrong (or right)?")
    lesson = Prompt.ask("Lesson learned")

    journal.close_trade(trade_id, exit_price, reflection, lesson)
    console.print(f"\n[green]Trade closed and saved![/green]")


@main.command()
def analyze():
    """Analyze your mistake patterns."""
    journal = Journal()
    analysis = journal.analyze()

    console.print(Panel("[bold]MISTAKE PATTERN ANALYSIS[/bold]", style="cyan"))

    console.print(f"\nTotal trades: {analysis.total_trades}")
    console.print(f"Win rate: {analysis.win_rate*100:.0f}%")
    console.print(f"Avg winner: [green]${analysis.avg_winner:+,.2f}[/green]")
    console.print(f"Avg loser: [red]${analysis.avg_loser:,.2f}[/red]")

    if analysis.top_mistakes:
        console.print("\n[bold]TOP MISTAKE PATTERNS:[/bold]")
        for i, mistake in enumerate(analysis.top_mistakes, 1):
            console.print(f"\n{i}. [red]{mistake.tag.upper()}[/red] ({mistake.trade_count} trades, {mistake.loss_rate*100:.0f}% loss rate)")
            console.print(f"   Avg loss: ${mistake.avg_loss:,.2f}")

    if analysis.win_rate_with_plan and analysis.win_rate_without_plan:
        console.print(f"\n[dim]With plan: {analysis.win_rate_with_plan*100:.0f}% win rate[/dim]")
        console.print(f"[dim]Without plan: {analysis.win_rate_without_plan*100:.0f}% win rate[/dim]")

    if analysis.recommendations:
        console.print("\n[bold]RECOMMENDATIONS:[/bold]")
        for rec in analysis.recommendations:
            console.print(f"  • {rec}")


@main.command()
@click.option("--closed", is_flag=True, help="Show only closed trades")
@click.option("--open", "open_only", is_flag=True, help="Show only open trades")
def review(closed, open_only):
    """Review your journal entries."""
    journal = Journal()
    trades = journal.get_trades(closed_only=closed, open_only=open_only)

    if not trades:
        console.print("[yellow]No trades found[/yellow]")
        return

    table = Table(title="Trade Journal")
    table.add_column("ID", style="cyan")
    table.add_column("Symbol")
    table.add_column("Action")
    table.add_column("Entry")
    table.add_column("Exit")
    table.add_column("P&L")
    table.add_column("Tags")

    for trade in trades[-20:]:  # Last 20
        pnl_str = ""
        if trade.is_closed:
            color = "green" if trade.pnl > 0 else "red"
            pnl_str = f"[{color}]${trade.pnl:+,.2f}[/{color}]"

        table.add_row(
            str(trade.id),
            trade.symbol,
            trade.action,
            f"${trade.entry_price:,.2f}",
            f"${trade.exit_price:,.2f}" if trade.exit_price else "-",
            pnl_str,
            ", ".join(trade.tags[:3]),
        )

    console.print(table)


@main.command()
def tags():
    """Show available mistake tags."""
    console.print("\n[bold]Available Mistake Tags[/bold]\n")

    table = Table()
    table.add_column("Tag", style="cyan")
    table.add_column("Description")

    for tag, desc in MISTAKE_TAGS.items():
        table.add_row(tag, desc)

    console.print(table)


@main.command()
def stats():
    """Quick statistics."""
    journal = Journal()
    analysis = journal.analyze()

    console.print(f"\n[bold]Quick Stats[/bold]")
    console.print(f"  Total trades: {analysis.total_trades}")
    console.print(f"  Closed: {analysis.closed_trades}")
    console.print(f"  Win rate: {analysis.win_rate*100:.0f}%")


@main.command()
@click.option("--week", is_flag=True, help="Report for last 7 days")
@click.option("--month", is_flag=True, help="Report for last 30 days")
def report(week, month):
    """Generate performance report for a period."""
    journal = Journal()

    if not week and not month:
        week = True  # Default to weekly

    now = datetime.now()
    if week:
        period_days = 7
        period_name = "Weekly"
        start_date = now - timedelta(days=7)
        prev_start = start_date - timedelta(days=7)
        prev_end = start_date
    else:
        period_days = 30
        period_name = "Monthly"
        start_date = now - timedelta(days=30)
        prev_start = start_date - timedelta(days=30)
        prev_end = start_date

    trades = journal.get_trades_in_period(start_date, now)
    closed = [t for t in trades if t.is_closed]

    console.print(Panel(f"[bold]{period_name} Performance Report[/bold]", style="cyan"))
    console.print(f"Period: {start_date.strftime('%Y-%m-%d')} to {now.strftime('%Y-%m-%d')}\n")

    # Period summary
    console.print("[bold]SUMMARY[/bold]")
    console.print(f"  Total trades: {len(trades)}")
    console.print(f"  Closed trades: {len(closed)}")

    if closed:
        winners = [t for t in closed if t.is_winner]
        win_rate = len(winners) / len(closed)
        total_pnl = sum(t.pnl for t in closed)
        pnl_color = "green" if total_pnl > 0 else "red"

        console.print(f"  Win rate: {win_rate*100:.0f}%")
        console.print(f"  Total P&L: [{pnl_color}]${total_pnl:+,.2f}[/{pnl_color}]")

        # Best/worst trades
        sorted_by_pnl = sorted(closed, key=lambda t: t.pnl, reverse=True)
        if sorted_by_pnl:
            best = sorted_by_pnl[0]
            worst = sorted_by_pnl[-1]
            console.print(f"\n[bold]BEST TRADE[/bold]")
            console.print(f"  {best.symbol} {best.action}: [green]${best.pnl:+,.2f}[/green]")
            console.print(f"\n[bold]WORST TRADE[/bold]")
            console.print(f"  {worst.symbol} {worst.action}: [red]${worst.pnl:+,.2f}[/red]")

        # Top mistakes during period
        tag_counts = {}
        for t in closed:
            if not t.is_winner:
                for tag in t.tags:
                    tag_counts[tag] = tag_counts.get(tag, 0) + 1

        if tag_counts:
            console.print(f"\n[bold]TOP MISTAKES THIS PERIOD[/bold]")
            for tag, count in sorted(tag_counts.items(), key=lambda x: x[1], reverse=True)[:3]:
                console.print(f"  • {tag}: {count} occurrences")

        # Compare to previous period
        prev_trades = journal.get_trades_in_period(prev_start, prev_end)
        prev_closed = [t for t in prev_trades if t.is_closed]

        if prev_closed:
            prev_winners = [t for t in prev_closed if t.is_winner]
            prev_win_rate = len(prev_winners) / len(prev_closed)
            prev_pnl = sum(t.pnl for t in prev_closed)

            console.print(f"\n[bold]VS PREVIOUS PERIOD[/bold]")
            wr_diff = (win_rate - prev_win_rate) * 100
            pnl_diff = total_pnl - prev_pnl
            wr_color = "green" if wr_diff >= 0 else "red"
            pnl_diff_color = "green" if pnl_diff >= 0 else "red"

            console.print(f"  Win rate: [{wr_color}]{wr_diff:+.0f}%[/{wr_color}]")
            console.print(f"  P&L: [{pnl_diff_color}]${pnl_diff:+,.2f}[/{pnl_diff_color}]")
    else:
        console.print("  [dim]No closed trades in this period[/dim]")


@main.command(name="export")
@click.option("--format", "-f", "fmt", type=click.Choice(["csv", "json"]), default="csv", help="Export format")
@click.option("--output", "-o", type=click.Path(), help="Output file path")
@click.option("--closed", is_flag=True, help="Export only closed trades")
def export_cmd(fmt, output, closed):
    """Export journal data to CSV or JSON."""
    journal = Journal()

    if fmt == "json":
        data = journal.export_json()
        default_name = "trades.json"
    else:
        data = journal.export_csv(closed_only=closed)
        default_name = "trades.csv"

    if not data:
        console.print("[yellow]No trades to export[/yellow]")
        return

    if output:
        Path(output).write_text(data)
        console.print(f"[green]Exported to {output}[/green]")
    else:
        # Output to stdout
        click.echo(data)


if __name__ == "__main__":
    main()
