// src/web/ui/v2/static/js/pages/calibration_risk.js

console.log(
  "[calibration_risk] script loaded ✅",
  new Date().toISOString()
);

// =================================================
// INSPECT RISK & STOPS
// =================================================

async function inspectCalibrationRisk() {
  console.log("[calibration_risk] inspectCalibrationRisk() START ✅");

  // --------------------------------------------------
  // Load calibration context from Step 1
  // --------------------------------------------------
  const symbol = localStorage.getItem("calibration.symbol");
  const timeframe = localStorage.getItem("calibration.timeframe");

  if (!symbol || !timeframe) {
    alert("Calibration context not found. Please complete Step 1 (Data) first.");
    return;
  }

  // --------------------------------------------------
  // Read form inputs
  // --------------------------------------------------
  const accountEquityEl = document.getElementById("account_equity");
  const riskFractionEl = document.getElementById("risk_fraction");
  const maxPositionEl = document.getElementById("max_position_fraction");
  const stopTypeEl = document.getElementById("stop_type");
  const stopFractionEl = document.getElementById("stop_fraction");
  const atrPeriodEl = document.getElementById("atr_period");
  const atrMultiplierEl = document.getElementById("atr_multiplier");
  const maxDrawdownEl = document.getElementById("max_drawdown_pct");

  if (!accountEquityEl || !riskFractionEl || !maxPositionEl || !stopTypeEl || !maxDrawdownEl) {
    console.error("[calibration_risk] Missing required form elements");
    alert("Internal error: risk form is incomplete.");
    return;
  }

  // --------------------------------------------------
  // Build stop config
  // --------------------------------------------------
  const stopType = stopTypeEl.value;
  let stopConfig = { type: stopType };

  if (stopType === "fixed" || stopType === "trailing") {
    if (!stopFractionEl) {
      alert("Stop fraction input missing");
      return;
    }
    stopConfig.stop_fraction = parseFloat(stopFractionEl.value) / 100;
  }

  if (stopType === "atr") {
    if (!atrPeriodEl || !atrMultiplierEl) {
      alert("ATR parameters missing");
      return;
    }
    stopConfig.atr_period = parseInt(atrPeriodEl.value);
    stopConfig.atr_multiplier = parseFloat(atrMultiplierEl.value);
  }

  // --------------------------------------------------
  // Build payload
  // --------------------------------------------------
  const payload = buildRiskPayload();

  console.log("[calibration_risk] inspect payload:", payload);

  // --------------------------------------------------
  // Disable next step while inspecting
  // --------------------------------------------------
  disableNextStep();

  // --------------------------------------------------
  // Call API
  // --------------------------------------------------
  try {
    const res = await fetch("/api/v2/calibration/risk/inspect", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    });

    const data = await res.json();
    console.log("[calibration_risk] inspect response:", data);

    if (data.status === "ok" || data.status === "warning") {
      persistRiskParametersForStep3();
    }

    renderRiskResult(payload, data);

    // --------------------------------------------------
    // Enable next step if OK or WARNING
    // --------------------------------------------------
    if (data.valid && data.status !== "fail") {
      enableNextStep();
    }

  } catch (err) {
    console.error("[calibration_risk] inspect FAILED", err);
    alert("Error inspecting risk configuration");
    disableNextStep();
  }
}

// =================================================
// VALIDATE RISK & STOPS
// =================================================

