"""Tests for the Prozes CLI core."""

import os
from pathlib import Path

import pytest
from click.testing import CliRunner

from prozes.core import cli


@pytest.fixture
def runner():
    """Fixture for CLI runner."""
    return CliRunner()


class TestCLIBasic:
    """Basic CLI tests."""

    def test_cli_version(self, runner):
        """Test --version flag works."""
        result = runner.invoke(cli, ["--version"])
        assert result.exit_code == 0
        assert "0.1.0" in result.output

    def test_cli_help(self, runner):
        """Test --help flag works."""
        result = runner.invoke(cli, ["--help"])
        assert result.exit_code == 0
        assert "Prozes" in result.output

    def test_cli_lang_option(self, runner):
        """Test --lang option."""
        result = runner.invoke(cli, ["--lang", "pt", "--help"])
        assert result.exit_code == 0


class TestMVCCommand:
    """Tests for the mvc command."""

    def test_mvc_help(self, runner):
        """Test mvc --help works."""
        result = runner.invoke(cli, ["mvc", "--help"])
        assert result.exit_code == 0
        assert "PROJECT_NAME" in result.output

    def test_mvc_creates_project(self, runner, tmp_path):
        """Test mvc creates project successfully."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["mvc", "test_project"])
            assert result.exit_code == 0
            assert Path("test_project").exists()
            assert Path("test_project/app").exists()
            assert Path("test_project/main.py").exists()

    def test_mvc_with_fastapi(self, runner, tmp_path):
        """Test mvc with FastAPI type."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["mvc", "fastapi_project", "-t", "web-fastapi"])
            assert result.exit_code == 0
            assert Path("fastapi_project").exists()

    def test_mvc_verbose(self, runner, tmp_path):
        """Test mvc with verbose flag."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["mvc", "test_project", "-v"])
            assert result.exit_code == 0

    def test_mvc_invalid_name(self, runner, tmp_path):
        """Test mvc with invalid project name."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["mvc", "123invalid"])
            assert result.exit_code == 1

    def test_mvc_python_keyword(self, runner, tmp_path):
        """Test mvc with Python keyword as name."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["mvc", "class"])
            assert result.exit_code == 1

    def test_mvc_existing_project(self, runner, tmp_path):
        """Test mvc with existing project."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            Path("existing_project").mkdir()
            result = runner.invoke(cli, ["mvc", "existing_project"])
            assert result.exit_code == 1


class TestAPICommand:
    """Tests for the api command."""

    def test_api_help(self, runner):
        """Test api --help works."""
        result = runner.invoke(cli, ["api", "--help"])
        assert result.exit_code == 0
        assert "PROJECT_NAME" in result.output

    def test_api_creates_project(self, runner, tmp_path):
        """Test api creates project successfully."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["api", "test_api"])
            assert result.exit_code == 0
            assert Path("test_api").exists()
            assert Path("test_api/main.py").exists()

    def test_api_with_flask(self, runner, tmp_path):
        """Test api with Flask type."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["api", "flask_api", "-t", "flask"])
            assert result.exit_code == 0

    def test_api_invalid_name(self, runner, tmp_path):
        """Test api with invalid project name."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["api", "my-api"])
            assert result.exit_code == 1


class TestCLICommandCommand:
    """Tests for the cli command."""

    def test_cli_cmd_help(self, runner):
        """Test cli --help works."""
        result = runner.invoke(cli, ["cli", "--help"])
        assert result.exit_code == 0
        assert "PROJECT_NAME" in result.output

    def test_cli_creates_project(self, runner, tmp_path):
        """Test cli creates project successfully."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["cli", "test_cli"])
            assert result.exit_code == 0
            assert Path("test_cli").exists()
            assert Path("test_cli/test_cli").exists()
            assert Path("test_cli/setup.py").exists()

    def test_cli_invalid_name(self, runner, tmp_path):
        """Test cli with invalid project name."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["cli", "def"])
            assert result.exit_code == 1


class TestCleanCommand:
    """Tests for the clean command."""

    def test_clean_help(self, runner):
        """Test clean --help works."""
        result = runner.invoke(cli, ["clean", "--help"])
        assert result.exit_code == 0
        assert "PROJECT_NAME" in result.output

    def test_clean_creates_project(self, runner, tmp_path):
        """Test clean creates project successfully."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["clean", "test_clean"])
            assert result.exit_code == 0
            assert Path("test_clean").exists()
            assert Path("test_clean/src").exists()
            assert Path("test_clean/src/entities").exists()
            assert Path("test_clean/src/use_cases").exists()

    def test_clean_with_fastapi(self, runner, tmp_path):
        """Test clean with FastAPI type."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["clean", "fastapi_clean", "-t", "fastapi"])
            assert result.exit_code == 0

    def test_clean_invalid_name(self, runner, tmp_path):
        """Test clean with invalid project name."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["clean", "import"])
            assert result.exit_code == 1


class TestConfigCommand:
    """Tests for the config command."""

    def test_config_help(self, runner):
        """Test config --help works."""
        result = runner.invoke(cli, ["config", "--help"])
        assert result.exit_code == 0

    def test_config_show(self, runner):
        """Test config --show works."""
        result = runner.invoke(cli, ["config", "--show"])
        assert result.exit_code == 0
        assert "Configuration" in result.output or "Active language" in result.output


class TestValidationErrors:
    """Tests for validation error scenarios."""

    def test_install_deps_without_venv(self, runner, tmp_path):
        """Test --install-deps without --venv fails."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["mvc", "test_project", "--install-deps"])
            assert result.exit_code == 1
            assert "venv" in result.output.lower()

    def test_invalid_python_version_format(self, runner, tmp_path):
        """Test invalid Python version format."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(
                cli, ["mvc", "test_project", "--venv", "--python-version", "python3.11"]
            )
            assert result.exit_code == 1

    def test_valid_python_version_format(self, runner, tmp_path):
        """Test valid Python version format passes validation."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            # This should pass validation (actual venv creation may vary)
            result = runner.invoke(
                cli, ["mvc", "test_project", "--python-version", "3.11"]
            )
            # Note: may fail later if Python 3.11 not installed, but should pass validation
            # We mainly care that format validation passed


class TestLanguageOption:
    """Tests for language options."""

    def test_portuguese_output(self, runner, tmp_path):
        """Test Portuguese language output."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["--lang", "pt", "mvc", "test_project"])
            assert result.exit_code == 0
            # Check for Portuguese text
            assert "Projeto criado com sucesso" in result.output or "sucesso" in result.output.lower()

    def test_english_output(self, runner, tmp_path):
        """Test English language output."""
        with runner.isolated_filesystem(temp_dir=tmp_path):
            result = runner.invoke(cli, ["--lang", "en", "mvc", "test_project"])
            assert result.exit_code == 0
            # Check for English text
            assert "successfully" in result.output.lower() or "success" in result.output.lower()
