"""task-1044.1: 대시보드 기록 탭 제목 통일 + 완료 시간 표시 테스트

server.py의 get_records_list()와 ArchiveView.js의 수정을 검증합니다.
"""

import json
import os
from datetime import datetime
from pathlib import Path

import pytest

_WORKSPACE = Path(os.environ.get("WORKSPACE_ROOT", "/home/jay/workspace"))


class TestGetRecordsList:
    """get_records_list() 함수 테스트."""

    @pytest.fixture
    def server_module(self):
        """dashboard.server 모듈 로드."""
        import sys

        sys.path.insert(0, str(_WORKSPACE / "dashboard"))
        import server

        return server

    def test_function_exists(self, server_module) -> None:
        """get_records_list 함수가 존재해야 함."""
        assert hasattr(server_module, "get_records_list")

    def test_returns_list(self, server_module) -> None:
        """리스트를 반환해야 함."""
        result = server_module.get_records_list("all")
        assert isinstance(result, list)

    def test_record_has_required_fields(self, server_module) -> None:
        """각 레코드에 필수 필드가 있어야 함."""
        result = server_module.get_records_list("all")
        if len(result) > 0:
            required_fields = ["filename", "type", "title", "size", "modified", "end_time"]
            for field in required_fields:
                assert field in result[0], f"필수 필드 '{field}'가 없음"

    def test_end_time_is_iso_format(self, server_module) -> None:
        """end_time이 ISO format이어야 함."""
        result = server_module.get_records_list("all")
        if len(result) > 0:
            end_time = result[0].get("end_time")
            if end_time:
                # ISO format 파싱 테스트
                try:
                    datetime.fromisoformat(end_time)
                except ValueError:
                    pytest.fail(f"end_time이 ISO format이 아님: {end_time}")

    def test_title_not_empty(self, server_module) -> None:
        """제목이 비어있지 않아야 함."""
        result = server_module.get_records_list("all")
        for record in result[:10]:  # 최근 10개만 검사
            title = record.get("title", "")
            assert title, f"제목이 비어있음: {record['filename']}"
            assert title != record["filename"].replace(
                ".md", ""
            ), f"제목이 파일명과 동일함 (제목 추출 실패): {record['filename']}"


class TestTitleExtraction:
    """제목 추출 로직 테스트."""

    @pytest.fixture
    def server_module(self):
        """dashboard.server 모듈 로드."""
        import sys

        sys.path.insert(0, str(_WORKSPACE / "dashboard"))
        import server

        return server

    def test_extracts_title_after_colon(self, server_module) -> None:
        """콜론 뒤 제목을 추출해야 함."""
        result = server_module.get_records_list("report")
        # "task-XXXX 완료 보고서: 제목" 형식의 파일이 있는지 확인
        for record in result[:5]:
            if "완료 보고서:" in record.get("title", ""):
                # 콜론 뒤에 실제 제목이 있는지 확인
                assert ":" in record["title"]
                parts = record["title"].split(":", 1)
                if len(parts) > 1:
                    actual_title = parts[1].strip()
                    assert actual_title, f"콜론 뒤 제목이 비어있음: {record['filename']}"

    def test_fallback_to_description(self, server_module) -> None:
        """콜론이 없으면 task-timers.json의 description 사용."""
        result = server_module.get_records_list("all")
        # task-timers.json에 description이 있는 작업 확인
        task_timers_path = _WORKSPACE / "memory/task-timers.json"
        if task_timers_path.exists():
            with open(task_timers_path, encoding="utf-8") as f:
                timers = json.load(f).get("tasks", {})

            for record in result[:10]:
                task_id = record["filename"].replace(".md", "")
                if task_id in timers:
                    desc = timers[task_id].get("description", "")
                    if desc and ":" not in record.get("title", ""):
                        # description이 있고 콜론이 없으면 description 사용
                        assert record["title"] != record["filename"].replace(".md", "")