async function validateCalibrationRisk() {
  console.log("[calibration_risk] inspectCalibrationRisk() START ✅");

  // --------------------------------------------------
  // Load calibration context from Step 1
  // --------------------------------------------------
  const symbol = localStorage.getItem("calibration.symbol");
  const timeframe = localStorage.getItem("calibration.timeframe");

  if (!symbol || !timeframe) {
    alert("Calibration context not found. Please complete Step 1 (Data) first.");
    return;
  }

  // --------------------------------------------------
  // Read form inputs
  // --------------------------------------------------
  const accountEquityEl = document.getElementById("account_equity");
  const riskFractionEl = document.getElementById("risk_fraction");
  const maxPositionEl = document.getElementById("max_position_fraction");
  const stopTypeEl = document.getElementById("stop_type");
  const stopFractionEl = document.getElementById("stop_fraction");
  const atrPeriodEl = document.getElementById("atr_period");
  const atrMultiplierEl = document.getElementById("atr_multiplier");
  const maxDrawdownEl = document.getElementById("max_drawdown_pct");

  if (!accountEquityEl || !riskFractionEl || !maxPositionEl || !stopTypeEl || !maxDrawdownEl) {
    console.error("[calibration_risk] Missing required form elements");
    alert("Internal error: risk form is incomplete.");
    return;
  }

  // --------------------------------------------------
  // Build stop config
  // --------------------------------------------------
  const stopType = stopTypeEl.value;
  let stopConfig = { type: stopType };

  if (stopType === "fixed" || stopType === "trailing") {
    if (!stopFractionEl) {
      alert("Stop fraction input missing");
      return;
    }
    stopConfig.stop_fraction = parseFloat(stopFractionEl.value) / 100;
  }

  if (stopType === "atr") {
    if (!atrPeriodEl || !atrMultiplierEl) {
      alert("ATR parameters missing");
      return;
    }
    stopConfig.atr_period = parseInt(atrPeriodEl.value);
    stopConfig.atr_multiplier = parseFloat(atrMultiplierEl.value);
  }

  // --------------------------------------------------
  // Build payload
  // --------------------------------------------------
  const payload = buildRiskPayload();

  console.log("[calibration_risk] inspect payload:", payload);

  // --------------------------------------------------
  // Disable next step while inspecting
  // --------------------------------------------------
  disableNextStep();

  // --------------------------------------------------
  // Call API
  // --------------------------------------------------
  try {
    const res = await fetch("/api/v2/calibration/risk/validate", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    });

    const data = await res.json();
    console.log("[calibration_risk] inspect response:", data);

    if (data.status === "ok" || data.status === "warning") {
      persistRiskParametersForStep3();
    }

    renderRiskResult(payload, data);

    // --------------------------------------------------
    // Enable next step if OK or WARNING
    // --------------------------------------------------
    if (data.valid && data.status !== "fail") {
      enableNextStep();
    }

  } catch (err) {
    console.error("[calibration_risk] inspect FAILED", err);
    alert("Error inspecting risk configuration");
    disableNextStep();
  }
}

// =================================================
// PDF REPORT RISK & STOPS
// =================================================

async function generateRiskReport() {
  console.log("[calibration_risk] generateRiskReport() START");

  const payload = buildRiskPayload();

  const res = await fetch("/api/v2/calibration/risk/report", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload),
  });

  const data = await res.json();

  if (data.url) {
    // Mostrar visor
    const viewer = document.getElementById("pdf_viewer_section");
    const frame = document.getElementById("pdf_frame");

    frame.src = data.url;
    viewer.classList.remove("d-none");

    // Scroll suave hacia el visor
    viewer.scrollIntoView({ behavior: "smooth" });
  } else {
    alert("Failed to generate report");
  }
}

// =================================================
// WIZARD NAVIGATION
// =================================================

function enableNextStep() {
  const btn = document.getElementById("next-step-btn");
  if (!btn) return;

  btn.classList.remove("btn-outline-secondary");
  btn.classList.add("btn-outline-primary");
  btn.setAttribute("aria-disabled", "false");
}

function disableNextStep() {
  const btn = document.getElementById("next-step-btn");
  if (!btn) return;

  btn.classList.remove("btn-outline-primary");
  btn.classList.add("btn-outline-secondary");
  btn.setAttribute("aria-disabled", "true");
}

// =================================================
// RENDER RESULT
// =================================================

function renderRiskResult(payload, data) {
  const container = document.getElementById("risk_result");
  const badge = document.getElementById("risk_status_badge");
  const message = document.getElementById("risk_message");
  const debug = document.getElementById("risk_debug");

  if (!container || !badge || !message || !debug) {
    console.warn("[calibration_risk] Result elements missing");
    return;
  }

  container.classList.remove("d-none");

  badge.className = "badge";

  if (data.status === "ok") {
    badge.classList.add("bg-success");
  } else if (data.status === "warning") {
    badge.classList.add("bg-warning");
  } else {
    badge.classList.add("bg-danger");
  }

  badge.textContent = data.status.toUpperCase();
  message.textContent = data.message;
  debug.textContent = JSON.stringify(data.checks, null, 2);

  renderRiskChecks(data.checks);
  if (data.checks?.stop_sanity?.metrics) {
    renderStopQuantiles(data.checks.stop_sanity.metrics);
  }

  renderRiskFormulas(payload, data)
  
  if (!data.series) {
    console.warn("[calibration_risk] No series returned, skipping plots");
    return;
  }
  
  if (data.series?.timestamps && data.series?.position_size_pct) {
    renderPositionSizePlot({
      timestamps: data.series.timestamps,
      positionSizePct: data.series.position_size_pct,
      maxPositionFraction: payload.risk.max_position_fraction
    });
    renderEffectiveRiskPlot({
      timestamps: data.series.timestamps,
      effectiveRiskPct: data.series.effective_risk_pct,
      targetRiskFraction: payload.risk.risk_fraction
    });
    renderStopDistanceDistribution({
      stopDistances: data.series.stop_distances,
      quantiles: data.checks?.stop_sanity?.metrics
    });
  }
}

