from __future__ import annotations

from datetime import time as dt_time
from typing import Any

from backend.data.numbers import finite_number as _number


def _text(value: Any) -> str:
    if isinstance(value, (list, tuple, set)):
        return "、".join(str(item).strip() for item in value if str(item).strip())
    return str(value or "").strip()


def _prices_equal(left: Any, right: Any) -> bool:
    if left is None or right is None:
        return False
    return abs(_number(left) - _number(right)) < 0.005


def _value_percentile(value: float, population: list[float]) -> float:
    valid = sorted(item for item in population if item >= 0)
    if not valid:
        return 0.0
    below = sum(item < value for item in valid)
    equal = sum(item == value for item in valid)
    return (below + equal * 0.5) / len(valid)


def _trading_session_progress(current_time: dt_time) -> float:
    morning_start = dt_time(9, 30)
    morning_end = dt_time(11, 30)
    afternoon_start = dt_time(13, 0)
    afternoon_end = dt_time(15, 0)
    if current_time <= morning_start:
        return 0.05
    if current_time <= morning_end:
        minutes = (current_time.hour * 60 + current_time.minute) - (9 * 60 + 30)
        return max(0.05, min(0.5, minutes / 240))
    if current_time < afternoon_start:
        return 0.5
    if current_time <= afternoon_end:
        minutes = (current_time.hour * 60 + current_time.minute) - 13 * 60
        return max(0.5, min(1.0, 0.5 + minutes / 240))
    return 1.0


def _display_time(value: Any) -> str:
    raw = str(value or "").replace(":", "").zfill(6)
    if not raw.strip("0"):
        return "--"
    return f"{raw[:2]}:{raw[2:4]}:{raw[4:6]}"


def _realtime_market_status(current_time: dt_time) -> str:
    if current_time < dt_time(9, 25):
        return "pre_open"
    if current_time < dt_time(9, 30):
        return "auction"
    if current_time <= dt_time(11, 30) or dt_time(13, 0) <= current_time <= dt_time(15, 0):
        return "trading"
    if current_time < dt_time(13, 0):
        return "lunch_break"
    return "closed"
