from __future__ import annotations

import tempfile
import unittest
from pathlib import Path

from backend.features.alerts.service import AlertService
from database import ReviewDatabase


class AlertServiceTests(unittest.TestCase):
    def setUp(self) -> None:
        self.temp = tempfile.TemporaryDirectory()
        self.database = ReviewDatabase(Path(self.temp.name) / "review.db")
        self.owner = self.database.create_user("alert_owner", "salt", "hash")
        self.other = self.database.create_user("alert_other", "salt", "hash")
        self.service = AlertService(self.database)

    def tearDown(self) -> None:
        self.temp.cleanup()

    def test_future_manual_alert_is_visible_but_not_unread_until_due(self):
        alert_id = self.service.create_manual(
            self.owner["id"],
            {
                "title": "复核承接",
                "content": "开盘不及预期则退出观察",
                "code": "002141",
                "remind_date": "2026-07-25",
            },
        )
        before = self.service.list_alerts(self.owner["id"], "all", "2026-07-22")
        due = self.service.list_alerts(self.owner["id"], "unread", "2026-07-25")

        self.assertEqual(before["items"][0]["id"], alert_id)
        self.assertFalse(before["items"][0]["due"])
        self.assertEqual(before["unread_count"], 0)
        self.assertEqual(due["unread_count"], 1)
        self.assertTrue(due["items"][0]["due"])

    def test_alert_reads_and_mutations_are_scoped_to_owner(self):
        alert_id = self.database.save_alert(
            self.owner["id"], "manual", "甲的提醒", "", "20260722", "", "owner-only"
        )
        self.assertEqual(
            self.service.list_alerts(self.other["id"], "all", "2026-07-22")["items"], []
        )
        self.assertFalse(self.database.mark_alert_read(self.other["id"], alert_id))
        self.assertFalse(self.database.delete_alert(self.other["id"], alert_id))
        self.assertTrue(self.database.mark_alert_read(self.owner["id"], alert_id))
        self.assertEqual(
            self.service.list_alerts(self.owner["id"], "all", "2026-07-22")["unread_count"], 0
        )
        self.assertTrue(self.database.delete_alert(self.owner["id"], alert_id))

    def test_strategy_alerts_are_idempotent(self):
        tracking = {
            "batches": [
                {
                    "run_id": 9,
                    "strategy_name": "修复策略",
                    "items": [{"code": "002141"}, {"code": "600000"}],
                    "summary": {
                        "observed": 2,
                        "completed": 2,
                        "t1_win_rate": 50.0,
                        "average_t5": 3.25,
                    },
                }
            ]
        }
        self.service.sync_strategy_tracking(self.owner["id"], tracking)
        self.service.sync_strategy_tracking(self.owner["id"], tracking)
        alerts = self.database.list_alerts(
            self.owner["id"], "99991231", unread_only=False
        )

        self.assertEqual(len(alerts), 2)
        self.assertEqual({item["kind"] for item in alerts}, {"strategy_t1", "strategy_t5"})

    def test_mark_all_only_changes_due_alerts(self):
        self.database.save_alert(
            self.owner["id"], "manual", "今日", "", "20260722", "", "due"
        )
        self.database.save_alert(
            self.owner["id"], "manual", "未来", "", "20260723", "", "future"
        )
        self.assertEqual(
            self.database.mark_all_alerts_read(self.owner["id"], "20260722"), 1
        )
        future = self.service.list_alerts(self.owner["id"], "unread", "2026-07-23")
        self.assertEqual([item["title"] for item in future["items"]], ["未来"])


if __name__ == "__main__":
    unittest.main()
