"""Tests for ClaudeMdLinter."""

import os
import tempfile
import pytest
import sys

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

from claudemd.analyzers.linter import ClaudeMdLinter
from claudemd.analyzers.token_counter import TokenCounter


class TestTokenCounter:
    def test_count_empty(self):
        counter = TokenCounter()
        assert counter.count("") == 0

    def test_count_words(self):
        counter = TokenCounter()
        # ~10 words = ~13 tokens (words/0.75)
        count = counter.count("Hello world this is a test sentence with ten words total")
        assert 10 <= count <= 20  # Rough bounds

    def test_analyze_returns_dict(self):
        counter = TokenCounter()
        result = counter.analyze("# Section\n\nSome content here")
        assert "total" in result
        assert "by_section" in result
        assert "status" in result

    def test_status_good(self):
        counter = TokenCounter()
        short_content = "Short content " * 50  # ~350 tokens
        result = counter.analyze(short_content)
        assert result["status"] == "good"

    def test_status_critical(self):
        counter = TokenCounter()
        long_content = "word " * 4000  # ~3000+ tokens
        result = counter.analyze(long_content)
        assert result["status"] in ("warning", "critical")

    def test_by_section_parsing(self):
        counter = TokenCounter()
        content = "## Section One\nContent here\n\n## Section Two\nMore content here"
        result = counter.analyze(content)
        assert "Section One" in result["by_section"] or "Section Two" in result["by_section"]


class TestLinter:
    def test_lint_empty(self):
        linter = ClaudeMdLinter()
        result = linter.lint("")
        assert "issues" in result
        assert "score" in result

    def test_lint_good_content(self):
        linter = ClaudeMdLinter()
        content = """# My Project

## Overview
A FastAPI web application for task management.

## Tech Stack
- Python 3.11, FastAPI, SQLAlchemy
- PostgreSQL for storage
- pytest for testing

## Architecture
- `src/` — application code
- `tests/` — test suite
- `main.py` — entry point

## Conventions
- Use type hints everywhere
- Follow PEP 8

## Commands
```bash
make install   # install deps
make test      # run tests
make run       # start server
```

## What NOT to do
- Don't import from `internal/` directly
"""
        result = linter.lint(content)
        # Should have a decent score for a well-structured doc
        assert result["score"] >= 50

    def test_detects_too_long(self):
        linter = ClaudeMdLinter()
        # Create very long content
        long_content = "word " * 5000
        result = linter.lint(long_content)
        assert any(i["rule"] == "token_count" and i["severity"] in ("error", "warning")
                   for i in result["issues"])

    def test_detects_too_short(self):
        linter = ClaudeMdLinter()
        content = "This is a very short CLAUDE.md."
        result = linter.lint(content)
        assert any(i["rule"] == "token_count_minimum" for i in result["issues"])

    def test_detects_missing_sections(self):
        linter = ClaudeMdLinter()
        content = """# My Project
Just some random text without proper sections.
"""
        result = linter.lint(content)
        missing = [i for i in result["issues"] if i["rule"] == "required_section"]
        assert len(missing) > 0

    def test_detects_no_headers(self):
        linter = ClaudeMdLinter()
        content = "Just a paragraph with no headers at all. " * 20
        result = linter.lint(content)
        assert any(i["rule"] == "no_headers" for i in result["issues"])

    def test_detects_placeholders(self):
        linter = ClaudeMdLinter()
        content = """## Overview
[TODO: add description here]

## Stack
[fill in your stack]
"""
        result = linter.lint(content)
        assert any(i["rule"] == "placeholders" for i in result["issues"])

    def test_good_content_has_high_score(self):
        linter = ClaudeMdLinter()
        content = """## Overview
A production web API built with FastAPI and PostgreSQL.

## Tech Stack
- Python 3.11, FastAPI, SQLAlchemy 2.0, Pydantic v2
- PostgreSQL with asyncpg driver
- pytest + httpx for testing

## Architecture
- `src/api/` — route handlers
- `src/models/` — SQLAlchemy models
- `src/services/` — business logic
- `tests/` — pytest test suite

## Conventions
- All routes use dependency injection for db sessions
- Use Pydantic schemas for request/response validation
- Never put business logic in route handlers

## Commands
```bash
make dev     # Start with hot reload
make test    # Run tests with coverage
make migrate # Run Alembic migrations
```

## Gotchas
- Never commit .env files (use .env.example as template)
- The database schema is in `migrations/` not auto-generated
"""
        result = linter.lint(content)
        assert result["score"] >= 70

    def test_lint_file_not_found(self):
        linter = ClaudeMdLinter("/tmp")
        result = linter.lint_file("nonexistent.md")
        assert result["errors"] == 1
        assert any(i["rule"] == "file_exists" for i in result["issues"])

    def test_format_report_returns_string(self):
        linter = ClaudeMdLinter()
        content = "## Test\nSome content."
        result = linter.lint(content)
        report = linter.format_report(result, content=content)
        assert isinstance(report, str)
        assert "Score" in report


class TestStalenessChecker:
    def test_no_file_returns_100(self):
        from claudemd.analyzers.staleness_checker import StalenessChecker
        with tempfile.TemporaryDirectory() as tmpdir:
            checker = StalenessChecker(tmpdir)
            result = checker.check()
            assert result["score"] == 100
            assert result["exists"] is False

    def test_fresh_file_returns_low_score(self):
        from claudemd.analyzers.staleness_checker import StalenessChecker
        with tempfile.TemporaryDirectory() as tmpdir:
            # Write a CLAUDE.md that matches the project
            with open(os.path.join(tmpdir, "CLAUDE.md"), "w") as f:
                f.write("# My Project\n\n## Overview\nA simple project.\n")
            checker = StalenessChecker(tmpdir)
            result = checker.check()
            assert result["exists"] is True
            assert isinstance(result["score"], int)

    def test_detects_dead_file_ref(self):
        from claudemd.analyzers.staleness_checker import StalenessChecker
        with tempfile.TemporaryDirectory() as tmpdir:
            with open(os.path.join(tmpdir, "CLAUDE.md"), "w") as f:
                f.write("# Project\n\nMain entry is `deleted_file.py`.\n")
            checker = StalenessChecker(tmpdir)
            result = checker.check()
            dead_refs = [i for i in result["issues"] if i["type"] == "dead_file_reference"]
            assert len(dead_refs) >= 1

    def test_detects_dead_dir_ref(self):
        from claudemd.analyzers.staleness_checker import StalenessChecker
        with tempfile.TemporaryDirectory() as tmpdir:
            with open(os.path.join(tmpdir, "CLAUDE.md"), "w") as f:
                f.write("# Project\n\nCode lives in `oldmodule/`.\n")
            checker = StalenessChecker(tmpdir)
            result = checker.check()
            dead_dirs = [i for i in result["issues"] if i["type"] == "dead_dir_reference"]
            assert len(dead_dirs) >= 1

    def test_format_report_string(self):
        from claudemd.analyzers.staleness_checker import StalenessChecker
        with tempfile.TemporaryDirectory() as tmpdir:
            checker = StalenessChecker(tmpdir)
            report = checker.format_report()
            assert isinstance(report, str)