// =================================================
// RENDER RISK CHECKS
// =================================================

function renderRiskChecks(checks) {
  const list = document.getElementById("risk_checks_list");
  if (!list || !checks) return;

  list.innerHTML = "";

  Object.entries(checks).forEach(([key, check]) => {
    const li = document.createElement("li");
    li.classList.add("mb-1");

    let icon = "❌";
    let color = "text-danger";

    if (check.status === "ok") {
      icon = "✅";
      color = "text-success";
    } else if (check.status === "warning") {
      icon = "⚠️";
      color = "text-warning";
    }

    const title = key.replace(/_/g, " ");

    li.innerHTML = `
      <span class="${color}">
        ${icon} <strong>${title}</strong>
      </span>
      ${check.message ? `<span class="text-muted"> — ${check.message}</span>` : ""}
    `;

    list.appendChild(li);
  });
}

function renderStopQuantiles(metrics) {
  const el = document.getElementById("stop_quantiles");
  if (!el || !metrics) return;

  el.innerHTML = `
    <li>P50 (typical): ${(metrics.p50 * 100).toFixed(2)}%</li>
    <li>P90 (wide): ${(metrics.p90 * 100).toFixed(2)}%</li>
    <li>P99 (extreme): ${(metrics.p99 * 100).toFixed(2)}%</li>
  `;
}

// =================================================
// RENDER RISK FORMULAS
// =================================================

function renderRiskFormulas(payload, result) {
  const el = document.getElementById("risk_formulas");
  if (!el) return;

  const equity = payload.account_equity;
  const riskFraction = payload.risk.risk_fraction;
  const maxPositionFraction = payload.risk.max_position_fraction;

  const stopMetrics = result.checks?.stop_sanity?.metrics;
  if (!stopMetrics || stopMetrics.p50 == null) {
    el.textContent = "Unable to compute risk formulas (missing stop metrics)";
    return;
  }

  const stopP50 = stopMetrics.p50;

  const idealPosition = (equity * riskFraction) / stopP50;
  const maxPosition = equity * maxPositionFraction;
  const effectivePosition = Math.min(idealPosition, maxPosition);
  const effectiveRisk = (effectivePosition * stopP50) / equity;

  el.innerHTML = `
    <li>Position size (ideal)
    = ${equity.toLocaleString()} × ${(riskFraction * 100).toFixed(2)}% ÷ ${(stopP50 * 100).toFixed(2)}%
    ≈ ${idealPosition.toFixed(0)}</li>

    <li>Max position size
    = ${equity.toLocaleString()} × ${(maxPositionFraction * 100).toFixed(2)}%
    = ${maxPosition.toFixed(0)}</li>

    <li>Effective position
    = min(${idealPosition.toFixed(0)}, ${maxPosition.toFixed(0)})
    = ${effectivePosition.toFixed(0)}</li>

    <li>Effective risk
    = ${effectivePosition.toFixed(0)} × ${(stopP50 * 100).toFixed(2)}% ÷ ${equity.toLocaleString()}
    ≈ ${(effectiveRisk * 100).toFixed(2)}%</li>
  `;
}

// =================================================
// STOP TYPE UI LOGIC
// =================================================

function updateStopParamsUI() {
  const stopType = document.getElementById("stop_type")?.value;
  if (!stopType) return;

  // Hide all stop param blocks
  document.querySelectorAll(".stop-param").forEach(el => {
    el.classList.add("d-none");
  });

  // Show relevant blocks
  if (stopType === "fixed" || stopType === "trailing") {
    document.querySelectorAll(".stop-fixed, .stop-trailing").forEach(el => {
      el.classList.remove("d-none");
    });
  }

  if (stopType === "atr") {
    document.querySelectorAll(".stop-atr").forEach(el => {
      el.classList.remove("d-none");
    });
  }
}

// =================================================
// RENDER PLOTS
// =================================================

