// Shared utilities and components

// ----- Number / currency formatters -----
const fmtPKR = (n, opts = {}) => {
  if (n === null || n === undefined || isNaN(n)) return "-";
  const { compact = false, symbol = "Rs." } = opts;
  if (compact) {
    if (Math.abs(n) >= 10000000) return `${symbol} ${(n / 10000000).toFixed(2)} crore`;
    if (Math.abs(n) >= 100000) return `${symbol} ${(n / 100000).toFixed(2)} lakh`;
    if (Math.abs(n) >= 1000) return `${symbol} ${(n / 1000).toFixed(1)}k`;
  }
  // Indian/Pakistani digit grouping: lakhs + crores
  const x = Math.round(n);
  const s = String(Math.abs(x));
  const lastThree = s.slice(-3);
  const rest = s.slice(0, -3);
  const grouped = (rest ? rest.replace(/\B(?=(\d{2})+(?!\d))/g, ",") + "," : "") + lastThree;
  return `${symbol} ${x < 0 ? "-" : ""}${grouped}`;
};

const fmtUnits = (n) => {
  if (n === null || n === undefined || isNaN(n)) return "-";
  return n < 10 ? n.toFixed(2) : n < 100 ? n.toFixed(1) : Math.round(n).toLocaleString("en-US");
};

const parseTime = (t) => {
  const [h, m] = (t || "0:0").split(":").map(Number);
  return h + (m || 0) / 60;
};

// Hours between start and end, handling wrap-around
const hoursBetween = (start, end) => {
  const s = parseTime(start);
  const e = parseTime(end);
  let diff = e - s;
  if (diff <= 0) diff += 24;
  if (diff > 23.999) diff = 24;
  return diff;
};

// ----- Visual components -----

const ss = {
  card: {
    background: "var(--surface)",
    border: "1px solid var(--border-soft)",
    borderRadius: "var(--radius)",
    padding: 16,
    boxShadow: "var(--shadow)",
  },
  label: {
    fontFamily: "var(--font-mono)",
    fontSize: 11,
    letterSpacing: "0.06em",
    textTransform: "uppercase",
    color: "var(--muted)",
    fontWeight: 500,
  },
  input: {
    width: "100%",
    padding: "10px 12px",
    background: "var(--surface)",
    border: "1px solid var(--border)",
    borderRadius: "var(--radius-sm)",
    fontSize: 15,
    color: "var(--fg)",
  },
};

const Section = ({ title, hint, action, children, style }) => (
  <section style={{ padding: "20px 18px", borderBottom: "1px solid var(--border-soft)", ...style }}>
    {(title || hint || action) && (
      <header style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", marginBottom: 12, gap: 12 }}>
        <div>
          {title && <div style={ss.label}>{title}</div>}
          {hint && <div style={{ fontSize: 13, color: "var(--muted)", marginTop: 2 }}>{hint}</div>}
        </div>
        {action}
      </header>
    )}
    {children}
  </section>
);

const PrimaryButton = ({ children, onClick, disabled, full, variant = "primary", icon, style }) => {
  const bg = variant === "primary" ? "var(--fg)" : variant === "ghost" ? "transparent" : "var(--surface)";
  const fg = variant === "primary" ? "var(--surface)" : "var(--fg)";
  const border = variant === "ghost" ? "1px solid var(--border)" : variant === "secondary" ? "1px solid var(--border)" : "1px solid var(--fg)";
  return (
    <button onClick={onClick} disabled={disabled} style={{
      display: "inline-flex", alignItems: "center", justifyContent: "center",
      gap: 8, padding: "12px 18px",
      background: bg, color: fg, border,
      borderRadius: 999,
      fontWeight: 500, fontSize: 14,
      opacity: disabled ? 0.4 : 1,
      width: full ? "100%" : "auto",
      transition: "transform .08s ease",
      ...style,
    }}>
      {icon}{children}
    </button>
  );
};

const Pill = ({ children, tone = "default", style, onClick }) => {
  const tones = {
    default: { bg: "var(--bg-2)", fg: "var(--fg-2)", border: "var(--border-soft)" },
    accent:  { bg: "var(--accent-soft)", fg: "var(--accent-ink)", border: "transparent" },
    solar:   { bg: "var(--solar-soft)", fg: "var(--solar-ink)", border: "transparent" },
    ghost:   { bg: "transparent", fg: "var(--muted)", border: "var(--border-soft)" },
  };
  const t = tones[tone] || tones.default;
  return (
    <span onClick={onClick} style={{
      display: "inline-flex", alignItems: "center", gap: 6,
      padding: "3px 9px", fontSize: 12, fontWeight: 500,
      background: t.bg, color: t.fg,
      border: `1px solid ${t.border}`, borderRadius: 999,
      cursor: onClick ? "pointer" : "default",
      ...style,
    }}>{children}</span>
  );
};

