# Copyright 2025 Vijaykumar Singh <singhvjd@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Session management slash commands: save, load, sessions, resume, compact."""

from __future__ import annotations

import logging

from rich.panel import Panel
from rich.table import Table

from victor.ui.slash.protocol import BaseSlashCommand, CommandContext, CommandMetadata
from victor.ui.slash.registry import register_command

logger = logging.getLogger(__name__)


@register_command
class SaveCommand(BaseSlashCommand):
    """Save current conversation to a session file."""

    @property
    def metadata(self) -> CommandMetadata:
        return CommandMetadata(
            name="save",
            description="Save current conversation to a session file",
            usage="/save [name]",
            category="session",
            requires_agent=True,
        )

    def execute(self, ctx: CommandContext) -> None:
        if not self._require_agent(ctx):
            return

        from victor.agent.session import get_session_manager

        title = " ".join(ctx.args) if ctx.args else None

        try:
            session_manager = get_session_manager()
            session_id = session_manager.save_session(
                conversation=ctx.agent.conversation,
                model=ctx.agent.model,
                provider=ctx.agent.provider_name,
                profile=getattr(ctx.settings, "current_profile", "default"),
                title=title,
                conversation_state=getattr(ctx.agent, "conversation_state", None),
            )
            ctx.console.print(
                Panel(
                    f"Session saved successfully!\n\n"
                    f"[bold]Session ID:[/] {session_id}\n"
                    f"[bold]Location:[/] {session_manager.session_dir / f'{session_id}.json'}\n\n"
                    f"[dim]Use '/load {session_id}' to restore this session[/]",
                    title="Session Saved",
                    border_style="green",
                )
            )
        except Exception as e:
            ctx.console.print(f"[red]Failed to save session:[/] {e}")
            logger.exception("Error saving session")


@register_command
class LoadCommand(BaseSlashCommand):
    """Load a saved session."""

    @property
    def metadata(self) -> CommandMetadata:
        return CommandMetadata(
            name="load",
            description="Load a saved session",
            usage="/load <session_id>",
            category="session",
            requires_agent=True,
        )

    def execute(self, ctx: CommandContext) -> None:
        if not ctx.args:
            ctx.console.print("[yellow]Usage:[/] /load <session_id>")
            ctx.console.print("[dim]Use '/sessions' to list available sessions[/]")
            return

        if not self._require_agent(ctx):
            return

        from victor.agent.conversation_state import ConversationStateMachine
        from victor.agent.message_history import MessageHistory
        from victor.agent.session import get_session_manager

        session_id = ctx.args[0]

        try:
            session_manager = get_session_manager()
            session = session_manager.load_session(session_id)

            if session is None:
                ctx.console.print(f"[red]Session not found:[/] {session_id}")
                return

            # Restore conversation
            ctx.agent.conversation = MessageHistory.from_dict(session.conversation)

            # Restore conversation state machine if available
            if session.conversation_state:
                ctx.agent.conversation_state = ConversationStateMachine.from_dict(
                    session.conversation_state
                )
                logger.info(
                    f"Restored conversation state: stage={ctx.agent.conversation_state.get_stage().name}"
                )

            ctx.console.print(
                Panel(
                    f"Session loaded successfully!\n\n"
                    f"[bold]Title:[/] {session.metadata.title}\n"
                    f"[bold]Model:[/] {session.metadata.model}\n"
                    f"[bold]Provider:[/] {session.metadata.provider}\n"
                    f"[bold]Messages:[/] {session.metadata.message_count}\n"
                    f"[bold]Created:[/] {session.metadata.created_at}",
                    title="Session Loaded",
                    border_style="green",
                )
            )
        except Exception as e:
            ctx.console.print(f"[red]Failed to load session:[/] {e}")
            logger.exception("Error loading session")


@register_command
class SessionsCommand(BaseSlashCommand):
    """List saved sessions."""

    @property
    def metadata(self) -> CommandMetadata:
        return CommandMetadata(
            name="sessions",
            description="List saved sessions",
            usage="/sessions [limit]",
            aliases=["history"],
            category="session",
        )

    def execute(self, ctx: CommandContext) -> None:
        from victor.agent.session import get_session_manager

        limit = self._parse_int_arg(ctx, 0, default=10)

        try:
            session_manager = get_session_manager()
            sessions = session_manager.list_sessions(limit=limit)

            if not sessions:
                ctx.console.print("[dim]No saved sessions found[/]")
                ctx.console.print(f"[dim]Sessions are stored in: {session_manager.session_dir}[/]")
                return

            table = Table(title=f"Saved Sessions (last {len(sessions)})")
            table.add_column("ID", style="cyan", no_wrap=True)
            table.add_column("Title", style="white")
            table.add_column("Model", style="yellow")
            table.add_column("Messages", justify="right")
            table.add_column("Updated", style="dim")

            for session in sessions:
                try:
                    from datetime import datetime

                    dt = datetime.fromisoformat(session.updated_at)
                    date_str = dt.strftime("%Y-%m-%d %H:%M")
                except Exception:
                    date_str = session.updated_at[:16]

                title = session.title[:40] + "..." if len(session.title) > 40 else session.title
                table.add_row(
                    session.session_id,
                    title,
                    session.model,
                    str(session.message_count),
                    date_str,
                )

            ctx.console.print(table)
            ctx.console.print("\n[dim]Use '/load <session_id>' to restore a session[/]")
        except Exception as e:
            ctx.console.print(f"[red]Failed to list sessions:[/] {e}")
            logger.exception("Error listing sessions")


