"""
tests/test_roi_report_service.py
─────────────────────────────────────────────────────────────────
Operation Ollama-First v5.0 / Phase 24 — ROI 月報生成器驗證
"""

from datetime import datetime
import logging
from unittest.mock import patch

import pytest


def test_baseline_constants():
    """戰前 baseline 應有 5 個必要欄位"""
    from services.roi_report_service import BASELINE

    required = {'gemini_monthly_tokens', 'gemini_monthly_cost_usd',
                'nim_monthly_tokens', 'ollama_monthly_tokens',
                'total_monthly_cost_usd'}
    assert required.issubset(BASELINE.keys())
    assert BASELINE['gemini_monthly_tokens'] == 50_000_000
    assert BASELINE['gemini_monthly_cost_usd'] == 20.0


def test_last_month_range_january():
    """1 月跑時上月應為去年 12 月"""
    from services.roi_report_service import _last_month_range

    today = datetime(2026, 1, 5)
    last_start, this_start = _last_month_range(today)
    assert last_start == datetime(2025, 12, 1)
    assert this_start == datetime(2026, 1, 1)


def test_last_month_range_normal_month():
    from services.roi_report_service import _last_month_range

    today = datetime(2026, 5, 15)
    last_start, this_start = _last_month_range(today)
    assert last_start == datetime(2026, 4, 1)
    assert this_start == datetime(2026, 5, 1)


def test_render_roi_report_with_savings():
    """戰役後成功攔截 Gemini → 訊息含「攔截」+ 達標 ✅"""
    from services.roi_report_service import render_roi_report

    stats = {
        'period_label': '2026年04月',
        'period_start': datetime(2026, 4, 1),
        'period_end': datetime(2026, 5, 1),
        'ai_total_tokens': 80_000_000,
        'ai_total_cost': 12.0,
        'ai_total_calls': 5000,
        'ollama_calls': 4000,
        'gemini_calls': 800,
        'claude_calls': 100,
        'nim_calls': 100,
        'rag_hit_calls': 200,
        'cache_hit_calls': 150,
        'gemini_tokens': 35_000_000,  # 戰前 50M → 省 15M (30%)
        'gemini_cost': 14.0,           # 戰前 $20 → 省 $6
        'claude_cost': 5.0,
        'mcp_total': 180,
        'mcp_cache_hits': 50,
        'rag_total': 800,
        'rag_saved': 250,              # 31% RAG 攔截率
        'rag_avg_feedback': 4.2,
    }
    msg = render_roi_report(stats)

    assert '2026年04月' in msg
    assert '攔截' in msg
    assert '15,000,000' in msg or '15M' in msg or '15,000' in msg
    assert '$6' in msg or '6.00' in msg
    assert '✅' in msg  # Gemini -23.5% 目標達標


def test_render_roi_report_below_target():
    """未達 -23.5% 目標 → 訊息含 ⚠️"""
    from services.roi_report_service import render_roi_report

    stats = {
        'period_label': '2026年04月',
        'period_start': datetime(2026, 4, 1),
        'period_end': datetime(2026, 5, 1),
        'ai_total_tokens': 80_000_000, 'ai_total_cost': 18.0, 'ai_total_calls': 5000,
        'ollama_calls': 1000, 'gemini_calls': 3000, 'claude_calls': 500, 'nim_calls': 500,
        'rag_hit_calls': 50, 'cache_hit_calls': 30,
        'gemini_tokens': 45_000_000,  # 戰前 50M → 只省 10% < 23%
        'gemini_cost': 18.0, 'claude_cost': 5.0,
        'mcp_total': 100, 'mcp_cache_hits': 10,
        'rag_total': 200, 'rag_saved': 30, 'rag_avg_feedback': 3.5,
    }
    msg = render_roi_report(stats)

    assert '⚠️' in msg  # 未達標標記


def test_render_empty_stats():
    """空 stats → 預設失敗訊息"""
    from services.roi_report_service import render_roi_report

    assert '⚠️' in render_roi_report({})


def test_render_roi_report_logs_feedback_block_failure(monkeypatch, caplog):
    """反饋趨勢附加區塊失敗時，月報主體仍應產生並留下可追蹤 log。"""
    from services.roi_report_service import render_roi_report
    import services.feedback_quality_tracker as fqt

    def _raise_feedback_error(days=30):
        raise RuntimeError("feedback trend unavailable")

    monkeypatch.setattr(fqt, "compute_caller_quality_trend", _raise_feedback_error)
    caplog.set_level(logging.WARNING, logger="services.roi_report_service")

    msg = render_roi_report({
        'period_label': '2026年04月',
        'gemini_tokens': 35_000_000,
        'gemini_cost': 14.0,
        'ollama_calls': 4000,
        'gemini_calls': 800,
        'claude_calls': 100,
        'claude_cost': 5.0,
        'nim_calls': 100,
        'rag_total': 800,
        'rag_saved': 250,
        'rag_avg_feedback': 4.2,
        'mcp_total': 180,
        'mcp_cache_hits': 50,
        'cache_hit_calls': 150,
    })

    assert 'ROI 月報 2026年04月' in msg
    assert '反饋趨勢查詢失敗' in caplog.text


def test_query_last_month_stats_db_fail_returns_empty(monkeypatch):
    """DB 失敗應回 {} 不 raise"""
    from services.roi_report_service import query_last_month_stats

    class _BrokenSession:
        def execute(self, *a, **kw):
            raise RuntimeError('DB connection lost')
        def close(self):
            pass

    import services.roi_report_service as ros
    monkeypatch.setattr('database.manager.get_session', lambda: _BrokenSession())
    result = ros.query_last_month_stats()
    assert result == {}