const Toggle = ({ options, value, onChange, full }) => (
  <div style={{
    display: "inline-grid", gridTemplateColumns: `repeat(${options.length}, 1fr)`,
    gap: 2, padding: 3, background: "var(--bg-2)",
    border: "1px solid var(--border-soft)", borderRadius: 999,
    width: full ? "100%" : "auto",
  }}>
    {options.map((opt) => {
      const v = typeof opt === "string" ? opt : opt.value;
      const label = typeof opt === "string" ? opt : opt.label;
      const active = v === value;
      return (
        <button key={v} onClick={() => onChange(v)} style={{
          padding: "8px 14px",
          borderRadius: 999,
          fontSize: 13, fontWeight: 500,
          background: active ? "var(--surface)" : "transparent",
          color: active ? "var(--fg)" : "var(--muted)",
          boxShadow: active ? "var(--shadow-sm)" : "none",
          transition: "all .15s ease",
          whiteSpace: "nowrap",
        }}>{label}</button>
      );
    })}
  </div>
);

const NumberField = ({ value, onChange, prefix, suffix, placeholder, min, max, step = 1, mono = true, large = false }) => (
  <div style={{
    display: "flex", alignItems: "center",
    background: "var(--surface)",
    border: "1px solid var(--border)", borderRadius: "var(--radius-sm)",
    padding: large ? "4px 8px 4px 16px" : "2px 4px 2px 12px",
    transition: "border-color .15s ease",
  }}
    onFocus={(e) => { e.currentTarget.style.borderColor = "var(--fg)"; }}
    onBlur={(e) => { e.currentTarget.style.borderColor = "var(--border)"; }}
  >
    {prefix && <span style={{ color: "var(--muted)", fontSize: large ? 16 : 13, marginRight: 8, fontFamily: mono ? "var(--font-mono)" : undefined }}>{prefix}</span>}
    <input
      type="number"
      value={value === 0 ? 0 : (value || "")}
      onChange={(e) => onChange(e.target.value === "" ? "" : Number(e.target.value))}
      placeholder={placeholder}
      min={min} max={max} step={step}
      style={{
        flex: 1, width: "100%",
        background: "transparent", border: "none",
        padding: large ? "12px 0" : "9px 0",
        fontFamily: mono ? "var(--font-mono)" : "var(--font-sans)",
        fontSize: large ? 22 : 15,
        fontWeight: large ? 500 : 400,
        color: "var(--fg)",
      }}
    />
    {suffix && <span style={{ color: "var(--muted)", fontSize: 13, marginRight: 8, fontFamily: mono ? "var(--font-mono)" : undefined }}>{suffix}</span>}
  </div>
);

const StatRow = ({ label, value, hint, emphasis }) => (
  <div style={{
    display: "flex", justifyContent: "space-between", alignItems: "baseline",
    padding: "10px 0", borderBottom: "1px dashed var(--border-soft)",
  }}>
    <div>
      <div style={{ fontSize: 14, color: "var(--fg)", fontWeight: emphasis ? 600 : 400 }}>{label}</div>
      {hint && <div style={{ fontSize: 12, color: "var(--muted)" }}>{hint}</div>}
    </div>
    <div className="mono" style={{
      fontSize: emphasis ? 17 : 14,
      fontWeight: emphasis ? 600 : 500,
      color: "var(--fg)",
    }}>{value}</div>
  </div>
);

// Bottom-sheet modal that slides up
const Sheet = ({ open, onClose, title, children, height = "85vh" }) => {
  if (!open) return null;
  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 100,
      background: "oklch(0.2 0.02 60 / 0.45)",
      backdropFilter: "blur(2px)",
      display: "flex", alignItems: "flex-end", justifyContent: "center",
      animation: "sheetFade .2s ease",
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        background: "var(--surface)",
        width: "min(440px, 100%)",
        maxHeight: height,
        height,
        borderRadius: "20px 20px 0 0",
        boxShadow: "var(--shadow-lg)",
        animation: "sheetSlide .25s cubic-bezier(.2,.8,.2,1)",
        display: "flex", flexDirection: "column",
        overflow: "hidden",
      }}>
        <div style={{
          padding: "10px 16px 6px",
          display: "flex", alignItems: "center", justifyContent: "space-between",
          borderBottom: "1px solid var(--border-soft)",
        }}>
          <div style={{ width: 36, height: 4, background: "var(--border)", borderRadius: 999, margin: "0 auto", position: "absolute", left: 0, right: 0, top: 8 }} />
          <div style={{ fontSize: 16, fontWeight: 600, marginTop: 6 }}>{title}</div>
          <button onClick={onClose} aria-label="Close" style={{
            width: 32, height: 32, display: "grid", placeItems: "center",
            borderRadius: 999, color: "var(--muted)",
            background: "var(--bg-2)",
          }}><IconClose size={16} /></button>
        </div>
        <div style={{ flex: 1, overflowY: "auto" }}>{children}</div>
      </div>
      <style>{`
        @keyframes sheetSlide { from { transform: translateY(100%); } to { transform: translateY(0); } }
        @keyframes sheetFade { from { opacity: 0; } to { opacity: 1; } }
      `}</style>
    </div>
  );
};

