"""Tests for the status command."""

import importlib
import json
from pathlib import Path

import pytest
from click.testing import CliRunner

status_module = importlib.import_module("gjalla_precommit.commands.status")
cli_module = importlib.import_module("gjalla_precommit.cli")
settings_module = importlib.import_module("gjalla_precommit.config.settings")


class TestStatusCommand:
    """Tests for gjalla status command."""

    def test_status_command_exists(self):
        """Status command should be registered."""
        main = cli_module.main
        assert "status" in main.commands

    def test_status_not_in_git_repo(self, tmp_path, monkeypatch):
        """Status should work even outside git repo."""
        monkeypatch.chdir(tmp_path)
        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        # Should show "Not a git repository" in output
        assert "Git Repository" in result.output
        assert "No" in result.output or "Not a git" in result.output

    def test_status_in_git_repo(self, temp_repo, monkeypatch):
        """Status should show git repo info."""
        monkeypatch.chdir(temp_repo)
        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        assert "Git Repository" in result.output
        # Should show branch info
        assert "Branch" in result.output or "Yes" in result.output

    def test_status_no_api_key(self, temp_repo, home_dir, monkeypatch):
        """Status should show API key as missing when not configured."""
        monkeypatch.chdir(temp_repo)
        # Clear any env var
        monkeypatch.delenv("GJALLA_API_KEY", raising=False)
        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        assert "API Key" in result.output
        assert "Missing" in result.output or "not configured" in result.output.lower()

    def test_status_with_api_key(self, temp_repo, home_dir, monkeypatch):
        """Status should show API key as configured when present."""
        monkeypatch.chdir(temp_repo)
        # Create config file with API key
        config_dir = home_dir / ".gjalla"
        config_dir.mkdir(parents=True, exist_ok=True)
        (config_dir / "config.yaml").write_text("api_key: gj_test_key_12345678\n")

        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        assert "API Key" in result.output
        # Should show masked key or "Configured"
        assert "Configured" in result.output or "gj_t" in result.output

    def test_status_project_not_mapped(self, temp_repo, home_dir, monkeypatch):
        """Status should show project as not mapped when not configured."""
        monkeypatch.chdir(temp_repo)
        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        assert "Project Mapping" in result.output
        assert "Not Mapped" in result.output or "not configured" in result.output.lower()

    def test_status_exit_code_success(self, temp_repo, monkeypatch):
        """Status command should exit with 0."""
        monkeypatch.chdir(temp_repo)
        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        assert result.exit_code == 0


class TestStatusApiKeyMasking:
    """Tests for API key masking in status output."""

    def test_short_api_key_fully_masked(self, temp_repo, home_dir, monkeypatch):
        """Short API keys should be fully masked."""
        monkeypatch.chdir(temp_repo)
        config_dir = home_dir / ".gjalla"
        config_dir.mkdir(parents=True, exist_ok=True)
        # Short key (8 chars or less)
        (config_dir / "config.yaml").write_text("api_key: short\n")

        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        # Should not show the actual key in full
        assert "short" not in result.output or "****" in result.output

    def test_long_api_key_partially_masked(self, temp_repo, home_dir, monkeypatch):
        """Long API keys should show first and last 4 chars."""
        monkeypatch.chdir(temp_repo)
        config_dir = home_dir / ".gjalla"
        config_dir.mkdir(parents=True, exist_ok=True)
        (config_dir / "config.yaml").write_text("api_key: gj_test_key_very_long_12345678\n")

        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        # Should show masked format like "gj_t...5678"
        assert "Configured" in result.output


class TestStatusAttestationLog:
    """Tests for attestation log summary in status output."""

    def test_no_log_file(self, temp_repo, monkeypatch):
        """No log.jsonl shows 'No history'."""
        monkeypatch.chdir(temp_repo)
        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        assert "Attestation Log" in result.output
        assert "No history" in result.output

    def test_empty_log_file(self, temp_repo, monkeypatch):
        """Empty log.jsonl shows 0 attested."""
        monkeypatch.chdir(temp_repo)
        gjalla_dir = temp_repo / ".gjalla"
        gjalla_dir.mkdir(exist_ok=True)
        (gjalla_dir / "log.jsonl").write_text("", encoding="utf-8")
        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        assert "Attestation Log" in result.output
        assert "0 attested" in result.output

    def test_counts_attested_and_uploaded(self, temp_repo, monkeypatch):
        """Uploaded and pending commits are counted separately."""
        monkeypatch.chdir(temp_repo)
        gjalla_dir = temp_repo / ".gjalla"
        gjalla_dir.mkdir(exist_ok=True)
        entries = [
            {"commit": "aaa", "branch": "main", "synced": True},
            {"commit": "bbb", "branch": "main", "synced": True},
            {"commit": "ccc", "branch": "dev", "synced": False},
        ]
        (gjalla_dir / "log.jsonl").write_text(
            "\n".join(json.dumps(e) for e in entries) + "\n", encoding="utf-8"
        )
        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        assert "3 attested" in result.output
        assert "2 uploaded" in result.output
        assert "1 pending upload" in result.output

    def test_counts_skipped(self, temp_repo, monkeypatch):
        """Skipped attestations are counted and shown separately."""
        monkeypatch.chdir(temp_repo)
        gjalla_dir = temp_repo / ".gjalla"
        gjalla_dir.mkdir(exist_ok=True)
        entries = [
            {"commit": "aaa", "branch": "main", "synced": True},
            {"event": "attestation_skipped", "commit": "bbb", "branch": "dev", "synced": False},
            {"event": "attestation_skipped", "branch": "dev", "synced": False},
        ]
        (gjalla_dir / "log.jsonl").write_text(
            "\n".join(json.dumps(e) for e in entries) + "\n", encoding="utf-8"
        )
        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        assert "1 attested" in result.output
        assert "2 skipped" in result.output

    def test_corrupted_log_shows_error(self, temp_repo, monkeypatch):
        """Malformed log.jsonl shows error gracefully."""
        monkeypatch.chdir(temp_repo)
        gjalla_dir = temp_repo / ".gjalla"
        gjalla_dir.mkdir(exist_ok=True)
        (gjalla_dir / "log.jsonl").write_text("not json\n", encoding="utf-8")
        runner = CliRunner()
        result = runner.invoke(cli_module.main, ["status"])
        assert "Attestation Log" in result.output
        assert "Error" in result.output
