"""
ADR-050 Telegram 互動式 Incident 管理 2.0 測試
==============================================
驗證 6鍵 Inline Keyboard + detail/reanalyze/history 訊息格式

測試策略 (遵循 feedback_no_mock_testing.md):
- 直接測試訊息格式化邏輯與 keyboard 結構
- 透過 source code 驗證實作正確性（不依賴 Runtime）
- 不發送實際 Telegram 訊息，不呼叫外部 API

版本: v1.0
建立: 2026-04-01 (台北時區)
建立者: Claude Code (ADR-050 P2 Tests)
"""


# =============================================================================
# Test: _build_inline_keyboard 6鍵結構
# =============================================================================

class TestInlineKeyboardStructure:
    """驗證 ADR-050 6鍵 Inline Keyboard 結構"""

    def _read_gateway(self) -> str:
        with open("src/services/telegram_gateway.py", encoding="utf-8") as f:
            return f.read()

    def test_keyboard_row1_approve_button_exists(self):
        """第一行有 ✅ 批准 按鈕"""
        assert "✅ 批准" in self._read_gateway()

    def test_keyboard_row1_reject_button_exists(self):
        """第一行有 ❌ 拒絕 按鈕"""
        assert "❌ 拒絕" in self._read_gateway()

    def test_keyboard_row1_silence_button_exists(self):
        """第一行有 🔕 靜默 按鈕"""
        assert "🔕 靜默" in self._read_gateway()

    def test_keyboard_row2_detail_uses_incident_id_format(self):
        """📋 詳情 按鈕使用 detail:{incident_id} 格式"""
        source = self._read_gateway()
        assert '📋 詳情' in source
        assert 'f"detail:{incident_id}"' in source

    def test_keyboard_row2_reanalyze_uses_incident_id_format(self):
        """🔄 重診 按鈕使用 reanalyze:{incident_id} 格式"""
        source = self._read_gateway()
        assert '🔄 重診' in source
        assert 'f"reanalyze:{incident_id}"' in source

    def test_keyboard_row2_history_uses_incident_id_format(self):
        """📊 歷史 按鈕使用 history:{incident_id} 格式"""
        source = self._read_gateway()
        assert '📊 歷史' in source
        assert 'f"history:{incident_id}"' in source

    def test_reanalyze_no_longer_placeholder(self):
        """reanalyze 不再是 placeholder（功能開發中已移除）"""
        assert "功能開發中" not in self._read_gateway(), (
            "reanalyze 仍是 placeholder！應已實作真實邏輯。"
        )


# =============================================================================
# Test: detail 訊息格式
# =============================================================================

class TestDetailMessageFormat:
    """驗證 _send_incident_detail 訊息格式與資料來源"""

    def _read_gateway(self) -> str:
        with open("src/services/telegram_gateway.py", encoding="utf-8") as f:
            return f.read()

    def test_detail_method_exists(self):
        """_send_incident_detail 方法存在"""
        assert "_send_incident_detail" in self._read_gateway()

    def test_detail_uses_real_db(self):
        """detail 從真實 DB 取得資料（IncidentRepository）"""
        source = self._read_gateway()
        assert "get_incident_repository" in source
        assert "repo.get_by_id(incident_id)" in source

    def test_detail_handles_not_found(self):
        """detail 處理找不到事件的情況"""
        assert "找不到事件" in self._read_gateway()

    def test_detail_shows_incident_id(self):
        """detail 訊息顯示 INC-ID"""
        assert "incident.incident_id" in self._read_gateway()

    def test_detail_shows_severity(self):
        """detail 訊息顯示嚴重度"""
        assert "incident.severity" in self._read_gateway()

    def test_detail_includes_truth_chain_gateway_summary(self):
        """detail 顯示 AwoooP truth-chain / MCP Gateway / automation quality / agent evidence 摘要"""
        source = self._read_gateway()
        assert "fetch_truth_chain" in source
        assert "_format_gateway_summary_lines" in source
        assert "_format_automation_quality_lines" in source
        assert "_format_awooop_agent_evidence_lines" in source
        assert "AI Agent 證據鏈" in source
        assert "MCP Gateway" in source
        assert "自動化品質" in source


# =============================================================================
# Test: history 訊息格式
# =============================================================================

