"""三所统一:账户流水路由 + 后台同步安装."""
from __future__ import annotations

import os
from typing import Any, Callable

from flask import Flask, Response, jsonify, request, session, stream_with_context
from jinja2 import ChoiceLoader, FileSystemLoader

from lib.account_ledger.account_ledger_db import ensure_account_ledger_tables, query_entries
from lib.account_ledger.account_ledger_normalize import (
    ACCOUNT_FUNDING,
    ACCOUNT_TRADING,
    PAGE_SIZE,
    VALID_ACCOUNTS,
)
from lib.account_ledger.account_ledger_sync import account_ledger_store
from lib.common.history_window_lib import resolve_list_window


def attach_account_ledger_templates(app: Flask, repo_root: str) -> None:
    tpl_dir = os.path.join(repo_root, "lib", "account_ledger", "templates")
    if not os.path.isdir(tpl_dir):
        return
    existing = app.jinja_loader
    loaders = [FileSystemLoader(tpl_dir)]
    if existing is not None:
        if isinstance(existing, ChoiceLoader):
            loaders = list(existing.loaders) + loaders
        else:
            loaders.insert(0, existing)
    app.jinja_loader = ChoiceLoader(loaders)


def _build_fetch_fn(exchange_key: str, app_module: Any) -> Callable:
    ex_key = (exchange_key or "").strip().lower()
    exchange = getattr(app_module, "exchange", None)
    ensure_markets = getattr(app_module, "ensure_markets_loaded", None)

    def _fetch(*, start_ms: int, end_ms: int):
        if exchange is None:
            return [], ["exchange missing"]
        if ex_key == "okx":
            from lib.exchange.okx_ledger_lib import fetch_okx_account_ledger

            return fetch_okx_account_ledger(
                exchange,
                start_ms=start_ms,
                end_ms=end_ms,
                ensure_markets=ensure_markets,
            )
        if ex_key == "binance":
            from lib.exchange.binance_ledger_lib import fetch_binance_account_ledger

            return fetch_binance_account_ledger(
                exchange,
                start_ms=start_ms,
                end_ms=end_ms,
                ensure_markets=ensure_markets,
            )
        from lib.exchange.gate_ledger_lib import fetch_gate_account_ledger

        return fetch_gate_account_ledger(
            exchange,
            start_ms=start_ms,
            end_ms=end_ms,
            ensure_markets=ensure_markets,
        )

    return _fetch


def _currencies_for_exchange(exchange_key: str) -> list[str]:
    if (exchange_key or "").strip().lower() == "okx":
        return ["USDT", "USDC"]
    return ["USDT"]


def install_account_ledger(
    app: Flask,
    repo_root: str,
    app_module: Any,
    *,
    exchange_key: str = "",
) -> None:
    ex = (exchange_key or "").strip().lower()
    if not ex:
        mod_name = getattr(app_module, "__name__", "") or ""
        if "okx" in mod_name.lower():
            ex = "okx"
        elif "binance" in mod_name.lower():
            ex = "binance"
        else:
            ex = "gate"
    exchange_key = ex

    attach_account_ledger_templates(app, repo_root)
    get_db = app_module.get_db
    login_required = app_module.login_required

    # 初始化表
    try:
        conn = get_db()
        try:
            ensure_account_ledger_tables(conn)
        finally:
            conn.close()
    except Exception:
        pass

    account_ledger_store.configure(
        get_db=get_db,
        fetch_fn=_build_fetch_fn(exchange_key, app_module),
        exchange_key=str(exchange_key),
    )
    account_ledger_store.start()
    app.extensions["account_ledger_exchange"] = str(exchange_key).lower()

    def _list_window():
        resolve = getattr(app_module, "_list_window_from_request", None)
        if callable(resolve):
            return resolve()
        return resolve_list_window(request.args, session)

    @app.route("/api/account_ledger")
    @login_required
    def api_account_ledger():
        account = (request.args.get("account") or ACCOUNT_FUNDING).strip().lower()
        if account not in VALID_ACCOUNTS:
            account = ACCOUNT_FUNDING
        try:
            page = int(request.args.get("page") or 1)
        except Exception:
            page = 1
        win = _list_window()
        start_ms = int(win.get("start_ms") or 0)
        end_ms = int(win.get("end_ms") or 0)
        ccys = _currencies_for_exchange(app.extensions.get("account_ledger_exchange") or "")
        conn = get_db()
        try:
            ensure_account_ledger_tables(conn)
            data = query_entries(
                conn,
                account=account,
                start_ms=start_ms,
                end_ms=end_ms,
                page=page,
                page_size=PAGE_SIZE,
                currencies=ccys,
            )
        finally:
            conn.close()
        st = account_ledger_store.status_dict()
        return jsonify(
            {
                "ok": True,
                "account": account,
                "window": {
                    "preset": win.get("preset"),
                    "label": win.get("label"),
                    "start_ms": start_ms,
                    "end_ms": end_ms,
                },
                "currencies": ccys,
                **data,
                **st,
            }
        )

    @app.route("/api/account_ledger/stream")
    @login_required
    def api_account_ledger_stream():
        return Response(
            stream_with_context(account_ledger_store.iter_sse()),
            mimetype="text/event-stream",
            headers={
                "Cache-Control": "no-cache",
                "Connection": "keep-alive",
                "X-Accel-Buffering": "no",
            },
        )

    @app.route("/api/account_ledger/refresh", methods=["POST"])
    @login_required
    def api_account_ledger_refresh():
        win = _list_window()
        body = request.get_json(silent=True) or {}
        start_ms = body.get("start_ms", win.get("start_ms"))
        end_ms = body.get("end_ms", win.get("end_ms"))
        try:
            start_i = int(start_ms) if start_ms is not None else None
            end_i = int(end_ms) if end_ms is not None else None
        except Exception:
            start_i, end_i = None, None
        result = account_ledger_store.sync_once(
            reason="manual", start_ms=start_i, end_ms=end_i
        )
        return jsonify(result)

    @app.route("/account_ledger")
    @login_required
    def account_ledger_page():
        from lib.instance.instance_embed_lib import redirect_to_embed_shell_if_enabled

        redir = redirect_to_embed_shell_if_enabled("account_ledger")
        if redir is not None:
            return redir
        return app_module.render_main_page("account_ledger")
