import re
import time
from datetime import datetime, timedelta

import pandas as pd
import requests


def _get_sina_page(node: str, page: int, num: int = 80) -> list:
    url = (
        f"https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/"
        f"Market_Center.getHQNodeData?page={page}&num={num}"
        f"&sort=changepercent&asc=0&node={node}&symbol=&_s_r_a=init"
    )
    try:
        r = requests.get(url, headers={"Referer": "https://finance.sina.com.cn"}, timeout=10)
        return r.json()
    except Exception:
        return []


def sina_get_market_snapshot(max_pages: int = 30) -> pd.DataFrame:
    all_data = []
    for page in range(1, max_pages + 1):
        data = _get_sina_page("hs_a", page, 80)
        if not data:
            break
        all_data.extend(data)
        if len(data) < 80:
            break
        time.sleep(0.2)

    if not all_data:
        return pd.DataFrame()

    rows = []
    seen = set()
    for item in all_data:
        code = item.get("code", "")
        if code in seen:
            continue
        seen.add(code)
        trade = float(item.get("trade", 0) or 0)
        settlement = float(item.get("settlement", 0) or 0)
        if trade <= 0 and settlement <= 0:
            continue
        if trade <= 0:
            trade = settlement
        rows.append({
            "代码": code,
            "名称": item.get("name", ""),
            "最新价": trade,
            "涨跌幅(%)": float(item.get("changepercent", 0) or 0),
            "涨跌额": float(item.get("pricechange", 0) or 0),
            "成交量(手)": int(float(item.get("volume", 0) or 0) / 100),
            "成交额(元)": float(item.get("amount", 0) or 0),
            "今开": float(item.get("open", 0) or 0),
            "最高": float(item.get("high", 0) or 0),
            "最低": float(item.get("low", 0) or 0),
            "昨收": settlement,
            "换手率(%)": float(item.get("turnoverratio", 0) or 0),
            "市盈率-动态": float(item.get("per", 0) or 0),
            "市净率": float(item.get("pb", 0) or 0),
            "总市值(元)": float(item.get("mktcap", 0) or 0) * 10000,
            "流通市值(元)": float(item.get("nmc", 0) or 0) * 10000,
        })

    return pd.DataFrame(rows)


def sina_get_stock_hist(symbol: str, days: int = 60) -> pd.DataFrame:
    prefix = "sh" if symbol.startswith("6") else "sz"
    url = (
        f"https://money.finance.sina.com.cn/quotes_service/api/json_v2.php/"
        f"CN_MarketData.getKLineData?symbol={prefix}{symbol}&scale=240&ma=no&datalen={days}"
    )
    try:
        r = requests.get(url, headers={"Referer": "https://finance.sina.com.cn"}, timeout=10)
        data = r.json()
        if not data:
            return pd.DataFrame()
        rows = []
        for item in data:
            rows.append({
                "日期": item["day"],
                "股票代码": symbol,
                "开盘": float(item["open"]),
                "收盘": float(item["close"]),
                "最高": float(item["high"]),
                "最低": float(item["low"]),
                "成交量(手)": int(float(item["volume"]) / 100),
            })
        df = pd.DataFrame(rows)
        if not df.empty:
            prev_close = df["收盘"].shift(1)
            df["成交额(元)"] = 0
            df["振幅(%)"] = ((df["最高"] - df["最低"]) / prev_close * 100).fillna(0)
            df["涨跌幅(%)"] = ((df["收盘"] - prev_close) / prev_close * 100).fillna(0)
            df["涨跌额"] = (df["收盘"] - prev_close).fillna(0)
            df["换手率(%)"] = 0
        return df
    except Exception:
        return pd.DataFrame()
