"""Generate shell completion scripts for iam-validator.

This command generates completion scripts for bash and zsh shells.
The generated scripts provide intelligent autocompletion for:
- Command names (validate, query, analyze, etc.)
- Command options (--service, --access-level, etc.)
- Cached AWS service names (for --service flag)

Both `iam-validator` and `iam-policy-validator` commands are supported.

Usage:
    # Bash completion
    iam-validator completion bash > ~/.bash_completion.d/iam-validator
    source ~/.bash_completion.d/iam-validator

    # Zsh completion
    iam-validator completion zsh > ~/.zsh/completion/_iam-validator
    # Then add to ~/.zshrc: fpath=(~/.zsh/completion $fpath)
"""

import argparse
import logging

from iam_validator.commands.base import Command
from iam_validator.core.aws_service.storage import ServiceFileStorage

logger = logging.getLogger(__name__)


class CompletionCommand(Command):
    """Generate shell completion scripts."""

    @property
    def name(self) -> str:
        """Command name."""
        return "completion"

    @property
    def help(self) -> str:
        """Command help text."""
        return "Generate shell completion scripts (bash or zsh)"

    @property
    def epilog(self) -> str:
        """Command epilog with examples."""
        return """
examples:
  # Generate bash completion
  iam-validator completion bash > ~/.bash_completion.d/iam-validator
  source ~/.bash_completion.d/iam-validator

  # Generate zsh completion
  iam-validator completion zsh > ~/.zsh/completion/_iam-validator
  # Add to ~/.zshrc: fpath=(~/.zsh/completion $fpath)

  # Direct evaluation (bash)
  eval "$(iam-validator completion bash)"

  # Direct evaluation (zsh)
  eval "$(iam-validator completion zsh)"
"""

    def add_arguments(self, parser: argparse.ArgumentParser) -> None:
        """Add completion command arguments."""
        parser.add_argument(
            "shell",
            choices=["bash", "zsh"],
            help="Shell type to generate completion for",
        )

    async def execute(self, args: argparse.Namespace) -> int:
        """Execute completion command."""
        try:
            if args.shell == "bash":
                script = self._generate_bash_completion()
            else:  # zsh
                script = self._generate_zsh_completion()

            print(script)
            return 0

        except Exception as e:  # pylint: disable=broad-exception-caught
            logger.error(f"Failed to generate completion: {e}", exc_info=True)
            return 1

    def _get_cached_services(self) -> list[str]:
        """Get list of cached AWS service names.

        Returns:
            List of service names that are cached locally.
            Returns empty list if cache is not available.
        """
        try:
            storage = ServiceFileStorage()
            cache_dir = storage.cache_directory

            if not cache_dir.exists():
                return []

            # Look for cached service files
            # Files are named like: s3_{hash}.json or services_list.json
            services = set()

            for cache_file in cache_dir.glob("*.json"):
                filename = cache_file.stem
                # Extract service name from cache filename
                # Format: servicename_hash or services_list
                if filename == "services_list":
                    continue
                # Extract service name (before underscore)
                if "_" in filename:
                    service_name = filename.split("_")[0]
                    services.add(service_name)

            return sorted(list(services))

        except Exception as e:  # pylint: disable=broad-exception-caught
            logger.debug(f"Could not load cached services: {e}")
            return []

    def _generate_bash_completion(self) -> str:
        """Generate bash completion script.

        Returns:
            Bash completion script as string
        """
        cached_services = self._get_cached_services()
        services_list = " ".join(cached_services) if cached_services else ""

        return f'''# Bash completion for iam-validator
# Generated by: iam-validator completion bash

_iam_validator_completion() {{
    local cur prev opts base
    COMPREPLY=()
    cur="${{COMP_WORDS[COMP_CWORD]}}"
    prev="${{COMP_WORDS[COMP_CWORD-1]}}"

    # Main commands
    local commands="validate post-to-pr analyze cache sync-services query completion mcp"

    # Get the command (first non-option argument)
    local cmd=""
    for ((i=1; i<COMP_CWORD; i++)); do
        if [[ ${{COMP_WORDS[i]}} != -* ]]; then
            cmd=${{COMP_WORDS[i]}}
            break
        fi
    done

    # Complete main command if we're at the first argument
    if [[ $COMP_CWORD -eq 1 ]]; then
        COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
        return 0
    fi

    # Completion based on previous argument
    case "$prev" in
        --service)
            # Provide cached service names
            local services="{services_list}"
            COMPREPLY=( $(compgen -W "$services" -- "$cur") )
            return 0
            ;;
        --access-level)
            COMPREPLY=( $(compgen -W "read write list tagging permissions-management" -- "$cur") )
            return 0
            ;;
        --format|-f)
            COMPREPLY=( $(compgen -W "console enhanced json markdown html csv sarif" -- "$cur") )
            return 0
            ;;
        --policy-type|-t)
            COMPREPLY=( $(compgen -W "IDENTITY_POLICY RESOURCE_POLICY TRUST_POLICY SERVICE_CONTROL_POLICY RESOURCE_CONTROL_POLICY" -- "$cur") )
            return 0
            ;;
        --output|-o)
            # Context-aware: file for validate, format for query
            if [[ "$cmd" == "query" ]]; then
                COMPREPLY=( $(compgen -W "json yaml text" -- "$cur") )
            else
                COMPREPLY=( $(compgen -f -- "$cur") )
            fi
            return 0
            ;;
        --path|-p|--config|-c|--custom-checks-dir|--aws-services-dir)
            # File/directory completion
            COMPREPLY=( $(compgen -f -- "$cur") )
            return 0
            ;;
        --resource-type|--condition|--name|--batch-size|--host|--port)
            # Allow any input
            return 0
            ;;
        completion)
            COMPREPLY=( $(compgen -W "bash zsh" -- "$cur") )
            return 0
            ;;
        --transport)
            COMPREPLY=( $(compgen -W "stdio sse" -- "$cur") )
            return 0
            ;;
        --config)
            # File completion for config
            COMPREPLY=( $(compgen -f -- "$cur") )
            return 0
            ;;
    esac

    # Handle cache list --format specifically
    if [[ "$cmd" == "cache" && "$prev" == "--format" ]]; then
        COMPREPLY=( $(compgen -W "table columns simple" -- "$cur") )
        return 0
    fi

    # Command-specific completions
    case "$cmd" in
        query)
            # Check if we need to complete the query subcommand
            local query_subcmd=""
            for ((i=2; i<COMP_CWORD; i++)); do
                if [[ ${{COMP_WORDS[i]}} =~ ^(action|arn|condition)$ ]]; then
                    query_subcmd=${{COMP_WORDS[i]}}
                    break
                fi
            done

            if [[ -z "$query_subcmd" ]]; then
                # Complete query subcommand
                COMPREPLY=( $(compgen -W "action arn condition" -- "$cur") )
                return 0
            fi

            # Complete options for query subcommands
            # Note: --service is optional if --name includes service prefix (e.g., s3:GetObject)
            # Note: --name accepts multiple values and supports wildcards
            local opts=""
            case "$query_subcmd" in
                action)
                    opts="--service --name --access-level --resource-type --condition --output --show-condition-keys --show-resource-types --show-access-level"
                    ;;
                arn)
                    opts="--service --name --list-arn-types --output"
                    ;;
                condition)
                    opts="--service --name --output"
                    ;;
            esac

            # Filter out already used options
            local used_opts=""
            for ((i=2; i<COMP_CWORD; i++)); do
                if [[ ${{COMP_WORDS[i]}} == --* ]]; then
                    used_opts="$used_opts ${{COMP_WORDS[i]}}"
                fi
            done

            local available_opts=""
            for opt in $opts; do
                if [[ ! " $used_opts " =~ " $opt " ]]; then
                    available_opts="$available_opts $opt"
                fi
            done

            COMPREPLY=( $(compgen -W "$available_opts" -- "$cur") )
            return 0
            ;;
        validate)
            opts="--path -p --stdin --format -f --output -o --no-recursive --fail-on-warnings --policy-type -t --github-comment --github-review --github-summary --verbose -v --config -c --custom-checks-dir --aws-services-dir --stream --batch-size --summary --severity-breakdown --allow-owner-ignore --no-owner-ignore --ci --ci-output"
            COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
            return 0
            ;;
        post-to-pr)
            opts="--report -r --create-review --no-review --add-summary --no-summary --config -c"
            COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
            return 0
            ;;
        analyze)
            opts="--path -p --policy-type -t --region --profile --format -f --output -o --no-recursive --fail-on-warnings --github-comment --github-review --github-summary --run-all-checks --check-access-not-granted --check-access-resources --check-no-new-access --check-no-public-access --public-access-resource-type --verbose -v"
            COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
            return 0
            ;;
        cache)
            # Check if we need to complete the cache subcommand
            local cache_subcmd=""
            for ((i=2; i<COMP_CWORD; i++)); do
                if [[ ${{COMP_WORDS[i]}} =~ ^(info|list|clear|refresh|prefetch|location)$ ]]; then
                    cache_subcmd=${{COMP_WORDS[i]}}
                    break
                fi
            done

            if [[ -z "$cache_subcmd" ]]; then
                # Complete cache subcommand
                COMPREPLY=( $(compgen -W "info list clear refresh prefetch location" -- "$cur") )
                return 0
            fi

            # Cache subcommand-specific options
            case "$cache_subcmd" in
                list)
                    COMPREPLY=( $(compgen -W "--config --format" -- "$cur") )
                    ;;
                info|clear|refresh|prefetch|location)
                    COMPREPLY=( $(compgen -W "--config" -- "$cur") )
                    ;;
            esac
            return 0
            ;;
        sync-services)
            opts="--output-dir --max-concurrent"
            COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
            return 0
            ;;
        mcp)
            opts="--transport --host --port --verbose -v --config"
            COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
            return 0
            ;;
    esac

    return 0
}}

complete -F _iam_validator_completion iam-validator
complete -F _iam_validator_completion iam-policy-validator
'''

    def _generate_zsh_completion(self) -> str:
        """Generate zsh completion script.

        Returns:
            Zsh completion script as string
        """
        cached_services = self._get_cached_services()
        # For zsh, we need to format as: 'service1' 'service2' ...
        services_list = " ".join(f"'{svc}'" for svc in cached_services) if cached_services else ""

        return f"""#compdef iam-validator iam-policy-validator
# Zsh completion for iam-validator and iam-policy-validator
# Generated by: iam-validator completion zsh

_iam_validator() {{
    local curcontext="$curcontext" state line
    typeset -A opt_args

    # Cached AWS services
    local -a aws_services
    aws_services=({services_list})

    _arguments -C \\
        '1: :_iam_validator_commands' \\
        '*::arg:->args'

    case $state in
        args)
            case $words[1] in
                query)
                    local query_state
                    _arguments -C \\
                        '1: :_iam_validator_query_subcommands' \\
                        '*::arg:->query_args' && return 0

                    case $state in
                        query_args)
                            case $words[1] in
                                action)
                                    _arguments \\
                                        '--service[AWS service (optional if --name has prefix)]:service:($aws_services)' \\
                                        '*--name[Action name(s) - supports multiple values and wildcards]:action name:' \\
                                        '--access-level[Filter by access level]:access level:(read write list tagging permissions-management)' \\
                                        '--resource-type[Filter by resource type]:resource type:' \\
                                        '--condition[Filter by condition key]:condition key:' \\
                                        '--output[Output format]:format:(json yaml text)' \\
                                        '--show-condition-keys[Show only condition keys for each action]' \\
                                        '--show-resource-types[Show only resource types for each action]' \\
                                        '--show-access-level[Show only access level for each action]'
                                    ;;
                                arn)
                                    _arguments \\
                                        '--service[AWS service (optional if --name has prefix)]:service:($aws_services)' \\
                                        '--name[ARN type (e.g., bucket or s3:bucket)]:arn type:' \\
                                        '--list-arn-types[List all ARN types]' \\
                                        '--output[Output format]:format:(json yaml text)'
                                    ;;
                                condition)
                                    _arguments \\
                                        '--service[AWS service (optional if --name has prefix)]:service:($aws_services)' \\
                                        '--name[Condition key (e.g., prefix or s3:prefix)]:condition key:' \\
                                        '--output[Output format]:format:(json yaml text)'
                                    ;;
                            esac
                            ;;
                    esac
                    ;;
                validate)
                    _arguments \\
                        '*--path[Path to policy file or directory]:file:_files' \\
                        '*-p[Path to policy file or directory]:file:_files' \\
                        '--stdin[Read policy from stdin]' \\
                        '(--format -f)'{{--format,-f}}'[Output format]:format:(console enhanced json markdown html csv sarif)' \\
                        '(--output -o)'{{--output,-o}}'[Output file path]:file:_files' \\
                        '--no-recursive[Do not recursively search directories]' \\
                        '--fail-on-warnings[Fail validation if warnings are found]' \\
                        '(--policy-type -t)'{{--policy-type,-t}}'[Type of IAM policy]:policy type:(IDENTITY_POLICY RESOURCE_POLICY TRUST_POLICY SERVICE_CONTROL_POLICY RESOURCE_CONTROL_POLICY)' \\
                        '--github-comment[Post summary comment to PR]' \\
                        '--github-review[Create line-specific review comments]' \\
                        '--github-summary[Write to GitHub Actions job summary]' \\
                        '(--verbose -v)'{{--verbose,-v}}'[Enable verbose logging]' \\
                        '(--config -c)'{{--config,-c}}'[Configuration file]:file:_files' \\
                        '--custom-checks-dir[Custom checks directory]:directory:_directories' \\
                        '--aws-services-dir[AWS service definitions directory]:directory:_directories' \\
                        '--stream[Process files one-by-one]' \\
                        '--batch-size[Policies per batch]:number:' \\
                        '--summary[Show Executive Summary section]' \\
                        '--severity-breakdown[Show Issue Severity Breakdown section]' \\
                        '--allow-owner-ignore[Allow CODEOWNERS to ignore findings]' \\
                        '--no-owner-ignore[Disable CODEOWNERS ignore feature]' \\
                        '--ci[CI mode - print enhanced output, write JSON to file]' \\
                        '--ci-output[Output file for JSON report in CI mode]:file:_files'
                    ;;
                post-to-pr)
                    _arguments \\
                        '(--report -r)'{{--report,-r}}'[Path to JSON report file]:file:_files' \\
                        '--create-review[Create line-specific review comments]' \\
                        '--no-review[Do not create line-specific review comments]' \\
                        '--add-summary[Add summary comment]' \\
                        '--no-summary[Do not add summary comment]' \\
                        '(--config -c)'{{--config,-c}}'[Configuration file]:file:_files'
                    ;;
                analyze)
                    _arguments \\
                        '*--path[Path to policy file or directory]:file:_files' \\
                        '*-p[Path to policy file or directory]:file:_files' \\
                        '(--policy-type -t)'{{--policy-type,-t}}'[Type of IAM policy]:policy type:(IDENTITY_POLICY RESOURCE_POLICY SERVICE_CONTROL_POLICY)' \\
                        '--region[AWS region]:region:' \\
                        '--profile[AWS profile]:profile:' \\
                        '(--format -f)'{{--format,-f}}'[Output format]:format:(console json markdown)' \\
                        '(--output -o)'{{--output,-o}}'[Output file path]:file:_files' \\
                        '--no-recursive[Do not recursively search directories]' \\
                        '--fail-on-warnings[Fail validation if warnings are found]' \\
                        '--github-comment[Post validation results as GitHub PR comment]' \\
                        '--github-review[Create line-specific review comments on PR]' \\
                        '--github-summary[Write validation summary to GitHub Actions job summary]' \\
                        '--run-all-checks[Run full validation checks if Access Analyzer passes]' \\
                        '*--check-access-not-granted[Actions to check are NOT granted]:action:' \\
                        '*--check-access-resources[Resources to check]:resource:' \\
                        '--check-no-new-access[Path to existing policy]:file:_files' \\
                        '--check-no-public-access[Check that resource policy does not allow public access]' \\
                        '*--public-access-resource-type[Resource type for public access check]:resource type:' \\
                        '(--verbose -v)'{{--verbose,-v}}'[Enable verbose logging]'
                    ;;
                cache)
                    local cache_state
                    _arguments -C \\
                        '1: :_iam_validator_cache_subcommands' \\
                        '*::arg:->cache_args' && return 0

                    case $state in
                        cache_args)
                            case $words[1] in
                                info|clear|refresh|prefetch|location)
                                    _arguments \\
                                        '--config[Configuration file]:file:_files'
                                    ;;
                                list)
                                    _arguments \\
                                        '--config[Configuration file]:file:_files' \\
                                        '--format[Output format]:format:(table columns simple)'
                                    ;;
                            esac
                            ;;
                    esac
                    ;;
                sync-services)
                    _arguments \\
                        '--output-dir[Output directory]:directory:_directories' \\
                        '--max-concurrent[Maximum concurrent downloads]:number:'
                    ;;
                completion)
                    _arguments \\
                        '1: :(bash zsh)'
                    ;;
                mcp)
                    _arguments \\
                        '--transport[Transport protocol]:transport:(stdio sse)' \\
                        '--host[Host for SSE transport]:host:' \\
                        '--port[Port for SSE transport]:port:' \\
                        '(--verbose -v)'{{--verbose,-v}}'[Enable verbose logging]' \\
                        '--config[Path to configuration YAML file]:file:_files'
                    ;;
            esac
            ;;
    esac
}}

_iam_validator_commands() {{
    local -a commands
    commands=(
        'validate:Validate IAM policies'
        'post-to-pr:Post validation results to GitHub PR'
        'analyze:Analyze IAM policies using AWS IAM Access Analyzer'
        'cache:Manage AWS service definition cache'
        'sync-services:Sync/download all AWS service definitions for offline use'
        'query:Query AWS service definitions (actions, ARNs, condition keys)'
        'completion:Generate shell completion scripts (bash or zsh)'
        'mcp:Start MCP server for AI assistant integration'
    )
    _describe 'command' commands
}}

_iam_validator_query_subcommands() {{
    local -a subcommands
    subcommands=(
        'action:Query IAM actions'
        'arn:Query ARN formats'
        'condition:Query condition keys'
    )
    _describe 'query subcommand' subcommands
}}

_iam_validator_cache_subcommands() {{
    local -a subcommands
    subcommands=(
        'info:Show cache information and statistics'
        'list:List all cached AWS services'
        'clear:Clear all cached AWS service definitions'
        'refresh:Refresh all cached services with fresh data'
        'prefetch:Pre-fetch common AWS services (without clearing)'
        'location:Show cache directory location'
    )
    _describe 'cache subcommand' subcommands
}}

_iam_validator "$@"
"""


# For testing
if __name__ == "__main__":
    import asyncio
    import sys

    cmd = CompletionCommand()
    arg_parser = argparse.ArgumentParser()
    cmd.add_arguments(arg_parser)
    parsed_args = arg_parser.parse_args()
    sys.exit(asyncio.run(cmd.execute(parsed_args)))
