"""Tests for the Watch feature."""

import tempfile
from pathlib import Path
from unittest.mock import AsyncMock, patch

import pytest

from alive.core.watch import (
    SkillSuggestion,
    _find_history_file,
    _parse_suggestions,
    _read_history,
    _sanitize_commands,
)


class TestFindHistoryFile:
    def test_finds_from_histfile_env(self, tmp_path):
        hist = tmp_path / ".custom_history"
        hist.write_text("ls\ncd /tmp\n")

        with patch.dict("os.environ", {"HISTFILE": str(hist)}):
            result = _find_history_file()
        assert result == hist

    def test_finds_zsh_history(self, tmp_path):
        with patch("alive.core.watch.Path.home", return_value=tmp_path):
            zsh_hist = tmp_path / ".zsh_history"
            zsh_hist.write_text("ls\ncd\n")
            with patch.dict("os.environ", {}, clear=True):
                result = _find_history_file()
            assert result == zsh_hist

    def test_returns_none_when_no_history(self, tmp_path):
        with patch("alive.core.watch.Path.home", return_value=tmp_path):
            with patch.dict("os.environ", {}, clear=True):
                result = _find_history_file()
            assert result is None


class TestReadHistory:
    def test_reads_plain_history(self, tmp_path):
        hist = tmp_path / "history"
        hist.write_text("ls\ncd /tmp\npwd\ngit status\n")

        result = _read_history(hist, n_lines=3)
        assert result == ["cd /tmp", "pwd", "git status"]

    def test_reads_zsh_extended_format(self, tmp_path):
        hist = tmp_path / ".zsh_history"
        hist.write_text(
            ": 1700000000:0;git add .\n"
            ": 1700000001:0;git commit -m 'test'\n"
            ": 1700000002:0;git push\n"
        )

        result = _read_history(hist, n_lines=10)
        assert result == ["git add .", "git commit -m 'test'", "git push"]

    def test_handles_empty_file(self, tmp_path):
        hist = tmp_path / "empty"
        hist.write_text("")
        result = _read_history(hist)
        assert result == []

    def test_limits_lines(self, tmp_path):
        hist = tmp_path / "big"
        hist.write_text("\n".join(f"cmd_{i}" for i in range(500)))

        result = _read_history(hist, n_lines=50)
        assert len(result) == 50
        assert result[-1] == "cmd_499"


class TestSanitizeCommands:
    def test_redacts_tokens(self):
        cmds = ["curl -H 'Authorization: token=abc123secret'"]
        result = _sanitize_commands(cmds)
        assert "abc123secret" not in result[0]
        assert "<REDACTED>" in result[0]

    def test_redacts_export_secrets(self):
        cmds = ["export GITHUB_TOKEN=ghp_verysecret123"]
        result = _sanitize_commands(cmds)
        assert "ghp_verysecret123" not in result[0]
        assert "<REDACTED>" in result[0]

    def test_leaves_normal_commands(self):
        cmds = ["ls -la", "git status", "npm install"]
        result = _sanitize_commands(cmds)
        assert result == cmds


class TestParseSuggestions:
    def test_parses_valid_suggestions(self):
        response = """
Found some patterns:

```suggestion
name: git_commit_push
description: Automate git add, commit, and push workflow
pattern: git add . && git commit -m '...' && git push
frequency: 8 times
build_command: alive build "a skill that stages all changes, commits with a message, and pushes to origin"
```

```suggestion
name: docker_rebuild
description: Rebuild and restart Docker containers
pattern: docker compose down && docker compose build && docker compose up -d
frequency: 5 times
build_command: alive build "a skill that rebuilds and restarts docker compose services"
```
"""
        result = _parse_suggestions(response)
        assert len(result) == 2
        assert result[0].name == "git_commit_push"
        assert "git add" in result[0].pattern
        assert result[0].frequency == "8 times"
        assert result[1].name == "docker_rebuild"

    def test_handles_no_patterns(self):
        result = _parse_suggestions("NO_PATTERNS_FOUND")
        assert result == []

    def test_skips_malformed_blocks(self):
        response = """
```suggestion
name: good_one
description: A valid suggestion
pattern: npm test
frequency: 10 times
build_command: alive build "run tests"
```

```suggestion
name:
description:
```
"""
        result = _parse_suggestions(response)
        assert len(result) == 1
        assert result[0].name == "good_one"

    def test_empty_response(self):
        result = _parse_suggestions("")
        assert result == []
