// Controls.jsx — right-hand panel of inputs

const { useState } = React;

function Section({ title, children, defaultOpen = true }) {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <div style={{ borderTop: "1px solid #e5e5e3" }}>
      <button
        type="button"
        onClick={() => setOpen(!open)}
        style={{
          width: "100%",
          padding: "12px 16px",
          background: "transparent",
          border: "none",
          textAlign: "left",
          fontFamily: "inherit",
          fontSize: 11,
          fontWeight: 600,
          letterSpacing: "0.08em",
          textTransform: "uppercase",
          color: "#1a1a1a",
          cursor: "pointer",
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
        }}
      >
        <span>{title}</span>
        <span style={{ color: "#999", fontSize: 14 }}>{open ? "−" : "+"}</span>
      </button>
      {open && <div style={{ padding: "0 16px 16px" }}>{children}</div>}
    </div>
  );
}

function Field({ label, children, hint }) {
  return (
    <div style={{ marginBottom: 12 }}>
      {label && <div style={{ fontSize: 11, color: "#666", marginBottom: 6, fontWeight: 500 }}>{label}</div>}
      {children}
      {hint && <div style={{ fontSize: 10, color: "#999", marginTop: 4 }}>{hint}</div>}
    </div>
  );
}

const inputStyle = {
  width: "100%",
  padding: "8px 10px",
  fontSize: 13,
  fontFamily: "inherit",
  border: "1px solid #d8d8d6",
  borderRadius: 4,
  background: "white",
  color: "#1a1a1a",
  outline: "none",
};

const textareaStyle = { ...inputStyle, fontFamily: '"JetBrains Mono", monospace', fontSize: 11, lineHeight: 1.5, resize: "vertical" };

function Chips({ options, value, onChange, getKey, getLabel, swatch }) {
  return (
    <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
      {options.map((opt) => {
        const k = getKey(opt);
        const active = k === value;
        return (
          <button
            key={k}
            type="button"
            onClick={() => onChange(k)}
            style={{
              padding: "6px 10px",
              fontSize: 11,
              fontFamily: "inherit",
              border: active ? "1px solid #1a1a1a" : "1px solid #d8d8d6",
              background: active ? "#1a1a1a" : "white",
              color: active ? "white" : "#1a1a1a",
              borderRadius: 999,
              cursor: "pointer",
              display: "inline-flex",
              alignItems: "center",
              gap: 6,
            }}
          >
            {swatch && swatch(opt)}
            {getLabel(opt)}
          </button>
        );
      })}
    </div>
  );
}

function Slider({ value, min, max, step = 1, onChange, suffix }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
      <input
        type="range"
        min={min}
        max={max}
        step={step}
        value={value}
        onChange={(e) => onChange(Number(e.target.value))}
        style={{ flex: 1, accentColor: "#1a1a1a" }}
      />
      <div style={{ minWidth: 48, textAlign: "right", fontSize: 11, fontFamily: '"JetBrains Mono", monospace', color: "#1a1a1a" }}>
        {value}{suffix || ""}
      </div>
    </div>
  );
}

function ColorRow({ label, value, onChange }) {
  return (
    <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "6px 0" }}>
      <span style={{ fontSize: 12, color: "#333" }}>{label}</span>
      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
        <input
          type="text"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          style={{ ...inputStyle, width: 90, fontSize: 11, padding: "4px 6px", fontFamily: '"JetBrains Mono", monospace' }}
        />
        <input
          type="color"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          style={{ width: 28, height: 28, padding: 0, border: "1px solid #d8d8d6", borderRadius: 4, background: "white", cursor: "pointer" }}
        />
      </div>
    </div>
  );
}

// Read an image file → downscaled JPEG dataURL (keeps autosave under the
// localStorage quota while staying sharp enough for the Player art block).
function readPhotoAsDataURL(file, maxDim) {
  return new Promise((resolve, reject) => {
    const fr = new FileReader();
    fr.onerror = reject;
    fr.onload = () => {
      const img = new Image();
      img.onerror = reject;
      img.onload = () => {
        const scale = Math.min(1, maxDim / Math.max(img.width, img.height));
        const canvas = document.createElement("canvas");
        canvas.width = Math.round(img.width * scale);
        canvas.height = Math.round(img.height * scale);
        canvas.getContext("2d").drawImage(img, 0, 0, canvas.width, canvas.height);
        resolve(canvas.toDataURL("image/jpeg", 0.88));
      };
      img.src = fr.result;
    };
    fr.readAsDataURL(file);
  });
}

