/**
 * 实盘/关键位放大 K 线:交易所 tick 精度,主题感知图表,高对比 meta.
 */
(function (global) {
  "use strict";

  let activePriceTick = null;

  function currentTheme() {
    return document.documentElement.getAttribute("data-theme") === "light"
      ? "light"
      : "dark";
  }

  function chartTheme(theme) {
    if (theme === "light") {
      return {
        layout: { background: { color: "#f0f4f9" }, textColor: "#142232" },
        grid: { vertLines: { color: "#d0dae4" }, horzLines: { color: "#d0dae4" } },
        rightPriceScale: { borderColor: "#b8c8d8" },
        timeScale: { borderColor: "#b8c8d8" },
        candle: {
          upColor: "#0a7a3d",
          downColor: "#c62828",
          wickUpColor: "#0a7a3d",
          wickDownColor: "#c62828",
        },
      };
    }
    return {
      layout: { background: { color: "#0f1320" }, textColor: "#d6deff" },
      grid: { vertLines: { color: "#1e263d" }, horzLines: { color: "#1e263d" } },
      rightPriceScale: { borderColor: "#2a3150" },
      timeScale: { borderColor: "#2a3150" },
      candle: {
        upColor: "#4cd97f",
        downColor: "#ff6666",
        wickUpColor: "#4cd97f",
        wickDownColor: "#ff6666",
      },
    };
  }

  const SAFE_PRICE_FORMAT = { type: "price", precision: 4, minMove: 0.0001 };

  function decimalsFromTick(tick) {
    if (tick == null || !Number.isFinite(Number(tick)) || Number(tick) <= 0) return null;
    const minMove = Number(tick);
    if (minMove >= 1) return 0;
    const raw = String(minMove);
    const sci = raw.match(/e-(\d+)/i);
    if (sci) return Math.min(12, parseInt(sci[1], 10));
    const fixed = minMove.toFixed(12);
    const frac = fixed.split(".")[1] || "";
    const trimmed = frac.replace(/0+$/, "");
    if (trimmed.length) return Math.min(12, trimmed.length);
    return Math.max(0, Math.min(12, Math.round(-Math.log10(minMove))));
  }

  function tickToPriceFormat(tick) {
    try {
      if (tick == null || !Number.isFinite(Number(tick)) || Number(tick) <= 0) {
        return { type: "price", precision: 2, minMove: 0.01 };
      }
      const minMove = Number(tick);
      let prec = decimalsFromTick(minMove);
      if (prec == null || prec < 0) prec = 4;
      prec = Math.min(12, Math.max(0, Math.floor(prec)));
      return { type: "price", precision: prec, minMove: minMove };
    } catch (_) {
      return SAFE_PRICE_FORMAT;
    }
  }

  function roundToTick(v, tick) {
    if (v == null || Number.isNaN(Number(v))) return v;
    const n = Number(v);
    if (tick == null || !Number.isFinite(Number(tick)) || Number(tick) <= 0) return n;
    const t = Number(tick);
    const rounded = Math.round(n / t) * t;
    const dec = decimalsFromTick(t);
    if (dec == null) return rounded;
    return parseFloat(rounded.toFixed(dec));
  }

  function fmtPriceByTick(v, tick) {
    if (v == null || Number.isNaN(Number(v))) return "-";
    const n = Number(roundToTick(v, tick));
    if (n === 0) return "0";
    const dec = decimalsFromTick(tick);
    if (dec != null) return n.toFixed(dec);
    const av = Math.abs(n);
    let d = 8;
    if (av >= 10000) d = 2;
    else if (av >= 100) d = 3;
    else if (av >= 1) d = 4;
    else if (av >= 0.01) d = 6;
    const text = n.toFixed(d);
    return text.includes(".") ? text.replace(/\.?0+$/, "") : text;
  }

  function setActivePriceTick(tick) {
    activePriceTick =
      tick == null || !Number.isFinite(Number(tick)) || Number(tick) <= 0
        ? null
        : Number(tick);
  }

  function formatSigned(v, digits) {
    digits = digits === undefined ? 2 : digits;
    if (v === null || typeof v === "undefined" || Number.isNaN(Number(v))) return "-";
    const n = Number(v);
    const sign = n > 0 ? "+" : "";
    return sign + n.toFixed(digits);
  }

  function formatSignedPrice(v) {
    if (v === null || typeof v === "undefined" || Number.isNaN(Number(v))) return "-";
    const n = Number(v);
    const body = fmtPriceByTick(Math.abs(n), activePriceTick);
    if (body === "-") return "-";
    return (n > 0 ? "+" : n < 0 ? "-" : "") + body;
  }

  function formatRrRatio(rr) {
    if (rr === null || typeof rr === "undefined") return "-:1";
    const n = Number(rr);
    if (Number.isNaN(n)) return "-:1";
    const body = Number.isInteger(n) ? String(n) : String(parseFloat(n.toFixed(2)));
    return body + ":1";
  }

  function displayPrice(orderOrData, field, rawField) {
    const dispKey = field + "_display";
    if (orderOrData && orderOrData[dispKey] && orderOrData[dispKey] !== "-") {
      return String(orderOrData[dispKey]);
    }
    const raw = orderOrData ? orderOrData[rawField || field] : null;
    if (raw === null || typeof raw === "undefined" || Number.isNaN(Number(raw))) return "-";
    return fmtPriceByTick(raw, activePriceTick);
  }

  function lineTitle(label, display) {
    const d = display && display !== "-" ? display : "";
    return d ? label + " " + d : label;
  }

  function paintOrderMeta(order) {
    const symEl = document.getElementById("m-symbol");
    const dirEl = document.getElementById("m-direction");
    const pnlEl = document.getElementById("m-pnl");
    if (symEl) symEl.textContent = order.symbol || "-";
    if (dirEl) {
      const isShort = order.direction === "short";
      dirEl.textContent = isShort ? "做空" : "做多";
      dirEl.className = "v " + (isShort ? "meta-dir-short" : "meta-dir-long");
    }
    const set = function (id, text) {
      const el = document.getElementById(id);
      if (el) el.textContent = text;
    };
    set("m-entry", displayPrice(order, "trigger_price"));
    set("m-sl", displayPrice(order, "stop_loss"));
    set("m-tp", displayPrice(order, "take_profit"));
    set("m-rr", formatRrRatio(order.rr_ratio));
    set(
      "m-breakeven",
      order.breakeven_enabled === false || order.breakeven_enabled === 0 ? "关闭" : "开启"
    );
    set(
      "m-price",
      order.current_price_display ||
        order.price_display ||
        displayPrice(order, "current_price")
    );
    if (pnlEl) {
      pnlEl.textContent =
        formatSigned(order.float_pnl, 2) +
        "U (" +
        formatSigned(order.float_pct, 2) +
        "%)";
      pnlEl.className = "v";
      const pnl = Number(order.float_pnl || 0);
      if (pnl > 0) pnlEl.classList.add("meta-pnl-up");
      else if (pnl < 0) pnlEl.classList.add("meta-pnl-down");
    }
  }

  function paintKeyMeta(data) {
    const key = data.key_monitor || null;
    const symEl = document.getElementById("m-symbol");
    if (symEl) symEl.textContent = data.symbol || "-";
    const set = function (id, text) {
      const el = document.getElementById(id);
      if (el) el.textContent = text;
    };
    set(
      "m-price",
      data.current_price_display || displayPrice(data, "current_price")
    );
    const dirEl = document.getElementById("m-direction");
    if (!key) {
      set("m-type", "未匹配到关键位");
      set("m-direction", "-");
      if (dirEl) dirEl.className = "v";
      set("m-upper", "-");
      set("m-lower", "-");
      set("m-updiff", "-");
      set("m-lowdiff", "-");
      return;
    }
    set("m-type", key.monitor_type || "-");
    if (dirEl) {
      const isShort = key.direction === "short";
      dirEl.textContent = isShort ? "做空" : "做多";
      dirEl.className = "v " + (isShort ? "meta-dir-short" : "meta-dir-long");
    }
    set("m-upper", key.upper_display || displayPrice(key, "upper"));
    set("m-lower", key.lower_display || displayPrice(key, "lower"));
    if (activePriceTick != null) {
      set(
        "m-updiff",
        formatSignedPrice(key.upper_diff) +
          " (" +
          formatSigned(key.upper_pct, 2) +
          "%)"
      );
      set(
        "m-lowdiff",
        formatSignedPrice(key.lower_diff) +
          " (" +
          formatSigned(key.lower_pct, 2) +
          "%)"
      );
    } else {
      set(
        "m-updiff",
        formatSigned(key.upper_diff, 4) + " (" + formatSigned(key.upper_pct, 2) + "%)"
      );
      set(
        "m-lowdiff",
        formatSigned(key.lower_diff, 4) + " (" + formatSigned(key.lower_pct, 2) + "%)"
      );
    }
  }

  function applyPriceFormatToSeries(series, pf) {
    if (!series || !series.applyOptions) return;
    try {
      series.applyOptions({ priceFormat: pf });
    } catch (_) {
      try {
        series.applyOptions({ priceFormat: SAFE_PRICE_FORMAT });
      } catch (_2) {}
    }
  }

  function createFocusChart(host) {
    if (!global.LightweightCharts) return null;
    const th = chartTheme(currentTheme());
    const chart = global.LightweightCharts.createChart(host, {
      layout: th.layout,
      grid: th.grid,
      rightPriceScale: th.rightPriceScale,
      timeScale: Object.assign({ timeVisible: true, secondsVisible: false }, th.timeScale),
      crosshair: { mode: 0 },
      localization: {
        priceFormatter: function (p) {
          return fmtPriceByTick(p, activePriceTick);
        },
      },
    });
    let candleSeries = null;

    function applyChartPriceFormat() {
      let pf = SAFE_PRICE_FORMAT;
      try {
        pf = tickToPriceFormat(activePriceTick);
      } catch (_) {
        pf = SAFE_PRICE_FORMAT;
      }
      applyPriceFormatToSeries(candleSeries, pf);
      try {
        chart.applyOptions({
          localization: {
            priceFormatter: function (p) {
              return fmtPriceByTick(p, activePriceTick);
            },
          },
        });
      } catch (_) {}
    }

    function setPriceTick(tick) {
      setActivePriceTick(tick);
      applyChartPriceFormat();
    }

    const opts = Object.assign({ borderVisible: false }, th.candle);
    if (typeof chart.addCandlestickSeries === "function") {
      candleSeries = chart.addCandlestickSeries(opts);
    } else if (
      typeof chart.addSeries === "function" &&
      global.LightweightCharts.CandlestickSeries
    ) {
      candleSeries = chart.addSeries(global.LightweightCharts.CandlestickSeries, opts);
    }
    applyChartPriceFormat();

    const priceLines = [];
    function resetPriceLines() {
      if (!candleSeries) return;
      priceLines.forEach(function (line) {
        try {
          candleSeries.removePriceLine(line);
        } catch (_) {}
      });
      priceLines.length = 0;
    }
    function addLine(price, title, color) {
      if (!candleSeries || price === null || typeof price === "undefined") return;
      const p = Number(roundToTick(price, activePriceTick));
      if (Number.isNaN(p) || p <= 0) return;
      priceLines.push(
        candleSeries.createPriceLine({
          price: p,
          color: color,
          lineWidth: 1,
          lineStyle: 0,
          axisLabelVisible: true,
          title: title,
        })
      );
    }
    function applyTheme() {
      const t = chartTheme(currentTheme());
      chart.applyOptions({
        layout: t.layout,
        grid: t.grid,
        rightPriceScale: t.rightPriceScale,
        timeScale: t.timeScale,
        localization: {
          priceFormatter: function (p) {
            return fmtPriceByTick(p, activePriceTick);
          },
        },
      });
      if (candleSeries && typeof candleSeries.applyOptions === "function") {
        candleSeries.applyOptions(t.candle);
      }
      applyChartPriceFormat();
    }
    function resize() {
      chart.applyOptions({ width: host.clientWidth, height: host.clientHeight });
    }
    global.addEventListener("resize", resize);
    resize();
    const obs = new MutationObserver(applyTheme);
    obs.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["data-theme"],
    });
    return {
      chart: chart,
      candleSeries: candleSeries,
      resetPriceLines: resetPriceLines,
      addLine: addLine,
      applyTheme: applyTheme,
      setPriceTick: setPriceTick,
      ensureSeries: function () {
        if (candleSeries) return true;
        const t = chartTheme(currentTheme());
        const o = Object.assign({ borderVisible: false }, t.candle);
        if (typeof chart.addCandlestickSeries === "function") {
          candleSeries = chart.addCandlestickSeries(o);
        } else if (
          typeof chart.addSeries === "function" &&
          global.LightweightCharts.CandlestickSeries
        ) {
          candleSeries = chart.addSeries(global.LightweightCharts.CandlestickSeries, o);
        }
        applyChartPriceFormat();
        return !!candleSeries;
      },
    };
  }

  global.FocusChartPage = {
    currentTheme: currentTheme,
    chartTheme: chartTheme,
    formatSigned: formatSigned,
    formatRrRatio: formatRrRatio,
    displayPrice: displayPrice,
    lineTitle: lineTitle,
    paintOrderMeta: paintOrderMeta,
    paintKeyMeta: paintKeyMeta,
    createFocusChart: createFocusChart,
    setActivePriceTick: setActivePriceTick,
    fmtPriceByTick: fmtPriceByTick,
  };
})(typeof window !== "undefined" ? window : globalThis);
