import os
import sys
import time
import random
import threading

sys.path.append(os.path.dirname(sys.path[0]))
from utils.db_connect import BaseUtils
import json
from flask import Flask, request, jsonify
import requests
import traceback

app = Flask(__name__)

ACCOUNTS = [
    {"accountId": "account_001", "phone": "13752682896", "password": "YSWG2026"},
    {"accountId": "account_002", "phone": "15112376559", "password": "PYB8899"},
]

RK_POOL = 'sif:pool:{}'
RK_STATUS = 'sif:status:{}'

ACCOUNT_MAP = {a["accountId"]: a for a in ACCOUNTS}

_redis = None
_redis_lock = threading.Lock()
_relogin_locks = {a["accountId"]: threading.Lock() for a in ACCOUNTS}


def db_resin():
    global _redis
    with _redis_lock:
        if _redis is None:
            _redis = BaseUtils().redis_db()
        try:
            _redis.ping()
        except Exception:
            _redis = BaseUtils().redis_db()
        return _redis


def generate_uuid():
    uuid_template = "Sif_xxxx-xxxx-4xxx-yxxx-xxxx"

    def replace_char(c):
        r = random.randint(0, 15)
        if c == 'x':
            return hex(r)[2:]
        elif c == 'y':
            return hex((r & 0x3) | 0x8)[2:]

    return ''.join(replace_char(c) if c in 'xy' else c for c in uuid_template)


def login_slf(phone, password):
    int_time = int(time.time() * 1000)
    _m = generate_uuid()
    login_url = f'https://www.sif.com/api/user/login?_t={int_time}&_m={_m}'
    print(f'[login] account={phone}')
    headers = {
        "Accept": "application/json, text/plain, */*",
        "Accept-Encoding": "gzip, deflate, br, zstd",
        "Accept-Language": "zh-CN,zh;q=0.9",
        "Cache-Control": "no-cache",
        "Connection": "keep-alive",
        "Content-Type": "application/json;charset=UTF-8",
        "Host": "www.sif.com",
        "Origin": "https://www.sif.com",
        "Pragma": "no-cache",
        "Referer": "https://www.sif.com/",
        "Sec-Ch-Ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
        "Sec-Ch-Ua-Mobile": "?0",
        "Sec-Ch-Ua-Platform": '"Windows"',
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-origin",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    }
    data = {"phone": phone, "password": password}
    try:
        resp = requests.post(login_url, headers=headers, json=data, timeout=20)
        auth = resp.headers.get('authorization')
        if not auth:
            print(f'[login] 失败：{resp.text}')
            return None
        headers['authorization'] = auth
        print(f'[login] OK account={phone}')
        return headers
    except Exception as e:
        print(f'[login] 异常：{e}')
        return None


def login_and_cache(account_id):
    acc = ACCOUNT_MAP.get(account_id)
    if not acc:
        return None
    r = db_resin()
    r.set(RK_STATUS.format(account_id), 'logging')
    headers = login_slf(acc["phone"], acc["password"])
    if headers:
        r.set(RK_POOL.format(account_id), json.dumps(headers))
        r.set(RK_STATUS.format(account_id), 'active')
        return headers
    r.set(RK_STATUS.format(account_id), 'expired')
    return None


def init_all_accounts():
    for acc in ACCOUNTS:
        aid = acc["accountId"]
        with _relogin_locks[aid]:
            login_and_cache(aid)
    print(f'[init] {len(ACCOUNTS)} accounts initialized')


def get_pool():
    r = db_resin()
    pool = []
    for acc in ACCOUNTS:
        aid = acc["accountId"]
        status = (r.get(RK_STATUS.format(aid)) or b'expired').decode()
        cached = r.get(RK_POOL.format(aid))
        headers = json.loads(cached) if cached else None
        pool.append({
            "accountId": aid,
            "status": status,
            "headers": headers,
        })
    return pool


def relogin_account(account_id):
    if account_id not in ACCOUNT_MAP:
        return None
    with _relogin_locks[account_id]:
        headers = login_and_cache(account_id)
        if headers:
            return {
                "accountId": account_id,
                "status": "active",
                "headers": headers,
            }
        return None


@app.route('/sif/api/headers', methods=['GET'])
def api_headers():
    mode = request.args.get('mode')
    action = request.args.get('action')
    account_id = request.args.get('accountId')

    try:
        if mode == 'pool':
            pool = get_pool()
            return jsonify({"code": 200, "message": "success", "data": pool})

        if action == 'relogin':
            if not account_id or account_id not in ACCOUNT_MAP:
                return jsonify({"code": 400, "message": f"invalid accountId: {account_id}", "data": None})
            result = relogin_account(account_id)
            if result:
                return jsonify({"code": 200, "message": "success", "data": result})
            return jsonify({"code": 500, "message": "relogin failed", "data": None})

        pool = get_pool()
        return jsonify({"code": 200, "message": "success", "data": pool})

    except Exception as e:
        print(traceback.format_exc())
        return jsonify({"code": 500, "message": str(e), "data": None})


@app.route('/sif/api/login', methods=['GET'])
def api_login_compat():
    reget = request.args.get('regetFlag') == 'true'
    try:
        if reget:
            init_all_accounts()
        pool = get_pool()
        active = [p for p in pool if p["status"] == "active"]
        if active:
            return jsonify({"code": 200, "message": "success", "headers": active[0]["headers"]})
        if not reget:
            cached = [p for p in pool if p["headers"] is not None]
            if cached:
                return jsonify({"code": 200, "message": "success", "headers": cached[0]["headers"]})
            init_all_accounts()
            pool = get_pool()
            active = [p for p in pool if p["status"] == "active"]
            if active:
                return jsonify({"code": 200, "message": "success", "headers": active[0]["headers"]})
        return jsonify({"code": 500, "message": "login failed", "headers": None})
    except Exception as e:
        print(traceback.format_exc())
        return jsonify({"code": 500, "message": str(e), "headers": None})


if __name__ == '__main__':
    init_all_accounts()
    app.run('0.0.0.0', 10248)
