/* Métricas — deep-dive tabs */

const METRIC_TABS = [
  { value: "sleep", label: "Sueño", icon: "moon", color: "var(--info)", unit: "h", key: "sleepHours", scoreKey: "sleepScore" },
  { value: "hrv", label: "HRV", icon: "heart", color: "var(--good)", unit: "ms", key: "hrv" },
  { value: "rhr", label: "FC reposo", icon: "flame", color: "var(--accent)", unit: "bpm", key: "rhr" },
  { value: "weight", label: "Peso", icon: "weight", color: "var(--warn)", unit: "kg", key: "weight" },
  { value: "body", label: "Composición", icon: "user", color: "var(--info)", unit: "%", key: "bodyFat" },
  { value: "energy", label: "Energía", icon: "zap", color: "var(--good)", unit: "", key: "energy" },
];

const Metrics = ({ density, dataState, inDemo }) => {
  const [tab, setTab] = React.useState("hrv");
  const [range, setRange] = React.useState("30d");
  const [provider, setProvider] = React.useState("");
  const m = METRIC_TABS.find((x) => x.value === tab);
  const days = range === "7d" ? 7 : range === "30d" ? 30 : range === "90d" ? 90 : 90;

  const [daily, setDaily] = React.useState(() => inDemo ? MOCK.daily : null);
  const [loading, setLoading] = React.useState(!inDemo);
  const [fetchError, setFetchError] = React.useState(null);

  React.useEffect(() => {
    if (inDemo) { setDaily(MOCK.daily); setLoading(false); return; }
    let alive = true;
    setLoading(true);
    setFetchError(null);
    (async () => {
      try {
        const today = new Date();
        const from = new Date(today); from.setDate(from.getDate() - days);
        const fmt = (d) => d.toISOString().slice(0, 10);
        const res = await API.dailyData({ from: fmt(from), to: fmt(today), provider });
        if (!alive) return;
        const items = Array.isArray(res) ? res : (res?.rows || res?.items || res?.daily || []);
        // Backend devuelve los días desc; lo invertimos para gráfico cronológico.
        const ordered = [...items].reverse().map(window.normalizeDailyRow);
        setDaily(ordered);
      } catch (e) {
        if (alive) {
          if (e.status === 401 || e.status === 403 || e.status === 422) return;
          setFetchError(e.message || "No se pudo cargar datos diarios.");
          // Sin backend → caer al MOCK con badge de aviso.
          setDaily(MOCK.daily);
        }
      } finally {
        if (alive) setLoading(false);
      }
    })();
    return () => { alive = false; };
  }, [inDemo, days, provider]);

  // Datos = solo los días que tienen valor real para esta métrica.
  const allRows = daily || [];
  const data = allRows.slice(-days).filter((d) => d[m.key] != null && !isNaN(Number(d[m.key])));
  const values = data.map((d) => Number(d[m.key]));
  const hasData = values.length > 0;
  const avg = hasData ? (values.reduce((a, b) => a + b, 0) / values.length) : null;
  const minV = hasData ? Math.min(...values) : null;
  const maxV = hasData ? Math.max(...values) : null;
  const first = hasData ? values[0] : null;
  const last = hasData ? values[values.length - 1] : null;
  const delta = (hasData && first !== 0 && first != null) ? ((last - first) / first) * 100 : null;
  const fmt1 = (n) => (n == null || isNaN(n)) ? "—" : Number(n).toFixed(1);
  // Etiquetas equiespaciadas — no asume cantidades fijas. Toma min(5, data.length).
  const xLabels = (() => {
    if (data.length === 0) return [];
    const n = Math.min(5, data.length);
    const out = [];
    for (let i = 0; i < n; i++) {
      const idx = Math.floor((data.length - 1) * (i / Math.max(1, n - 1)));
      out.push(data[idx].label);
    }
    return out;
  })();

  return (
    <div className="af-padded" style={{ padding: "var(--sp-6) var(--sp-8) 80px", display: "flex", flexDirection: "column", gap: 18 }}>
      {/* Tabs */}
      <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
        <div style={{ display: "flex", gap: 4, overflowX: "auto" }}>
          {METRIC_TABS.map((t) => (
            <button key={t.value} onClick={() => setTab(t.value)} style={{
              padding: "8px 14px",
              borderRadius: "var(--r-2)",
              border: tab === t.value ? `1px solid ${t.color}` : "1px solid var(--line)",
              background: tab === t.value ? `color-mix(in srgb, ${t.color} 10%, var(--bg-1))` : "var(--bg-1)",
              color: tab === t.value ? t.color : "var(--text-2)",
              fontSize: 12.5, fontWeight: 500,
              display: "inline-flex", gap: 7, alignItems: "center",
              transition: "all 0.15s",
            }}>
              <Icon name={t.icon} size={13} color={tab === t.value ? t.color : "var(--text-3)"} />
              {t.label}
            </button>
          ))}
        </div>
        <div style={{ flex: 1 }} />
        <RangePicker value={range} onChange={setRange} />
      </div>

      {/* Estado de carga / errores / sin datos. */}
      {loading && (
        <Card>
          <div style={{ padding: "30px 0", textAlign: "center", color: "var(--text-3)", fontSize: 13, fontFamily: "var(--font-mono)" }}>
            cargando datos…
          </div>
        </Card>
      )}
      {!loading && fetchError && (
        <div style={{
          padding: "10px 12px",
          background: "var(--warn-soft)",
          border: "1px solid color-mix(in srgb, var(--warn) 30%, transparent)",
          borderRadius: "var(--r-2)", fontSize: 12, color: "var(--text-2)",
        }}>
          <strong style={{ color: "var(--warn)" }}>Aviso:</strong> {fetchError} — mostrando datos de muestra.
        </div>
      )}

      {/* Hero stats */}
      <div className="af-stack-mobile" style={{ display: "grid", gridTemplateColumns: "1.6fr 1fr", gap: 14 }}>
        <Card padded={false}>
          <div style={{ padding: 22, paddingBottom: 4 }}>
            <div style={{ display: "flex", alignItems: "flex-start", gap: 14 }}>
              <div>
                <div className="eyebrow">{m.label.toUpperCase()} · {range.toUpperCase()}</div>
                <div style={{ display: "flex", alignItems: "baseline", gap: 6, marginTop: 6 }}>
                  <span className="num" style={{ fontSize: 44, fontWeight: 500, letterSpacing: "-0.025em", color: m.color }}>{fmt1(avg)}</span>
                  <span style={{ fontSize: 14, color: "var(--text-3)" }}>{m.unit}</span>
                  <span style={{ marginLeft: 12, fontSize: 12.5, color: "var(--text-3)" }}>media</span>
                </div>
                <div style={{ display: "flex", gap: 14, marginTop: 8 }}>
                  <span style={{ fontSize: 12, color: "var(--text-3)" }}>min <span className="num" style={{ color: "var(--text-2)" }}>{fmt1(minV)}</span></span>
                  <span style={{ fontSize: 12, color: "var(--text-3)" }}>máx <span className="num" style={{ color: "var(--text-2)" }}>{fmt1(maxV)}</span></span>
                  {delta != null && (
                    <span style={{ fontSize: 12 }}>tendencia <Trend delta={Number(delta.toFixed(1))} unit="%" goodDirection={m.value === "rhr" || m.value === "weight" || m.value === "body" ? "down" : "up"} /></span>
                  )}
                </div>
              </div>
              <div style={{ flex: 1 }} />
              <Source sources={m.value === "weight" || m.value === "body" ? ["Eufy"] : ["Garmin"]} />
            </div>
          </div>
          <div style={{ padding: "0 12px 14px" }}>
            {hasData ? (
              <AreaChart data={values} width={680} height={220} color={m.color} xLabels={xLabels} />
            ) : (
              <EmptyMetric label={m.label} />
            )}
          </div>
        </Card>

        {/* Side: lectura derivada de los datos reales. */}
        <Card>
          <div className="eyebrow" style={{ marginBottom: 12 }}>LECTURA</div>
          <MetricVerdict metric={m} avg={avg} delta={delta} hasData={hasData} sampleSize={values.length} rangeDays={days} />
        </Card>
      </div>

      {/* Distribution + events — calculadas desde los datos reales. */}
      <div className="af-stack-mobile" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
        <Card>
          <div className="eyebrow" style={{ marginBottom: 12 }}>DISTRIBUCIÓN POR DÍA DE LA SEMANA</div>
          {hasData ? <DowDistribution data={data} metricKey={m.key} color={m.color} /> : <EmptyMetric label={m.label} compact />}
        </Card>
        <Card>
          <div style={{ display: "flex", alignItems: "center", marginBottom: 10 }}>
            <div className="eyebrow">EVENTOS RECIENTES</div>
            <div style={{ flex: 1 }} />
            <span style={{ fontSize: 11, color: "var(--text-3)", fontFamily: "var(--font-mono)" }}>{values.length} mediciones</span>
          </div>
          <div style={{ display: "flex", flexDirection: "column", maxHeight: 180, overflowY: "auto" }}>
            {data.slice(-8).reverse().map((d, i) => (
              <div key={i} style={{
                display: "grid", gridTemplateColumns: "60px 1fr auto",
                gap: 12, padding: "8px 0", alignItems: "center",
                borderBottom: i === 7 ? "none" : "1px dashed var(--line-soft)",
                fontSize: 12.5,
              }}>
                <span className="num" style={{ color: "var(--text-3)" }}>{d.label}</span>
                <span className="num" style={{ fontWeight: 500 }}>{fmt1(d[m.key])} {m.unit}</span>
                <Source sources={m.value === "weight" || m.value === "body" ? ["Eufy"] : ["Garmin"]} />
              </div>
            ))}
            {data.length === 0 && (
              <div style={{ padding: "20px 0", textAlign: "center", fontSize: 12, color: "var(--text-3)", fontFamily: "var(--font-mono)" }}>
                sin mediciones en este rango
              </div>
            )}
          </div>
        </Card>
      </div>
    </div>
  );
};