// Derive a 5-color palette from a single base color (hex)
function derivePalette(baseHex) {
  // Convert hex -> hsl, then create variants
  const hex = baseHex.replace("#", "");
  const r = parseInt(hex.slice(0, 2), 16) / 255;
  const g = parseInt(hex.slice(2, 4), 16) / 255;
  const b = parseInt(hex.slice(4, 6), 16) / 255;
  const max = Math.max(r, g, b), min = Math.min(r, g, b);
  let h = 0, s = 0;
  const l = (max + min) / 2;
  if (max !== min) {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch (max) {
      case r: h = ((g - b) / d + (g < b ? 6 : 0)); break;
      case g: h = ((b - r) / d + 2); break;
      case b: h = ((r - g) / d + 4); break;
    }
    h /= 6;
  }
  function hsl(hh, ss, ll) {
    return `hsl(${(hh * 360).toFixed(0)} ${(ss * 100).toFixed(0)}% ${(ll * 100).toFixed(0)}%)`;
  }
  return {
    label: "Custom",
    bg: hsl(h, Math.min(s * 0.3, 0.15), Math.min(0.96, l + 0.45)),
    ink: hsl(h, Math.min(s * 0.6, 0.5), Math.max(0.12, l - 0.5)),
    accent: baseHex,
    muted: hsl(h, Math.min(s * 0.4, 0.2), Math.min(0.78, l + 0.25)),
    highlight: hsl((h + 0.55) % 1, Math.min(s * 0.5, 0.4), Math.max(0.5, l)),
  };
}

