"""Tests for StackDetector."""

import os
import tempfile
import json
import pytest
import sys

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

from claudemd.generators.stack_detector import StackDetector


@pytest.fixture
def tmpproject():
    """Create a temporary project directory."""
    with tempfile.TemporaryDirectory() as tmpdir:
        yield tmpdir


def write_file(root, filename, content):
    """Helper to write a file in the temp project."""
    path = os.path.join(root, filename)
    os.makedirs(os.path.dirname(path), exist_ok=True)
    with open(path, "w") as f:
        f.write(content)


class TestPythonDetection:
    def test_detects_python_from_pyproject(self, tmpproject):
        write_file(tmpproject, "pyproject.toml", '[project]\nname="myapp"\n')
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "Python" in stack["languages"]

    def test_detects_fastapi(self, tmpproject):
        write_file(tmpproject, "pyproject.toml", '[project]\ndependencies = ["fastapi>=0.100"]\n')
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "FastAPI" in stack["frameworks"]

    def test_detects_pytest(self, tmpproject):
        write_file(tmpproject, "pyproject.toml", '[project]\ndependencies = ["pytest>=7"]\n')
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "pytest" in stack["test_frameworks"]

    def test_detects_requirements_txt(self, tmpproject):
        write_file(tmpproject, "requirements.txt", "requests==2.28.0\nflask==3.0\n")
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "Python" in stack["languages"]
        assert "Flask" in stack["frameworks"]

    def test_detects_conda_env(self, tmpproject):
        write_file(tmpproject, "environment.yml", "name: myenv\ndependencies:\n  - numpy\n")
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "conda" in stack["package_managers"]

    def test_detects_sqlalchemy(self, tmpproject):
        write_file(tmpproject, "requirements.txt", "sqlalchemy>=2.0\n")
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "SQLAlchemy" in stack["databases"]


class TestNodeJSDetection:
    def test_detects_nodejs(self, tmpproject):
        pkg = {"name": "myapp", "dependencies": {"react": "^18.0.0"}}
        write_file(tmpproject, "package.json", json.dumps(pkg))
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "JavaScript/TypeScript" in stack["languages"]

    def test_detects_react(self, tmpproject):
        pkg = {"name": "myapp", "dependencies": {"react": "^18.0.0"}}
        write_file(tmpproject, "package.json", json.dumps(pkg))
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "React" in stack["frameworks"]

    def test_detects_nextjs(self, tmpproject):
        pkg = {"name": "myapp", "dependencies": {"next": "^14.0.0", "react": "^18.0.0"}}
        write_file(tmpproject, "package.json", json.dumps(pkg))
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "Next.js" in stack["frameworks"]

    def test_detects_typescript(self, tmpproject):
        pkg = {"name": "myapp", "dependencies": {}}
        write_file(tmpproject, "package.json", json.dumps(pkg))
        write_file(tmpproject, "tsconfig.json", '{"compilerOptions": {}}')
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "TypeScript" in stack["languages"]

    def test_detects_jest(self, tmpproject):
        pkg = {"name": "myapp", "devDependencies": {"jest": "^29.0.0"}}
        write_file(tmpproject, "package.json", json.dumps(pkg))
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "Jest" in stack["test_frameworks"]

    def test_detects_prisma(self, tmpproject):
        pkg = {"name": "myapp", "dependencies": {"@prisma/client": "^5.0.0"}}
        write_file(tmpproject, "package.json", json.dumps(pkg))
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "Prisma" in stack["databases"]

    def test_detects_npm_package_manager(self, tmpproject):
        pkg = {"name": "myapp", "dependencies": {}}
        write_file(tmpproject, "package.json", json.dumps(pkg))
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "npm" in stack["package_managers"]


class TestRustDetection:
    def test_detects_rust(self, tmpproject):
        write_file(tmpproject, "Cargo.toml", '[package]\nname = "myapp"\n')
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "Rust" in stack["languages"]
        assert "cargo" in stack["package_managers"]

    def test_detects_axum(self, tmpproject):
        write_file(tmpproject, "Cargo.toml", '[dependencies]\naxum = "0.7"\n')
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "Axum" in stack["frameworks"]


class TestDockerDetection:
    def test_detects_dockerfile(self, tmpproject):
        write_file(tmpproject, "Dockerfile", "FROM python:3.11\n")
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "Docker" in stack["tools"]

    def test_detects_docker_compose(self, tmpproject):
        write_file(tmpproject, "docker-compose.yml", "version: '3'\nservices:\n  app:\n    image: myapp\n")
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "Docker Compose" in stack["tools"]


class TestCIDetection:
    def test_detects_github_actions(self, tmpproject):
        write_file(tmpproject, ".github/workflows/ci.yml", "on: push\njobs:\n  test:\n    runs-on: ubuntu-latest\n")
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert "GitHub Actions" in stack["tools"]


class TestEmptyProject:
    def test_empty_project(self, tmpproject):
        """Empty project should return empty but valid result."""
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert isinstance(stack, dict)
        assert "languages" in stack
        assert "frameworks" in stack

    def test_to_summary_empty(self, tmpproject):
        """Summary for empty project should not crash."""
        d = StackDetector(tmpproject)
        summary = d.to_summary()
        assert isinstance(summary, str)


class TestDeduplication:
    def test_no_duplicate_languages(self, tmpproject):
        """Languages should not be duplicated."""
        write_file(tmpproject, "pyproject.toml", "[project]\n")
        write_file(tmpproject, "requirements.txt", "requests\n")
        d = StackDetector(tmpproject)
        stack = d.detect()
        assert stack["languages"].count("Python") == 1