/* ───────── helpers de la pantalla métrica ───────── */

const EmptyMetric = ({ label, compact }) => (
  <div style={{
    padding: compact ? "16px 10px" : "40px 10px",
    textAlign: "center",
    fontSize: 12, color: "var(--text-3)",
    fontFamily: "var(--font-mono)",
    border: "1px dashed var(--line)", borderRadius: "var(--r-2)",
  }}>
    Sin mediciones de {label.toLowerCase()} en este rango.<br />
    <span style={{ color: "var(--text-4)", fontSize: 10, marginTop: 6, display: "inline-block" }}>
      Sincronizá tu provider o ampliá el rango.
    </span>
  </div>
);

/* MetricVerdict — texto interpretativo basado en valor real, no hardcoded.
 * Reglas conservadoras: sólo afirmamos lo que los números soportan. */
const MetricVerdict = ({ metric, avg, delta, hasData, sampleSize, rangeDays }) => {
  if (!hasData || avg == null) {
    return (
      <div style={{ fontSize: 12.5, color: "var(--text-3)", lineHeight: 1.55 }}>
        No hay suficientes datos para esta métrica en el rango seleccionado.
      </div>
    );
  }
  const goodDown = metric.value === "rhr" || metric.value === "weight" || metric.value === "body";
  const direction = delta == null ? "estable" : (delta > 1.5 ? (goodDown ? "subiendo" : "subiendo") : delta < -1.5 ? (goodDown ? "bajando" : "bajando") : "estable");
  const tone = delta == null ? "info" : (Math.abs(delta) < 1.5 ? "info" : (goodDown ? (delta < 0 ? "good" : "warn") : (delta > 0 ? "good" : "warn")));
  const headline = (() => {
    if (direction === "estable") return `Tu ${metric.label.toLowerCase()} está estable.`;
    if (metric.value === "hrv") return delta > 0 ? "HRV en alza — recuperación trabajando." : "HRV cayendo — atento a la carga.";
    if (metric.value === "sleep") return delta > 0 ? "Estás durmiendo más." : "Estás durmiendo menos.";
    if (metric.value === "rhr") return delta < 0 ? "Tu FC reposo baja — buena señal." : "Tu FC reposo sube — descanso o estrés agudo.";
    if (metric.value === "weight") return delta < 0 ? "Estás bajando peso." : "Estás subiendo peso.";
    if (metric.value === "body") return delta < 0 ? "Bajando grasa corporal." : "Subiendo grasa corporal.";
    if (metric.value === "energy") return delta > 0 ? "Energía al alza." : "Energía a la baja.";
    return `Tendencia ${direction}.`;
  })();
  const detail = `Media ${avg.toFixed(1)}${metric.unit ? ` ${metric.unit}` : ""} sobre ${sampleSize} día${sampleSize === 1 ? "" : "s"} (rango ${rangeDays}d).${delta != null ? ` Cambio ${delta > 0 ? "+" : ""}${delta.toFixed(1)}%.` : ""}`;
  return (
    <>
      <div className="display" style={{ fontSize: 20, lineHeight: 1.2, marginBottom: 8, color: tone === "good" ? "var(--good)" : tone === "warn" ? "var(--warn)" : "var(--text)" }}>
        {headline}
      </div>
      <div style={{ fontSize: 12.5, color: "var(--text-2)", lineHeight: 1.55, marginBottom: 14 }}>
        {detail}
      </div>
      <div style={{ fontSize: 11, color: "var(--text-3)", borderTop: "1px solid var(--line-soft)", paddingTop: 12 }}>
        Para una lectura cualitativa más profunda, abrí "Coach" y preguntale por tendencias.
      </div>
    </>
  );
};