function renderPositionSizePlot({
  timestamps,
  positionSizePct,
  maxPositionFraction
}) {
  const el = document.getElementById("position_size_plot");
  if (!el) {
    console.warn("[calibration_risk] position_size_plot not found");
    return;
  }

  if (!timestamps || !positionSizePct || timestamps.length === 0) {
    el.innerHTML = "<em>No position size data available</em>";
    return;
  }

  const trace = {
    x: timestamps,
    y: positionSizePct.map(v => v * 100),
    type: "scatter",
    mode: "lines",
    name: "Position size",
    line: {
      color: "#59a14f",
      width: 2
    }
  };

  const layout = {
    yaxis: {
      title: "Position size (% equity)",
      rangemode: "tozero"
    },
    xaxis: {
      title: "Time"
    },
    shapes: [
      {
        type: "line",
        xref: "paper",
        x0: 0,
        x1: 1,
        y0: maxPositionFraction * 100,
        y1: maxPositionFraction * 100,
        line: {
          dash: "dot",
          color: "#e15759",
          width: 2
        }
      }
    ],
    annotations: [
      {
        xref: "paper",
        x: 1,
        y: maxPositionFraction * 100,
        xanchor: "left",
        text: "Max position cap",
        showarrow: false,
        font: {
          size: 11,
          color: "#e15759"
        }
      }
    ],
    margin: { t: 20 }
  };

  Plotly.newPlot(el, [trace], layout, {
    responsive: true,
    displayModeBar: true
  });
}

function renderEffectiveRiskPlot({
  timestamps,
  effectiveRiskPct,
  targetRiskFraction
}) {
  const el = document.getElementById("effective_risk_plot");
  if (!el) {
    console.warn("[calibration_risk] effective_risk_plot not found");
    return;
  }

  if (!timestamps || !effectiveRiskPct || timestamps.length === 0) {
    el.innerHTML = "<em>No effective risk data available</em>";
    return;
  }

  const trace = {
    x: timestamps,
    y: effectiveRiskPct.map(v => v * 100),
    type: "scatter",
    mode: "lines",
    name: "Effective risk",
    line: {
      color: "#f28e2b",
      width: 2
    }
  };

  const layout = {
    yaxis: {
      title: "Effective risk (% equity)",
      rangemode: "tozero"
    },
    xaxis: {
      title: "Time"
    },
    shapes: [
      {
        type: "line",
        xref: "paper",
        x0: 0,
        x1: 1,
        y0: targetRiskFraction * 100,
        y1: targetRiskFraction * 100,
        line: {
          dash: "dot",
          color: "#4c78a8",
          width: 2
        }
      }
    ],
    annotations: [
      {
        xref: "paper",
        x: 1,
        y: targetRiskFraction * 100,
        xanchor: "left",
        text: "Target risk",
        showarrow: false,
        font: {
          size: 11,
          color: "#4c78a8"
        }
      }
    ],
    margin: { t: 20 }
  };

  Plotly.newPlot(el, [trace], layout, {
    responsive: true,
    displayModeBar: true
  });
}

function renderStopDistanceDistribution({
  stopDistances,
  quantiles
}) {
  const el = document.getElementById("stop_distance_plot");
  if (!el) {
    console.warn("[calibration_risk] stop_distance_plot not found");
    return;
  }

  if (!stopDistances || stopDistances.length === 0) {
    el.innerHTML = "<em>No stop distance data available</em>";
    return;
  }

  const valuesPct = stopDistances
    .filter(v => v != null && v > 0)
    .map(v => v * 100);

  const trace = {
    x: valuesPct,
    type: "histogram",
    nbinsx: 40,
    name: "Stop distance",
    marker: {
      color: "#bab0ac"
    }
  };

  const shapes = [];
  const annotations = [];

  if (quantiles) {
    const qMap = [
      { key: "p50", label: "P50 (typical)", color: "#4c78a8" },
      { key: "p90", label: "P90 (wide)", color: "#f28e2b" },
      { key: "p99", label: "P99 (extreme)", color: "#e15759" }
    ];

    qMap.forEach(q => {
      const val = quantiles[q.key];
      if (val != null) {
        shapes.push({
          type: "line",
          xref: "x",
          yref: "paper",
          x0: val * 100,
          x1: val * 100,
          y0: 0,
          y1: 1,
          line: {
            dash: "dot",
            width: 2,
            color: q.color
          }
        });

        annotations.push({
          x: val * 100,
          y: 1,
          yref: "paper",
          xanchor: "left",
          text: q.label,
          showarrow: false,
          font: {
            size: 11,
            color: q.color
          }
        });
      }
    });
  }

  const layout = {
    xaxis: {
      title: "Stop distance (% price)"
    },
    yaxis: {
      title: "Frequency"
    },
    shapes: shapes,
    annotations: annotations,
    margin: { t: 20 }
  };

  Plotly.newPlot(el, [trace], layout, {
    responsive: true,
    displayModeBar: true
  });
}

// =================================================
// UTILS
// =================================================