@register_command
class ResumeCommand(BaseSlashCommand):
    """Resume the most recent session."""

    @property
    def metadata(self) -> CommandMetadata:
        return CommandMetadata(
            name="resume",
            description="Resume the most recent session",
            usage="/resume",
            category="session",
            requires_agent=True,
        )

    def execute(self, ctx: CommandContext) -> None:
        if not self._require_agent(ctx):
            return

        from victor.agent.conversation_state import ConversationStateMachine
        from victor.agent.message_history import MessageHistory
        from victor.agent.session import get_session_manager

        try:
            session_manager = get_session_manager()
            sessions = session_manager.list_sessions(limit=1)

            if not sessions:
                ctx.console.print("[yellow]No sessions to resume[/]")
                return

            latest = sessions[0]
            session = session_manager.load_session(latest.session_id)

            if session is None:
                ctx.console.print("[red]Failed to load most recent session[/]")
                return

            # Restore conversation
            ctx.agent.conversation = MessageHistory.from_dict(session.conversation)

            if session.conversation_state:
                ctx.agent.conversation_state = ConversationStateMachine.from_dict(
                    session.conversation_state
                )

            ctx.console.print(
                Panel(
                    f"Resumed session: [bold]{session.metadata.title}[/]\n"
                    f"Messages: {session.metadata.message_count}",
                    title="Session Resumed",
                    border_style="green",
                )
            )
        except Exception as e:
            ctx.console.print(f"[red]Failed to resume session:[/] {e}")
            logger.exception("Error resuming session")


@register_command
class CompactCommand(BaseSlashCommand):
    """Compress conversation history to reduce context size."""

    @property
    def metadata(self) -> CommandMetadata:
        return CommandMetadata(
            name="compact",
            description="Compress conversation history (use --smart for AI summarization)",
            usage="/compact [--smart]",
            aliases=["summarize"],
            category="session",
            requires_agent=True,
            is_async=True,
        )

    async def execute(self, ctx: CommandContext) -> None:
        if not self._require_agent(ctx):
            return

        original_count = ctx.agent.conversation.message_count()

        if original_count < 5:
            ctx.console.print("[dim]Conversation is already small enough, nothing to compact[/]")
            return

        use_smart = self._has_flag(ctx, "--smart", "-s")
        keep_recent = 6

        # Parse --keep N
        keep_val = self._get_flag_value(ctx, "--keep") or self._get_flag_value(ctx, "-k")
        if keep_val:
            try:
                keep_recent = int(keep_val)
            except ValueError:
                pass

        keep_recent = min(keep_recent, len(ctx.agent.conversation.messages) // 2)
        messages = ctx.agent.conversation.messages

        if use_smart:
            ctx.console.print("[dim]Generating AI summary...[/]")

            conversation_text = "\n".join(
                [
                    (
                        f"{msg.role}: {msg.content[:200]}..."
                        if len(msg.content) > 200
                        else f"{msg.role}: {msg.content}"
                    )
                    for msg in messages[:-keep_recent]
                ]
            )

            summary_prompt = (
                "Summarize this conversation concisely, focusing on key decisions, "
                f"code changes, and context needed for continuation:\n\n{conversation_text}"
            )

            try:
                summary_response = await ctx.agent.chat(summary_prompt)
                summary = summary_response.content

                # Create new conversation with summary + recent messages
                from victor.agent.message_types import Message

                new_messages = [
                    Message(role="system", content=f"[Previous conversation summary]\n{summary}"),
                    *messages[-keep_recent:],
                ]
                ctx.agent.conversation.messages = new_messages

                ctx.console.print(
                    Panel(
                        f"Compacted {original_count} messages to {len(new_messages)}.\n\n"
                        f"[bold]Summary:[/]\n{summary[:500]}...",
                        title="Smart Compaction Complete",
                        border_style="green",
                    )
                )
            except Exception as e:
                ctx.console.print(f"[red]Smart compaction failed:[/] {e}")
        else:
            # Simple truncation
            ctx.agent.conversation.messages = messages[-keep_recent:]
            new_count = ctx.agent.conversation.message_count()

            ctx.console.print(
                f"[green]Compacted:[/] {original_count} -> {new_count} messages\n"
                "[dim]Use /compact --smart for AI-powered summarization[/]"
            )