function Controls({ state, set, applyPreset }) {
  const isCustomSize = state.sizeKey === "Custom";

  return (
    <div style={{ height: "100%", overflow: "auto", paddingBottom: 80 }}>
      {/* Header */}
      <div style={{ padding: "16px 16px 14px" }}>
        <div style={{ fontSize: 11, color: "#999", letterSpacing: "0.1em", textTransform: "uppercase", marginBottom: 4 }}>Lyrics Poster Studio</div>
        <div style={{ fontSize: 18, fontWeight: 700, letterSpacing: "-0.01em" }}>Compose your poster</div>
      </div>

      {/* Size */}
      <Section title="Format">
        <Field label="Size">
          <Chips
            options={Object.entries(SIZES).map(([k, v]) => ({ k, ...v }))}
            value={state.sizeKey}
            onChange={(k) => set({ sizeKey: k })}
            getKey={(o) => o.k}
            getLabel={(o) => o.label}
          />
        </Field>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }}>
          <Field label="Width (mm)">
            <input
              type="number"
              value={state.customW}
              onChange={(e) => set({ customW: Number(e.target.value) || 100, sizeKey: "Custom" })}
              style={inputStyle}
              min={50}
              max={1500}
            />
          </Field>
          <Field label="Height (mm)">
            <input
              type="number"
              value={state.customH}
              onChange={(e) => set({ customH: Number(e.target.value) || 100, sizeKey: "Custom" })}
              style={inputStyle}
              min={50}
              max={1500}
            />
          </Field>
        </div>
        {!isCustomSize && (
          <div style={{ fontSize: 10, color: "#999" }}>
            Editing dimensions switches to Custom.
          </div>
        )}
      </Section>

      {/* Layout */}
      <Section title="Layout">
        <Field label="Style">
          <Chips
            options={LAYOUTS}
            value={state.layout}
            onChange={(k) => set({ layout: k })}
            getKey={(o) => o.id}
            getLabel={(o) => o.label}
          />
        </Field>
        <Field label="Lyric alignment">
          <Chips
            options={[
              { id: "left", label: "Left" },
              { id: "center", label: "Center" },
              { id: "right", label: "Right" },
            ]}
            value={state.lyricAlign}
            onChange={(k) => set({ lyricAlign: k })}
            getKey={(o) => o.id}
            getLabel={(o) => o.label}
          />
        </Field>
        {state.layout === "tape" && (
          <Field label={`Tape bands (${state.tapeCount})`}>
            <Slider value={state.tapeCount} min={1} max={6} onChange={(v) => set({ tapeCount: v })} />
          </Field>
        )}
        {(state.layout === "player" || state.layout === "vinyl") && (
          <Field
            label="Artwork"
            hint={state.photo
              ? (state.layout === "player"
                  ? "Your photo fills the artwork square. Remove it to show the hero word instead."
                  : "Your photo is pressed into the record's centre label. Remove it to show the title label instead.")
              : "Optional: upload a photo for the artwork (kept locally, up to ~2400px). Used by Player and Vinyl."}
          >
            <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
              <label style={{ ...inputStyle, cursor: "pointer", background: "#f7f7f5", textAlign: "center", flex: 1 }}>
                {state.photo ? "Replace photo…" : "Upload photo…"}
                <input
                  type="file"
                  accept="image/*"
                  style={{ display: "none" }}
                  onChange={(e) => {
                    const file = e.target.files && e.target.files[0];
                    e.target.value = "";
                    if (!file) return;
                    readPhotoAsDataURL(file, 2400).then((dataUrl) => set({ photo: dataUrl }))
                      .catch(() => alert("Couldn't read that image — try a JPEG or PNG."));
                  }}
                />
              </label>
              {state.photo && (
                <button
                  type="button"
                  onClick={() => set({ photo: null })}
                  style={{ ...inputStyle, width: "auto", cursor: "pointer", color: "#c8262a" }}
                >
                  Remove
                </button>
              )}
            </div>
            {state.photo && (
              <img src={state.photo} alt="Player artwork preview" style={{ marginTop: 8, width: 72, height: 72, objectFit: "cover", borderRadius: 4, border: "1px solid #d8d8d6", display: "block" }} />
            )}
          </Field>
        )}
      </Section>

      {/* Text */}
      <Section title="Text">
        <Field label="Hero word">
          <input
            type="text"
            value={state.hero}
            onChange={(e) => set({ hero: e.target.value })}
            style={{ ...inputStyle, fontWeight: 600 }}
            placeholder="wildfire"
          />
        </Field>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8, marginTop: 12 }}>
          <div style={{ fontSize: 11, color: "#666", fontWeight: 500 }}>Lyric blocks</div>
          <label style={{ fontSize: 10, color: "#666", display: "inline-flex", alignItems: "center", gap: 4, cursor: "pointer" }}>
            <input
              type="checkbox"
              checked={state.advanced}
              onChange={(e) => set({ advanced: e.target.checked })}
            />
            Advanced
          </label>
        </div>
        {state.blocks.map((b, i) => (
          <div key={b.id} style={{ marginBottom: 10 }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 4 }}>
              <span style={{ fontSize: 10, color: "#999", fontFamily: '"JetBrains Mono", monospace' }}>Block {i + 1}</span>
              {state.advanced && state.blocks.length > 1 && (
                <button
                  type="button"
                  onClick={() => {
                    const next = state.blocks.filter((x) => x.id !== b.id);
                    set({ blocks: next });
                  }}
                  style={{ background: "none", border: "none", color: "#999", cursor: "pointer", fontSize: 11 }}
                >
                  remove
                </button>
              )}
            </div>
            <textarea
              value={b.text}
              onChange={(e) => {
                const next = [...state.blocks];
                next[i] = { ...b, text: e.target.value };
                set({ blocks: next });
              }}
              rows={5}
              placeholder="Type or paste lyrics here…"
              style={textareaStyle}
            />
            {state.advanced && (
              <div style={{ display: "flex", alignItems: "center", gap: 6, marginTop: 5 }}>
                <span style={{ fontSize: 10, color: "#999", fontFamily: '"JetBrains Mono", monospace' }}>align</span>
                {[
                  { id: undefined, label: "Auto" },
                  { id: "left", label: "L" },
                  { id: "center", label: "C" },
                  { id: "right", label: "R" },
                ].map((opt) => {
                  const active = (b.align || undefined) === opt.id;
                  return (
                    <button
                      key={opt.label}
                      type="button"
                      onClick={() => {
                        const next = [...state.blocks];
                        const { align, ...rest } = b;
                        next[i] = opt.id ? { ...rest, align: opt.id } : { ...rest };
                        set({ blocks: next });
                      }}
                      style={{
                        padding: "2px 8px",
                        fontSize: 10,
                        fontFamily: "inherit",
                        border: active ? "1px solid #1a1a1a" : "1px solid #d8d8d6",
                        background: active ? "#1a1a1a" : "white",
                        color: active ? "white" : "#666",
                        borderRadius: 3,
                        cursor: "pointer",
                      }}
                    >
                      {opt.label}
                    </button>
                  );
                })}
              </div>
            )}
          </div>
        ))}
        {state.advanced && (
          <button
            type="button"
            onClick={() => {
              const id = "b" + Date.now();
              set({ blocks: [...state.blocks, { id, text: "" }] });
            }}
            style={{ ...inputStyle, cursor: "pointer", background: "#f7f7f5", textAlign: "center" }}
          >
            + Add lyric block
          </button>
        )}
      </Section>

      {/* Typography */}
      <Section title="Typography">
        <Field label="Hero font">
          <select value={state.heroFontId} onChange={(e) => set({ heroFontId: e.target.value })} style={inputStyle}>
            {FONTS.map((f) => (
              <option key={f.id} value={f.id}>{f.label} — {f.kind}</option>
            ))}
          </select>
        </Field>
        <Field label="Body font">
          <select value={state.bodyFontId} onChange={(e) => set({ bodyFontId: e.target.value })} style={inputStyle}>
            {BODY_FONTS.map((f) => (
              <option key={f.id} value={f.id}>{f.label}</option>
            ))}
          </select>
        </Field>
        <Field label={`Hero size (${state.heroSize}%)`} hint="Scales the hero word in every layout.">
          <Slider value={state.heroSize} min={20} max={200} step={5} onChange={(v) => set({ heroSize: v })} suffix="%" />
        </Field>
        <Field label={`Body size (${state.bodySize}mm)`}>
          <Slider value={state.bodySize} min={2} max={12} step={0.5} onChange={(v) => set({ bodySize: v })} suffix="mm" />
        </Field>
        <Field label={`Margin (${state.padding}mm)`}>
          <Slider value={state.padding} min={5} max={40} onChange={(v) => set({ padding: v })} suffix="mm" />
        </Field>
      </Section>

      {/* Colors */}
      <Section title="Colors">
        <Field label="Mode">
          <Chips
            options={[
              { id: "preset", label: "Preset" },
              { id: "derive", label: "From base color" },
              { id: "manual", label: "Manual" },
            ]}
            value={state.colorMode}
            onChange={(id) => set({ colorMode: id })}
            getKey={(o) => o.id}
            getLabel={(o) => o.label}
          />
        </Field>

        {state.colorMode === "preset" && (
          <Field label="Palette">
            {PALETTE_GROUPS.map((g) => (
              <div key={g} style={{ marginBottom: 10 }}>
                <div style={{ fontSize: 10, color: "#999", letterSpacing: "0.08em", textTransform: "uppercase", margin: "4px 0 6px" }}>{g}</div>
                <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6 }}>
                  {Object.entries(PALETTES).filter(([, p]) => p.group === g).map(([k, p]) => {
                    const active = k === state.paletteKey;
                    return (
                      <button
                        key={k}
                        type="button"
                        onClick={() => set({ paletteKey: k })}
                        style={{
                          padding: "8px",
                          border: active ? "2px solid #1a1a1a" : "1px solid #d8d8d6",
                          borderRadius: 6,
                          background: "white",
                          cursor: "pointer",
                          textAlign: "left",
                        }}
                      >
                        <div style={{ display: "flex", gap: 2, marginBottom: 6 }}>
                          {[p.bg, p.ink, p.accent, p.muted, p.highlight].map((c, i) => (
                            <div key={i} style={{ width: 14, height: 14, background: c, borderRadius: 2, border: "1px solid rgba(0,0,0,.06)" }} />
                          ))}
                        </div>
                        <div style={{ fontSize: 11, fontWeight: 600 }}>{p.label}</div>
                      </button>
                    );
                  })}
                </div>
              </div>
            ))}
          </Field>
        )}

        {state.colorMode === "derive" && (
          <>
            <Field label="Base color">
              <ColorRow label="Base" value={state.baseColor} onChange={(v) => set({ baseColor: v })} />
            </Field>
            <div style={{ fontSize: 10, color: "#999" }}>
              The system derives bg, ink, accent, muted and highlight from this color.
            </div>
          </>
        )}

        {state.colorMode === "manual" && (
          <div>
            <ColorRow label="Background" value={state.manualPalette.bg} onChange={(v) => set({ manualPalette: { ...state.manualPalette, bg: v } })} />
            <ColorRow label="Lyric ink" value={state.manualPalette.ink} onChange={(v) => set({ manualPalette: { ...state.manualPalette, ink: v } })} />
            <ColorRow label="Hero / accent" value={state.manualPalette.accent} onChange={(v) => set({ manualPalette: { ...state.manualPalette, accent: v } })} />
            <ColorRow label="Muted" value={state.manualPalette.muted} onChange={(v) => set({ manualPalette: { ...state.manualPalette, muted: v } })} />
            <ColorRow label="Highlight" value={state.manualPalette.highlight} onChange={(v) => set({ manualPalette: { ...state.manualPalette, highlight: v } })} />
          </div>
        )}
      </Section>

      {/* Pattern */}
      <Section title="Background pattern">
        <Field label="Type">
          <Chips
            options={PATTERNS}
            value={state.pattern}
            onChange={(k) => set({ pattern: k })}
            getKey={(o) => o.id}
            getLabel={(o) => o.label}
          />
        </Field>
        <Field label={`Scale (${state.patternScale}mm)`}>
          <Slider value={state.patternScale} min={3} max={120} onChange={(v) => set({ patternScale: v })} suffix="mm" />
        </Field>
        <Field label={`Density (${state.patternDensity}%)`}>
          <Slider value={state.patternDensity} min={0} max={100} onChange={(v) => set({ patternDensity: v })} suffix="%" />
        </Field>
        {(state.pattern === "arcs" || state.pattern === "rays") && (
          <Field label={`Origin X (${state.patternOriginX}%)`}>
            <Slider value={state.patternOriginX} min={-20} max={120} onChange={(v) => set({ patternOriginX: v })} suffix="%" />
          </Field>
        )}
        {state.pattern === "wave" && (
          <Field label={`Thickness (${state.patternThickness}mm)`}>
            <Slider value={state.patternThickness} min={0.2} max={6} step={0.1} onChange={(v) => set({ patternThickness: v })} suffix="mm" />
          </Field>
        )}
        {(() => {
          const smartUsable = state.pattern === "arcs" || state.pattern === "rays" || state.pattern === "bands" || state.layout === "split";
          return (
            <label style={{ display: "flex", alignItems: "flex-start", gap: 8, padding: "8px 10px", background: "#f7f7f5", borderRadius: 4, cursor: smartUsable ? "pointer" : "default", marginTop: 4, opacity: smartUsable ? 1 : 0.45 }}>
              <input
                type="checkbox"
                checked={!!state.smartContrast}
                disabled={!smartUsable}
                onChange={(e) => set({ smartContrast: e.target.checked })}
                style={{ marginTop: 2 }}
              />
              <div>
                <div style={{ fontSize: 12, fontWeight: 600, color: "#1a1a1a" }}>Smart contrast</div>
                <div style={{ fontSize: 10, color: "#777", marginTop: 2, lineHeight: 1.4 }}>
                  {smartUsable
                    ? "When a shape would match the hero color, the text swaps to a different palette color so it always stands out."
                    : "Available with Arcs, Rays or Bands patterns, or the Split layout."}
                </div>
              </div>
            </label>
          );
        })()}
      </Section>

      {/* Quick presets */}
      <Section title="Quick presets" defaultOpen={false}>
        <div style={{ display: "grid", gap: 6 }}>
          <button type="button" onClick={() => applyPreset("belter")} style={presetBtn}>Belter — Stamped × Cream</button>
          <button type="button" onClick={() => applyPreset("canter")} style={presetBtn}>Canter — Bleed × Teal</button>
          <button type="button" onClick={() => applyPreset("neon")} style={presetBtn}>Neon — Tower × Black</button>
          <button type="button" onClick={() => applyPreset("repeat")} style={presetBtn}>Mantra — Repeat × Mono</button>
          <button type="button" onClick={() => applyPreset("split")} style={presetBtn}>Split — Side band × Earth</button>
          <button type="button" onClick={() => applyPreset("tape")} style={presetBtn}>Tape — Diagonal band × Paper</button>
        </div>
      </Section>
    </div>
  );
}

const presetBtn = {
  padding: "8px 10px",
  fontSize: 12,
  fontFamily: "inherit",
  border: "1px solid #d8d8d6",
  borderRadius: 4,
  background: "white",
  color: "#1a1a1a",
  cursor: "pointer",
  textAlign: "left",
};

window.Controls = Controls;
window.derivePalette = derivePalette;
