"""Prozes CLI - Python project generator."""

import sys
import click
from prozes.modules.dirs import create_project_folder, command_git
from prozes.modules.venv import criar_venv, instalar_dependencias
from prozes.modules.install import create_default_requirements
from prozes.modules.structures import (
    create_mvc_structure,
    create_api_structure,
    create_cli_structure,
    create_clean_structure,
)
from prozes.modules.console import (
    console,
    print_header,
    print_success,
    print_error,
    print_info,
    print_step,
    print_summary,
    print_next_steps,
    ICONS,
)
from prozes.modules.i18n import t, set_language
from prozes.modules.validation import run_all_validations


class LanguageOption(click.Option):
    """Option que troca o idioma antes de executar o comando."""

    def __init__(self, *args, help_key=None, **kwargs):
        self.help_key = help_key
        super().__init__(*args, **kwargs)

    def handle_parse_result(self, ctx, opts, args):
        # Only override if user explicitly passed --lang
        if 'lang' in opts and opts['lang'] is not None:
            set_language(opts['lang'])
        return super().handle_parse_result(ctx, opts, args)

    def get_help_record(self, ctx):
        if self.help_key:
            self.help = t(self.help_key)
        return super().get_help_record(ctx)


class TranslatedGroup(click.Group):
    """Grupo do Click com textos de ajuda traduzidos."""

    def __init__(self, *args, help_key=None, **kwargs):
        self.help_key = help_key
        super().__init__(*args, **kwargs)

    def get_short_help_str(self, limit=150):
        if self.help_key:
            return t(self.help_key)[:limit]
        return super().get_short_help_str(limit)

    def format_help(self, ctx, formatter):
        if self.help_key:
            self.help = t(self.help_key)
        super().format_help(ctx, formatter)


class TranslatedCommand(click.Command):
    """Comando do Click com help traduzido."""

    def __init__(self, *args, help_key=None, help_long_key=None, **kwargs):
        self.help_key = help_key
        self.help_long_key = help_long_key
        super().__init__(*args, **kwargs)

    def get_short_help_str(self, limit=150):
        if self.help_key:
            return t(self.help_key)[:limit]
        return super().get_short_help_str(limit)

    def format_help(self, ctx, formatter):
        if self.help_key:
            help_text = t(self.help_key)
            if self.help_long_key:
                help_text += "\n\n" + t(self.help_long_key)
            self.help = help_text
        super().format_help(ctx, formatter)


class TranslatedOption(click.Option):
    """Opção do Click com help traduzido."""

    def __init__(self, *args, help_key=None, **kwargs):
        self.help_key = help_key
        super().__init__(*args, **kwargs)

    def get_help_record(self, ctx):
        if self.help_key:
            self.help = t(self.help_key)
        return super().get_help_record(ctx)


@click.group(cls=TranslatedGroup, help_key='help_main')
@click.option(
    '--lang', '-L',
    type=click.Choice(['en', 'pt'], case_sensitive=False),
    default=None,
    cls=LanguageOption,
    is_eager=True,
    help_key='help_lang',
)
@click.version_option(version='0.1.0', prog_name='prozes')
@click.pass_context
def cli(ctx, lang):
    """Prozes - gerador de projetos Python com arquiteturas prontas."""
    from prozes.modules.i18n import get_language
    ctx.ensure_object(dict)
    ctx.obj['lang'] = lang if lang else get_language()


# =============================================================================
# Common options decorator
# =============================================================================

def common_options(f):
    """Decorator que adiciona as opções comuns em todos os comandos."""
    f = click.option('-v', '--verbose', is_flag=True,
                     cls=TranslatedOption, help_key='help_verbose')(f)
    f = click.option('--git', is_flag=True,
                     cls=TranslatedOption, help_key='help_git')(f)
    f = click.option('--venv', is_flag=True,
                     cls=TranslatedOption, help_key='help_venv')(f)
    f = click.option('--python-version', type=str, default=None,
                     cls=TranslatedOption, help_key='help_python_version')(f)
    f = click.option('--install-deps', is_flag=True,
                     cls=TranslatedOption, help_key='help_install_deps')(f)
    return f


def validate_and_exit_on_error(project_name, git, venv, python_version, install_deps):
    """Valida as entradas e sai com erro se algo estiver errado."""
    errors = run_all_validations(
        project_name=project_name,
        git=git,
        venv=venv,
        python_version=python_version,
        install_deps=install_deps,
    )

    if errors:
        console.print()
        console.print(f"[bold red]{t('validation_errors_header')}:[/bold red]")
        for error in errors:
            print_error(error)
        console.print()
        sys.exit(1)