class TestEndTimeExtraction:
    """end_time 추출 로직 테스트."""

    @pytest.fixture
    def server_module(self):
        """dashboard.server 모듈 로드."""
        import sys

        sys.path.insert(0, str(_WORKSPACE / "dashboard"))
        import server

        return server

    def test_uses_task_timers_end_time(self, server_module) -> None:
        """task-timers.json의 end_time을 사용해야 함."""
        result = server_module.get_records_list("all")

        task_timers_path = _WORKSPACE / "memory/task-timers.json"
        if task_timers_path.exists():
            with open(task_timers_path, encoding="utf-8") as f:
                timers = json.load(f).get("tasks", {})

            for record in result[:10]:
                task_id = record["filename"].replace(".md", "")
                if task_id in timers:
                    expected_end_time = timers[task_id].get("end_time")
                    if expected_end_time:
                        assert record.get("end_time") == expected_end_time, f"end_time 불일치: {record['filename']}"

    def test_fallback_to_mtime(self, server_module) -> None:
        """task-timers.json에 없으면 파일 mtime 사용."""
        result = server_module.get_records_list("all")

        # task-timers.json에 없는 파일 찾기
        task_timers_path = _WORKSPACE / "memory/task-timers.json"
        timers = {}
        if task_timers_path.exists():
            with open(task_timers_path, encoding="utf-8") as f:
                timers = json.load(f).get("tasks", {})

        for record in result:
            task_id = record["filename"].replace(".md", "")
            if task_id not in timers:
                # mtime이 end_time으로 사용되었는지 확인
                assert record.get("end_time"), f"end_time이 없음: {record['filename']}"
                break


class TestArchiveViewRendering:
    """ArchiveView.js 렌더링 테스트."""

    def test_component_file_exists(self) -> None:
        """ArchiveView.js 파일이 존재해야 함."""
        path = _WORKSPACE / "dashboard/components/ArchiveView.js"
        assert path.exists()

    def test_uses_end_time_field(self) -> None:
        """end_time 필드를 사용해야 함."""
        path = _WORKSPACE / "dashboard/components/ArchiveView.js"
        content = path.read_text(encoding="utf-8")

        # end_time 필드 사용 확인
        assert "r.end_time" in content or "end_time" in content, "ArchiveView.js에서 end_time 필드를 사용하지 않음"

    def test_displays_time_not_just_date(self) -> None:
        """날짜뿐만 아니라 시간도 표시해야 함."""
        path = _WORKSPACE / "dashboard/components/ArchiveView.js"
        content = path.read_text(encoding="utf-8")

        # toLocaleString 사용 확인 (날짜+시간)
        assert "toLocaleString" in content, "toLocaleString 사용하지 않음 (시간 표시 안 됨)"

        # hour, minute 옵션 확인
        assert "hour" in content and "minute" in content, "hour/minute 옵션 없음 (시간 표시 안 됨)"


class TestIntegration:
    """통합 테스트."""

    def test_api_returns_complete_data(self) -> None:
        """API가 완전한 데이터를 반환해야 함."""
        import subprocess

        result = subprocess.run(
            ["curl", "-s", "-m", "5", "http://localhost:8000/api/records?type=all"],
            capture_output=True,
            text=True,
            timeout=10,
        )

        if result.returncode != 0 or not result.stdout.strip():
            pytest.skip("서버 실행 중 아님")

        try:
            data = json.loads(result.stdout)
        except json.JSONDecodeError:
            pytest.skip("API 응답 파싱 실패")

        if len(data) > 0:
            # 필수 필드 확인
            required = ["filename", "type", "title"]
            for field in required:
                assert field in data[0], f"API 응답에 '{field}' 필드 없음"

            # end_time 필드 확인 (서버 재시작 후에만 사용 가능)
            if "end_time" not in data[0]:
                pytest.skip("서버 재시작 필요 (end_time 필드 미반영)")

            # 제목이 파일명과 다른지 확인
            for record in data[:5]:
                assert record["title"] != record["filename"].replace(
                    ".md", ""
                ), f"제목이 파일명과 동일함: {record['filename']}"

    def test_no_empty_titles(self) -> None:
        """빈 제목이 없어야 함."""
        import subprocess

        result = subprocess.run(
            ["curl", "-s", "-m", "5", "http://localhost:8000/api/records?type=all"],
            capture_output=True,
            text=True,
            timeout=10,
        )

        if result.returncode != 0 or not result.stdout.strip():
            pytest.skip("서버 실행 중 아님")

        try:
            data = json.loads(result.stdout)
        except json.JSONDecodeError:
            pytest.skip("API 응답 파싱 실패")

        for record in data:
            title = record.get("title", "")
            assert title, f"빈 제목: {record['filename']}"
