import json
import os
import tempfile
import unittest
from unittest import mock

import server
from server import TREND_BREAK_LIVE_INTERVAL_SEC, trend_break_live_due


class TrendBreakRealtimeTest(unittest.TestCase):
    def test_live_scheduler_due_respects_interval(self):
        now_ts = 1_000.0
        self.assertTrue(trend_break_live_due({}, now_ts=now_ts))
        self.assertFalse(trend_break_live_due(
            {"last_attempt_ts": now_ts - TREND_BREAK_LIVE_INTERVAL_SEC + 1},
            now_ts=now_ts,
        ))
        self.assertTrue(trend_break_live_due(
            {"last_attempt_ts": now_ts - TREND_BREAK_LIVE_INTERVAL_SEC},
            now_ts=now_ts,
        ))

    def test_live_runner_records_current_scan_result(self):
        with tempfile.TemporaryDirectory() as tmp:
            state_path = os.path.join(tmp, "live_state.json")
            log_path = os.path.join(tmp, "live.log")
            result_path = os.path.join(tmp, "trend_break_results.json")
            with open(result_path, "w", encoding="utf-8") as handle:
                json.dump({
                    "timestamp_iso": "2026-07-30T09:02:00+07:00",
                    "candidate_count": 4,
                    "universe_count": 820,
                    "snapshot_phase": "LIVE",
                }, handle)

            completed = mock.Mock(returncode=0, stdout="scan ok\n")
            with (
                mock.patch.object(server, "TREND_BREAK_LIVE_STATE_FILE", state_path),
                mock.patch.object(server, "TREND_BREAK_LIVE_LOG_FILE", log_path),
                mock.patch.object(server.os, "getcwd", return_value=tmp),
                mock.patch.object(server, "read_job_status", return_value={"status": "idle"}),
                mock.patch.object(server.subprocess, "run", return_value=completed),
            ):
                ok, state = server.run_trend_break_live_scan(trigger="test")

            self.assertTrue(ok)
            self.assertEqual(state["status"], "completed")
            self.assertEqual(state["candidate_count"], 4)
            self.assertEqual(state["universe_count"], 820)
            self.assertEqual(state["phase"], "LIVE")
            with open(log_path, "r", encoding="utf-8") as handle:
                self.assertIn("scan ok", handle.read())

    def test_market_open_tick_starts_scan_without_manual_request(self):
        with (
            mock.patch.object(server, "TREND_BREAK_LIVE_ENABLED", True),
            mock.patch.object(server, "is_market_open", return_value=True),
            mock.patch.object(server, "read_trend_break_live_state", return_value={}),
            mock.patch.object(
                server,
                "run_trend_break_live_scan",
                return_value=(True, {"status": "completed"}),
            ) as run_scan,
        ):
            ok, state = server.trend_break_live_tick(now_ts=1_000.0)

        self.assertTrue(ok)
        self.assertEqual(state["status"], "completed")
        run_scan.assert_called_once_with(trigger="auto-market")


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