def finalize_project(project_path, project_name, project_type, verbose, git, venv, python_version, install_deps):
    """Finaliza a criação do projeto (venv, git, deps)."""
    options = {'venv': False, 'git': False, 'deps': False}

    # Create requirements.txt
    create_default_requirements(project_path, project_type)
    if verbose:
        print_info(t('requirements_created'))

    # Virtual environment setup
    if venv:
        console.print()
        print_step(f"{ICONS['python']} {t('creating_venv')}")
        venv_success = criar_venv(project_path, python_version, verbose=False)
        if venv_success:
            options['venv'] = True
            print_success(t('venv_created'))

            if install_deps:
                print_step(f"{ICONS['package']} {t('installing_deps')}")
                deps_success = instalar_dependencias(project_path, 'requirements.txt', verbose=False)
                if deps_success:
                    options['deps'] = True
                    print_success(t('deps_installed'))

    # Git initialization
    if git:
        console.print()
        print_step(f"{ICONS['git']} {t('initializing_git')}")
        git_success = command_git(project_path, verbose=False)
        if git_success:
            options['git'] = True
            print_success(t('git_initialized'))

    # Final summary
    print_summary(project_path, project_type, options)

    return options


# =============================================================================
# MVC Command
# =============================================================================

@cli.command(cls=TranslatedCommand, help_key='help_mvc', help_long_key='help_mvc_long')
@click.argument('project_name')
@click.option(
    '-t', '--type', 'project_type',
    type=click.Choice(['web-flask', 'web-fastapi'], case_sensitive=False),
    default='web-flask',
    cls=TranslatedOption, help_key='help_mvc_type'
)
@common_options
def mvc(project_name, project_type, verbose, git, venv, python_version, install_deps):
    """Create a project with MVC architecture."""
    validate_and_exit_on_error(project_name, git, venv, python_version, install_deps)

    try:
        print_header(f"{t('creating_project_mvc')}: {project_name}", project_type)
        console.print()

        project_path = create_project_folder(project_name, verbose=False)
        print_step(t('creating_folder_structure'))
        create_mvc_structure(project_path, project_type, verbose)

        options = finalize_project(project_path, project_name, project_type, verbose, git, venv, python_version, install_deps)

        # Next steps
        steps = [f"cd {project_name}"]
        if options.get('venv'):
            steps.append(f"{project_name}\\venv\\Scripts\\activate  [dim]{t('activate_venv_win')}[/dim]")
        if project_type == 'web-fastapi':
            steps.append("uvicorn main:app --reload")
        else:
            steps.append("python main.py")

        print_next_steps(steps)

    except Exception as e:
        print_error(f"{t('error_creating_project')}: {e}")
        if verbose:
            console.print_exception()
        sys.exit(1)


# =============================================================================
# API Command
# =============================================================================

@cli.command(cls=TranslatedCommand, help_key='help_api', help_long_key='help_api_long')
@click.argument('project_name')
@click.option(
    '-t', '--type', 'project_type',
    type=click.Choice(['flask', 'fastapi'], case_sensitive=False),
    default='fastapi',
    cls=TranslatedOption, help_key='help_api_type'
)
@common_options
def api(project_name, project_type, verbose, git, venv, python_version, install_deps):
    """Create a pure REST API (no frontend)."""
    validate_and_exit_on_error(project_name, git, venv, python_version, install_deps)

    try:
        full_type = f"api-{project_type}"
        print_header(f"{t('creating_project_api')}: {project_name}", full_type)
        console.print()

        project_path = create_project_folder(project_name, verbose=False)
        print_step(t('creating_folder_structure'))
        create_api_structure(project_path, full_type, verbose)

        options = finalize_project(project_path, project_name, full_type, verbose, git, venv, python_version, install_deps)

        # Next steps
        steps = [f"cd {project_name}"]
        if options.get('venv'):
            steps.append(f"{project_name}\\venv\\Scripts\\activate  [dim]{t('activate_venv_win')}[/dim]")
        if project_type == 'fastapi':
            steps.append("uvicorn main:app --reload")
            steps.append(f"{t('open_docs')} http://localhost:8000/docs")
        else:
            steps.append("python main.py")

        print_next_steps(steps)

    except Exception as e:
        print_error(f"{t('error_creating_project')}: {e}")
        if verbose:
            console.print_exception()
        sys.exit(1)