function num(id) {
  const el = document.getElementById(id);
  if (!el) return null;

  const val = el.value;
  if (val === "" || val === null || val === undefined) return null;

  const n = Number(val);
  return Number.isFinite(n) ? n : null;
}

function str(id) {
  const el = document.getElementById(id);
  if (!el) return null;
  const v = el.value;
  return v === null || v === undefined ? null : String(v);
}

function buildRiskPayload() {
  const symbol = localStorage.getItem("calibration.symbol");
  const timeframe = localStorage.getItem("calibration.timeframe");

  const stopType = document.getElementById("stop_type")?.value;

  const stop = { type: stopType };

  if (stopType === "fixed" || stopType === "trailing") {
    stop.stop_fraction = num("stop_fraction");
  }

  if (stopType === "atr") {
    stop.atr_period = num("atr_period");
    stop.atr_multiplier = num("atr_multiplier");
  }

  const payload = {
    symbol,
    timeframe,
    account_equity: num("account_equity"),

    risk: {
      risk_fraction: num("risk_fraction") / 100,
      max_position_fraction: num("max_position_fraction") / 100,
    },

    stop,

    global_rules: {
      max_drawdown_pct: num("max_drawdown_pct") / 100,
      daily_loss_limit_pct: num("daily_loss_limit_pct") 
        ? num("daily_loss_limit_pct") / 100 
        : null,
      max_consecutive_losses: num("max_consecutive_losses"),
      cooldown_bars: num("cooldown_bars"),
    },
  };

  console.log("[calibration_risk] FINAL PAYLOAD:", payload);

  return payload;
}

function persistRiskParametersForStep3() {

  try {

    const dataToPersist = {
      risk_fraction: num("risk_fraction"),
      max_position_fraction: num("max_position_fraction"),
      stop_type: str("stop_type"),
      stop_fraction: num("stop_fraction"),
      atr_period: num("atr_period"),
      atr_multiplier: num("atr_multiplier"),
      max_drawdown_pct: num("max_drawdown_pct"),
      daily_loss_limit_pct: num("daily_loss_limit_pct"),
      max_consecutive_losses: num("max_consecutive_losses"),
      cooldown_bars: num("cooldown_bars"),
    };

    Object.entries(dataToPersist).forEach(([key, value]) => {
      localStorage.setItem(`calibration.${key}`, value ?? "");
    });

    console.log("[calibration_risk] Parameters saved for Step 3 ✅");

  } catch (err) {
    console.error("[calibration_risk] Persist failed ❌", err);
  }
}

// =================================================
// INIT
// =================================================

document.addEventListener("DOMContentLoaded", () => {
  console.log("[calibration_risk] DOMContentLoaded ✅");

  document
    .getElementById("inspect_risk_btn")
    ?.addEventListener("click", inspectCalibrationRisk);

  const stopTypeSelect = document.getElementById("stop_type");
  stopTypeSelect?.addEventListener("change", updateStopParamsUI);
  
  const symbol = localStorage.getItem("calibration.symbol");
  const timeframe = localStorage.getItem("calibration.timeframe");

  if (symbol && timeframe) {
    const symbolEl = document.getElementById("ctx_symbol");
    const timeframeEl = document.getElementById("ctx_timeframe");

    if (symbolEl) symbolEl.textContent = symbol;
    if (timeframeEl) timeframeEl.textContent = timeframe;
  }

  // Initial state
  updateStopParamsUI();
});

document.addEventListener("DOMContentLoaded", () => {
  console.log("[calibration_risk] DOMContentLoaded ✅");

  document
    .getElementById("validate_risk_btn")
    ?.addEventListener("click", validateCalibrationRisk);

  const stopTypeSelect = document.getElementById("stop_type");
  stopTypeSelect?.addEventListener("change", updateStopParamsUI);
  
  const symbol = localStorage.getItem("calibration.symbol");
  const timeframe = localStorage.getItem("calibration.timeframe");

  if (symbol && timeframe) {
    const symbolEl = document.getElementById("ctx_symbol");
    const timeframeEl = document.getElementById("ctx_timeframe");

    if (symbolEl) symbolEl.textContent = symbol;
    if (timeframeEl) timeframeEl.textContent = timeframe;
  }

  // Initial state
  updateStopParamsUI();
});

document.addEventListener("DOMContentLoaded", () => {
  console.log("[calibration_risk] DOMContentLoaded ✅");

  document
    .getElementById("generate_report_btn")
    ?.addEventListener("click", generateRiskReport);

  document
    .getElementById("close_pdf_btn")
    ?.addEventListener("click", () => {
      document.getElementById("pdf_viewer_section").classList.add("d-none");
      document.getElementById("pdf_frame").src = "";
  });
});


