#!/usr/bin/env python3
"""done-watcher.py 테스트 스위트"""

import json
import os
import sys
import tempfile
from datetime import datetime, timezone
from pathlib import Path

import pytest

# 임시 WORKSPACE_ROOT 설정
_TEMP_WORKSPACE = tempfile.mkdtemp()
os.environ["WORKSPACE_ROOT"] = _TEMP_WORKSPACE

sys.path.insert(0, str(Path(__file__).parent.parent))

# __import__ 사용: Any 타입 반환으로 동적 속성 할당 허용
dw = __import__("done-watcher")


class TestExtractTeamFromDoneFile:
    """done 파일명에서 팀 추출 테스트"""

    def test_extract_dev1_team(self, tmp_path):
        """task-648.1.dev1.done → dev1"""
        done_file = tmp_path / "task-648.1.dev1.done"
        result = dw.extract_team_from_done_file(done_file)
        assert result == "dev1"

    def test_extract_dev2_team(self, tmp_path):
        """task-648.1.dev2.done → dev2"""
        done_file = tmp_path / "task-648.1.dev2.done"
        result = dw.extract_team_from_done_file(done_file)
        assert result == "dev2"

    def test_extract_dev3_team(self, tmp_path):
        """task-648.1.dev3.done → dev3"""
        done_file = tmp_path / "task-648.1.dev3.done"
        result = dw.extract_team_from_done_file(done_file)
        assert result == "dev3"

    def test_no_team_in_filename_falls_back_to_timers(self, tmp_path):
        """팀 정보 없으면 task-timers.json 조회"""
        # task-timers.json 생성
        timer_file = tmp_path / "memory" / "task-timers.json"
        timer_file.parent.mkdir(parents=True)
        timer_file.write_text(json.dumps({"tasks": {"task-648.1": {"team_id": "dev3-team"}}}))
        dw.WORKSPACE_ROOT = str(tmp_path)

        done_file = tmp_path / "task-648.1.done"
        result = dw.extract_team_from_done_file(done_file)
        assert result == "dev3-team"

    def test_no_team_no_timers_returns_none(self, tmp_path):
        """팀 정보 없고 timers도 없으면 None"""
        dw.WORKSPACE_ROOT = str(tmp_path)
        done_file = tmp_path / "task-648.1.done"
        result = dw.extract_team_from_done_file(done_file)
        assert result is None


class TestSetBotIdle:
    """봇 상태 idle 전환 테스트"""

    def test_set_idle_from_processing(self, tmp_path):
        """processing → idle 전환 성공"""
        bot_file = tmp_path / "bot-activity.json"
        bot_file.parent.mkdir(parents=True, exist_ok=True)
        bot_file.write_text(
            json.dumps({"bots": {"dev1-team": {"status": "processing", "since": "2026-03-17T00:00:00Z"}}})
        )
        dw.BOT_ACTIVITY_FILE = bot_file

        result = dw.set_bot_idle("dev1-team")
        assert result is True

        saved = json.loads(bot_file.read_text())
        assert saved["bots"]["dev1-team"]["status"] == "idle"

    def test_already_idle_returns_true(self, tmp_path):
        """이미 idle이면 True 반환 (변경 없음)"""
        bot_file = tmp_path / "bot-activity.json"
        bot_file.parent.mkdir(parents=True, exist_ok=True)
        bot_file.write_text(json.dumps({"bots": {"dev1-team": {"status": "idle", "since": "2026-03-17T00:00:00Z"}}}))
        dw.BOT_ACTIVITY_FILE = bot_file

        result = dw.set_bot_idle("dev1-team")
        assert result is True

    def test_unknown_team_returns_false(self, tmp_path):
        """존재하지 않는 팀 → False"""
        bot_file = tmp_path / "bot-activity.json"
        bot_file.parent.mkdir(parents=True, exist_ok=True)
        bot_file.write_text(json.dumps({"bots": {}}))
        dw.BOT_ACTIVITY_FILE = bot_file
        dw.DONE_PROTOCOL_LOG = tmp_path / "log.log"

        result = dw.set_bot_idle("unknown-team")
        assert result is False

    def test_idle_timestamp_updated(self, tmp_path):
        """idle 전환 시 since 필드 업데이트"""
        bot_file = tmp_path / "bot-activity.json"
        bot_file.parent.mkdir(parents=True, exist_ok=True)
        bot_file.write_text(json.dumps({"bots": {"dev2": {"status": "processing", "since": "2026-01-01T00:00:00Z"}}}))
        dw.BOT_ACTIVITY_FILE = bot_file
        dw.DONE_PROTOCOL_LOG = tmp_path / "log.log"

        dw.set_bot_idle("dev2")

        saved = json.loads(bot_file.read_text())
        # since가 2026-03으로 업데이트 되었는지 확인
        assert saved["bots"]["dev2"]["since"].startswith("2026-03")


class TestScanDoneFiles:
    """done 파일 스캔 테스트"""

    def test_scan_finds_done_files(self, tmp_path):
        """처리 안 된 .done 파일 찾기"""
        events_dir = tmp_path / "memory" / "events"
        events_dir.mkdir(parents=True)
        (events_dir / "task-648.1.done").write_text("{}")
        (events_dir / "task-648.2.done").write_text("{}")
        dw.EVENTS_DIR = events_dir

        result = dw.scan_done_files()
        assert len(result) == 2

    def test_scan_empty_dir(self, tmp_path):
        """done 파일 없으면 빈 리스트"""
        events_dir = tmp_path / "memory" / "events"
        events_dir.mkdir(parents=True)
        dw.EVENTS_DIR = events_dir

        result = dw.scan_done_files()
        assert result == []

    def test_scan_ignores_non_done_files(self, tmp_path):
        """done이 아닌 파일은 제외"""
        events_dir = tmp_path / "memory" / "events"
        events_dir.mkdir(parents=True)
        (events_dir / "task-648.1.failed").write_text("{}")
        (events_dir / "some-file.json").write_text("{}")
        dw.EVENTS_DIR = events_dir

        result = dw.scan_done_files()
        assert result == []


class TestProcessDoneFiles:
    """done 파일 처리 통합 테스트"""

    def test_process_done_file_sets_bot_idle(self, tmp_path):
        """done 파일 감지 → 봇 idle 전환"""
        events_dir = tmp_path / "memory" / "events"
        events_dir.mkdir(parents=True)

        # done 파일에 팀 정보 포함
        (events_dir / "task-648.1.dev1.done").write_text("{}")

        # bot-activity.json 생성
        bot_file = events_dir / "bot-activity.json"
        bot_file.write_text(json.dumps({"bots": {"dev1": {"status": "processing", "since": "2026-03-17T00:00:00Z"}}}))

        dw.EVENTS_DIR = events_dir
        dw.BOT_ACTIVITY_FILE = bot_file
        dw.DONE_PROTOCOL_LOG = tmp_path / "log.log"

        processed = dw.process_done_files()
        assert processed == 1

        saved = json.loads(bot_file.read_text())
        assert saved["bots"]["dev1"]["status"] == "idle"

    def test_process_no_done_files(self, tmp_path):
        """done 파일 없으면 0 반환"""
        events_dir = tmp_path / "memory" / "events"
        events_dir.mkdir(parents=True)
        dw.EVENTS_DIR = events_dir
        dw.DONE_PROTOCOL_LOG = tmp_path / "log.log"

        processed = dw.process_done_files()
        assert processed == 0


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
