"""SimClock:连续模拟时钟(真实时间 × 倍率),v2 世界的唯一时间源。

- 默认 30×(1 真实秒 = 30 模拟秒,一夜 10 模拟小时 ≈ 20 真实分钟);
- 倍率运行时可调(造物主加速 / 活跃对话自动降速),调整时保持模拟时刻连续;
- 可注入 time_fn 以便测试确定性(手动拨表)。
"""

from __future__ import annotations

import time
from typing import Callable

_PERIODS = [(5, "凌晨"), (9, "清晨"), (12, "上午"), (14, "正午"), (18, "下午"), (22, "夜晚"), (24, "深夜")]


class SimClock:
    def __init__(self, *, rate: float = 30.0, start_hour: float = 21.0,
                 time_fn: Callable[[], float] | None = None) -> None:
        self._time_fn = time_fn or time.monotonic
        self.rate = rate
        self._anchor_real = self._time_fn()
        self._anchor_sim = start_hour * 3600.0  # 模拟秒
        self._paused = False

    # —— 读 ——
    @property
    def sim_seconds(self) -> float:
        if self._paused:
            return self._anchor_sim
        return self._anchor_sim + (self._time_fn() - self._anchor_real) * self.rate

    @property
    def sim_hours(self) -> float:
        return self.sim_seconds / 3600.0

    @property
    def day(self) -> int:
        return int(self.sim_seconds // 86400) + 1

    @property
    def hour(self) -> float:
        return (self.sim_seconds % 86400) / 3600.0

    def label(self) -> str:
        h = self.hour
        period = next(name for limit, name in _PERIODS if h < limit)
        return f"第{self.day}天 {int(h):02d}:{int((h % 1) * 60):02d} {period}"

    # —— 控 ——
    def set_rate(self, rate: float) -> None:
        """变速:先把当前模拟时刻定格为新锚点,保证时间连续不跳变。"""
        self._anchor_sim = self.sim_seconds
        self._anchor_real = self._time_fn()
        self.rate = max(0.1, rate)

    def pause(self) -> None:
        self._anchor_sim = self.sim_seconds
        self._anchor_real = self._time_fn()
        self._paused = True

    def resume(self) -> None:
        self._anchor_real = self._time_fn()
        self._paused = False

    def real_seconds_until(self, sim_at: float) -> float:
        """距离模拟时刻 sim_at 还需等待的真实秒数(供调度器睡眠)。"""
        return max(0.0, (sim_at - self.sim_seconds) / self.rate)