# =============================================================================
# CLI Command
# =============================================================================

@cli.command('cli', cls=TranslatedCommand, help_key='help_cli', help_long_key='help_cli_long')
@click.argument('project_name')
@common_options
def cli_cmd(project_name, verbose, git, venv, python_version, install_deps):
    """Create a CLI project with Click."""
    validate_and_exit_on_error(project_name, git, venv, python_version, install_deps)

    try:
        print_header(f"{t('creating_project_cli')}: {project_name}", "click")
        console.print()

        project_path = create_project_folder(project_name, verbose=False)
        print_step(t('creating_folder_structure'))
        create_cli_structure(project_path, verbose)

        options = finalize_project(project_path, project_name, 'cli', verbose, git, venv, python_version, install_deps)

        # Next steps
        steps = [
            f"cd {project_name}",
            "pip install -e .",
            f"{project_name} --help",
        ]

        print_next_steps(steps)

    except Exception as e:
        print_error(f"{t('error_creating_project')}: {e}")
        if verbose:
            console.print_exception()
        sys.exit(1)


# =============================================================================
# Clean Architecture Command
# =============================================================================

@cli.command(cls=TranslatedCommand, help_key='help_clean', help_long_key='help_clean_long')
@click.argument('project_name')
@click.option(
    '-t', '--type', 'project_type',
    type=click.Choice(['flask', 'fastapi'], case_sensitive=False),
    default='flask',
    cls=TranslatedOption, help_key='help_clean_type'
)
@common_options
def clean(project_name, project_type, verbose, git, venv, python_version, install_deps):
    """Create a project with Clean Architecture."""
    validate_and_exit_on_error(project_name, git, venv, python_version, install_deps)

    try:
        full_type = f"clean-{project_type}"
        print_header(f"{t('creating_project_clean')}: {project_name}", full_type)
        console.print()

        project_path = create_project_folder(project_name, verbose=False)
        print_step(t('creating_folder_structure'))
        create_clean_structure(project_path, full_type, verbose)

        options = finalize_project(project_path, project_name, full_type, verbose, git, venv, python_version, install_deps)

        # Next steps
        steps = [f"cd {project_name}"]
        if options.get('venv'):
            steps.append(f"{project_name}\\venv\\Scripts\\activate  [dim]{t('activate_venv_win')}[/dim]")
        steps.append("python main.py")

        print_next_steps(steps)

    except Exception as e:
        print_error(f"{t('error_creating_project')}: {e}")
        if verbose:
            console.print_exception()
        sys.exit(1)


# =============================================================================
# Config Command
# =============================================================================

@cli.command(cls=TranslatedCommand, help_key='help_config')
@click.option(
    '--lang', '-l',
    type=click.Choice(['en', 'pt'], case_sensitive=False),
    cls=TranslatedOption, help_key='help_config_lang'
)
@click.option('--show', '-s', is_flag=True,
              cls=TranslatedOption, help_key='help_config_show')
def config(lang, show):
    """Configure Prozes settings."""
    from pathlib import Path
    import os

    config_dir = Path.home() / '.prozes'
    config_file = config_dir / 'config'

    if show:
        from prozes.modules.i18n import get_language

        console.print(f"\n[bold cyan]Prozes Configuration[/bold cyan]")
        console.print(f"  Config file: [dim]{config_file}[/dim]")

        if config_file.exists():
            content = config_file.read_text().strip()
            console.print(f"  Contents:")
            for line in content.split('\n'):
                console.print(f"    [green]{line}[/green]")
        else:
            console.print(f"  [dim]No config file found (using defaults)[/dim]")

        console.print(f"\n  Environment:")
        env_lang = os.environ.get('PROZEES_LANG', '[dim]not set[/dim]')
        console.print(f"    PROZEES_LANG: {env_lang}")

        console.print(f"\n  [bold]Active language:[/bold] [green]{get_language()}[/green]")
        return

    if lang:
        # Create config directory if it doesn't exist
        config_dir.mkdir(parents=True, exist_ok=True)

        # Write config
        config_file.write_text(f"lang={lang}\n")

        print_success(f"Language set to '{lang}'")
        console.print(f"  Config saved to: [dim]{config_file}[/dim]")
    else:
        # No options provided, show help
        ctx = click.get_current_context()
        click.echo(ctx.get_help())


def main():
    """Ponto de entrada do CLI."""
    cli()


if __name__ == '__main__':
    main()