/* DowDistribution — promedio por día de la semana basado en `data`.
 * El día se infiere de `d.date` (ISO yyyy-mm-dd). */
const DowDistribution = ({ data, metricKey, color }) => {
  // 0=Lun ... 6=Dom (queremos arrancar en lunes)
  const buckets = [[], [], [], [], [], [], []];
  data.forEach((d) => {
    if (!d.date) return;
    const dt = new Date(d.date + "T12:00:00Z");
    if (isNaN(dt.getTime())) return;
    const jsDow = dt.getUTCDay(); // 0=Sun ... 6=Sat
    const localDow = (jsDow + 6) % 7; // 0=Mon ... 6=Sun
    const v = Number(d[metricKey]);
    if (!isNaN(v)) buckets[localDow].push(v);
  });
  const avgs = buckets.map((arr) => arr.length === 0 ? 0 : arr.reduce((a, b) => a + b, 0) / arr.length);
  const counts = buckets.map((arr) => arr.length);
  // Bars espera valores en alguna escala; multiplicamos por 10 para darle altura visual igual al original.
  const max = Math.max(...avgs);
  const scaleFactor = max > 0 ? 100 / max : 1;
  return (
    <>
      <Bars
        data={avgs.map((v) => v * scaleFactor)}
        labels={["L", "M", "X", "J", "V", "S", "D"]}
        width={460} height={120}
        color={color}
      />
      <div style={{ marginTop: 8, fontSize: 11, color: "var(--text-3)", fontFamily: "var(--font-mono)" }}>
        muestras por día: {counts.join(" · ")}
      </div>
    </>
  );
};

window.Metrics = Metrics;
