"""Fish shell completion generator."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from ..models import CommandCompletion

__all__ = ["generate_fish"]

_HEADER = """# Fish completion for pypr
# Generated by: pypr compgen fish

# Disable default file completions for pypr
complete -c pypr -f

# Helper function to count args after command
function __pypr_arg_count
    set -l cmd (commandline -opc)
    math (count $cmd) - 1
end

# Main commands"""


def _build_main_commands(commands: dict[str, CommandCompletion]) -> list[str]:
    """Build main command completion lines."""
    lines: list[str] = []
    for cmd_name, cmd in sorted(commands.items()):
        desc = cmd.description.replace('"', '\\"') if cmd.description else ""
        # Add subcommand hint if applicable
        if cmd.subcommands and not cmd.args and not desc:
            subcmds = "|".join(sorted(cmd.subcommands.keys()))
            desc = f"<{subcmds}>"
        if desc:
            lines.append(f'complete -c pypr -n "__fish_use_subcommand" -a "{cmd_name}" -d "{desc}"')
        else:
            lines.append(f'complete -c pypr -n "__fish_use_subcommand" -a "{cmd_name}"')
    return lines


def _build_subcommand_completions(cmd_name: str, cmd: CommandCompletion) -> list[str]:
    """Build fish completions for a command's subcommands."""
    lines: list[str] = []
    for subcmd_name, subcmd in sorted(cmd.subcommands.items()):
        subdesc = subcmd.description.replace('"', '\\"') if subcmd.description else ""
        if subdesc:
            lines.append(
                f'complete -c pypr -n "__fish_seen_subcommand_from {cmd_name}; '
                f'and test (__pypr_arg_count) -eq 1" -a "{subcmd_name}" -d "{subdesc}"'
            )
        else:
            lines.append(
                f'complete -c pypr -n "__fish_seen_subcommand_from {cmd_name}; and test (__pypr_arg_count) -eq 1" -a "{subcmd_name}"'
            )
    return lines


def _build_help_completions(cmd: CommandCompletion, all_commands: list[str]) -> list[str]:
    """Build fish completions for help command with hierarchical completion.

    Position 1: complete with all commands
    Position 2+: complete subcommands based on the command at position 1
    """
    lines: list[str] = []

    # Position 1: complete with all command names
    all_cmds_str = " ".join(all_commands)
    lines.append(f'complete -c pypr -n "__fish_seen_subcommand_from help; and test (__pypr_arg_count) -eq 1" -a "{all_cmds_str}"')

    # Position 2+: complete subcommands for each parent command
    for parent_name, parent_cmd in sorted(cmd.subcommands.items()):
        if parent_cmd.args:
            subcmds_str = " ".join(parent_cmd.args[0].values)
            lines.append(
                f'complete -c pypr -n "__fish_seen_subcommand_from help; '
                f"and contains {parent_name} (commandline -opc); "
                f'and test (__pypr_arg_count) -eq 2" -a "{subcmds_str}"'
            )

    return lines


def _build_args_completions(cmd_name: str, cmd: CommandCompletion) -> list[str]:
    """Build fish completions for a command's positional args."""
    lines: list[str] = []
    for arg in cmd.args:
        if arg.completion_type in ("choices", "dynamic", "literal"):
            values_str = " ".join(arg.values)
            lines.append(
                f'complete -c pypr -n "__fish_seen_subcommand_from {cmd_name}; '
                f'and test (__pypr_arg_count) -eq {arg.position}" -a "{values_str}"'
            )
        elif arg.completion_type == "file":
            lines.append(f'complete -c pypr -n "__fish_seen_subcommand_from {cmd_name}; and test (__pypr_arg_count) -eq {arg.position}" -F')
        # hint type: no completion added
    return lines


def generate_fish(commands: dict[str, CommandCompletion]) -> str:
    """Generate fish completion script content.

    Args:
        commands: Dict mapping command name -> CommandCompletion

    Returns:
        The fish completion script content
    """
    lines = [_HEADER]
    lines.extend(_build_main_commands(commands))

    lines.append("")
    lines.append("# Subcommand and positional argument completions")

    all_cmd_names = sorted(commands.keys())
    for cmd_name, cmd in sorted(commands.items()):
        if cmd_name == "help":
            lines.extend(_build_help_completions(cmd, all_cmd_names))
        elif cmd.subcommands:
            lines.extend(_build_subcommand_completions(cmd_name, cmd))
        elif cmd.args:
            lines.extend(_build_args_completions(cmd_name, cmd))

    return "\n".join(lines) + "\n"