class TestHistoryMessageFormat:
    """驗證 _send_incident_history 訊息格式與資料來源"""

    def _read_gateway(self) -> str:
        with open("src/services/telegram_gateway.py", encoding="utf-8") as f:
            return f.read()

    def test_history_method_exists(self):
        """_send_incident_history 方法存在"""
        assert "_send_incident_history" in self._read_gateway()

    def test_history_uses_real_frequency_stats(self):
        """history 使用真實頻率統計資料"""
        source = self._read_gateway()
        assert "count_1h" in source
        assert "count_24h" in source
        assert "count_7d" in source
        assert "count_30d" in source

    def test_history_handles_no_stats(self):
        """history 處理無頻率統計資料的情況 (Phase 27: 舊 incident 無 DB 快照)"""
        source = self._read_gateway()
        # Phase 27 雙層策略: 無快照時顯示說明，而非舊版 "無頻率統計資料"
        assert "無建立時快照" in source or "無頻率統計資料" in source

    def test_history_includes_db_truth_chain_fallback(self):
        """history 也顯示 DB truth-chain，避免 Redis TTL 缺口讓處置階段失真"""
        source = self._read_gateway()
        assert "DB Truth-chain" in source
        assert "incident_history_truth_chain_summary_failed" in source
        assert "_format_automation_quality_lines" in source
        assert "_format_awooop_agent_evidence_lines" in source


# =============================================================================
# Test: reanalyze 訊息格式
# =============================================================================

class TestReanalyzeMessageFormat:
    """驗證 _send_reanalyze_result 訊息格式"""

    def _read_gateway(self) -> str:
        with open("src/services/telegram_gateway.py", encoding="utf-8") as f:
            return f.read()

    def test_reanalyze_result_method_exists(self):
        """_send_reanalyze_result 方法存在"""
        assert "_send_reanalyze_result" in self._read_gateway()

    def test_reanalyze_calls_trigger_reanalysis(self):
        """reanalyze handler 呼叫 trigger_reanalysis"""
        assert "trigger_reanalysis" in self._read_gateway()

    def test_reanalyze_uses_lazy_import(self):
        """reanalyze 使用 lazy import 避免循環依賴"""
        assert "from src.services.incident_service import get_incident_service" in self._read_gateway()

    def test_reanalyze_scheduled_message(self):
        """reanalyze 有「重診已排程」訊息"""
        assert "重診已排程" in self._read_gateway()

    def test_reanalyze_in_progress_message(self):
        """reanalyze 有「重診進行中」訊息"""
        assert "重診進行中" in self._read_gateway()

    def test_reanalyze_failure_message(self):
        """reanalyze 有「重診失敗」訊息"""
        assert "重診失敗" in self._read_gateway()

    def test_reanalyze_uses_html_escape(self):
        """reanalyze 訊息使用 html.escape 防 XSS"""
        source = self._read_gateway()
        # _send_reanalyze_result 之後應有 html.escape 呼叫
        reanalyze_section = source.split("_send_reanalyze_result")[1] if "_send_reanalyze_result" in source else ""
        assert "html.escape" in reanalyze_section


# =============================================================================
# Test: trigger_reanalysis 邏輯結構
# =============================================================================

class TestTriggerReanalysisStructure:
    """驗證 trigger_reanalysis() 方法結構（不連接真實 Redis）"""

    def _read_service(self) -> str:
        with open("src/services/incident_service.py", encoding="utf-8") as f:
            return f.read()

    def test_method_exists(self):
        """trigger_reanalysis 方法存在於 IncidentService"""
        assert "async def trigger_reanalysis" in self._read_service()

    def test_uses_redis_setnx(self):
        """使用 Redis SETNX (nx=True) 去重"""
        assert "nx=True" in self._read_service()

    def test_dedup_key_format(self):
        """去重 key 格式為 reanalyze_dedup:{incident_id}"""
        assert '"reanalyze_dedup:"' in self._read_service() or "reanalyze_dedup:" in self._read_service()

    def test_ttl_is_600_seconds(self):
        """去重 TTL 為 600 秒（10 分鐘）"""
        assert "600" in self._read_service()

    def test_returns_triggered_key(self):
        """回傳值包含 triggered key"""
        assert '"triggered"' in self._read_service()

    def test_returns_message_key(self):
        """回傳值包含 message key"""
        assert '"message"' in self._read_service()

    def test_returns_already_analyzing_key(self):
        """回傳值包含 already_analyzing key"""
        assert '"already_analyzing"' in self._read_service()

    def test_deletes_key_on_not_found(self):
        """找不到 incident 時刪除去重 key（允許重試）"""
        assert "redis_client.delete(dedup_key)" in self._read_service()

    def test_fallback_to_episodic_memory(self):
        """Working Memory 找不到時 fallback 到 Episodic Memory (DB)"""
        source = self._read_service()
        assert "get_from_working_memory" in source
        assert "get_from_episodic_memory" in source