// Ad slot — shows real AdSense ins when SITE_CONFIG is filled, placeholder otherwise
// Usage: <AdSlot slot="electricity" /> | <AdSlot slot="solar" /> | <AdSlot slot="gas" />
const AdSlot = ({ slot, variant = "banner", style }) => {
  const cfg = window.SITE_CONFIG || {};
  const client = cfg.adsenseClient || "";
  const slotId = (cfg.adSlots || {})[slot] || "";
  const ref = React.useRef(null);

  React.useEffect(() => {
    if (client && slotId && ref.current) {
      try {
        (window.adsbygoogle = window.adsbygoogle || []).push({});
      } catch (_) {}
    }
  }, [client, slotId]);

  if (client && slotId) {
    return (
      <ins
        ref={ref}
        className="adsbygoogle"
        style={{ display: "block", width: "100%", ...style }}
        data-ad-client={client}
        data-ad-slot={slotId}
        data-ad-format="auto"
        data-full-width-responsive="true"
      />
    );
  }

  // Dev / unconfigured placeholder
  return (
    <div style={{
      border: "2px dashed #cbd5e1",
      background: "#f8fafc",
      color: "#94a3b8",
      textAlign: "center",
      padding: "16px",
      margin: "12px 0",
      fontSize: "12px",
      borderRadius: "6px",
      ...style,
    }}>
      Ad slot — {slot} ({variant})
    </div>
  );
};

// Time-of-day visualizer ring
const TimeRing = ({ items, size = 132 }) => {
  const cx = size/2, cy = size/2, r = size/2 - 14;
  const colors = ["#d97706", "#65a30d", "#0891b2", "#a855f7", "#e11d48", "#0d9488", "#ca8a04", "#7c3aed"];
  const segments = items.map((it, i) => {
    const s = parseTime(it.start);
    const e = parseTime(it.end);
    let len = e - s; if (len <= 0) len += 24;
    return { ...it, s, len, color: colors[i % colors.length] };
  });
  const arc = (start, length) => {
    const startAng = (start / 24) * 2 * Math.PI - Math.PI/2;
    const endAng = ((start + length) / 24) * 2 * Math.PI - Math.PI/2;
    const x1 = cx + r * Math.cos(startAng);
    const y1 = cy + r * Math.sin(startAng);
    const x2 = cx + r * Math.cos(endAng);
    const y2 = cy + r * Math.sin(endAng);
    const large = length > 12 ? 1 : 0;
    return `M ${x1} ${y1} A ${r} ${r} 0 ${large} 1 ${x2} ${y2}`;
  };
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      <circle cx={cx} cy={cy} r={r} fill="none" stroke="var(--border-soft)" strokeWidth={6} />
      {segments.map((seg, i) => (
        <path key={i} d={arc(seg.s, seg.len)} fill="none" stroke={seg.color} strokeWidth={6} strokeLinecap="round" opacity="0.85" />
      ))}
      {[0, 6, 12, 18].map((h) => {
        const ang = (h / 24) * 2 * Math.PI - Math.PI/2;
        const x1 = cx + (r-10) * Math.cos(ang);
        const y1 = cy + (r-10) * Math.sin(ang);
        const x2 = cx + (r+6) * Math.cos(ang);
        const y2 = cy + (r+6) * Math.sin(ang);
        return <line key={h} x1={x1} y1={y1} x2={x2} y2={y2} stroke="var(--muted-2)" strokeWidth="1" />;
      })}
      <text x={cx} y={cy-4} textAnchor="middle" fontFamily="var(--font-mono)" fontSize="10" fill="var(--muted)" letterSpacing="0.1em">24H</text>
      <text x={cx} y={cy+10} textAnchor="middle" fontFamily="var(--font-mono)" fontSize="9" fill="var(--muted-2)">CYCLE</text>
    </svg>
  );
};

Object.assign(window, {
  fmtPKR, fmtUnits, parseTime, hoursBetween,
  ss, Section, PrimaryButton, Pill, Toggle, NumberField, StatRow, Sheet,
  AdSlot, TimeRing,
});
