// 橋本商会ポータル — Shared UI components
// Globals expected: React

const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ─────────── Icons (Lucide-style, 24x24) ───────────
const Ico = {
  mic: (p) => <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M5 10v2a7 7 0 0 0 14 0v-2"/><line x1="12" y1="19" x2="12" y2="22"/></svg>,
  stop: (p) => <svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" {...p}><rect x="6" y="6" width="12" height="12" rx="2"/></svg>,
  check: (p) => <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" {...p}><polyline points="20 6 9 17 4 12"/></svg>,
  checkSmall: (p) => <svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" {...p}><polyline points="13 4 6 11 3 8"/></svg>,
  copy: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>,
  plus: (p) => <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" {...p}><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>,
  search: (p) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>,
  back: (p) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><polyline points="15 18 9 12 15 6"/></svg>,
  chevR: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><polyline points="9 18 15 12 9 6"/></svg>,
  chevD: (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><polyline points="6 9 12 15 18 9"/></svg>,
  bell: (p) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>,
  home: (p) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>,
  list: (p) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>,
  user: (p) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>,
  cal: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>,
  chat: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>,
  sparkle: (p) => <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor" {...p}><path d="M12 2l1.5 6.5L20 10l-6.5 1.5L12 18l-1.5-6.5L4 10l6.5-1.5z"/></svg>,
  pin: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 22s8-7.5 8-13a8 8 0 1 0-16 0c0 5.5 8 13 8 13z"/><circle cx="12" cy="9" r="3"/></svg>,
  car: (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 17h14M5 17a2 2 0 1 1-4 0M19 17a2 2 0 1 0 4 0M5 17v-5l2-5h10l2 5v5M3 12h18"/></svg>,
  phone: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>,
  edit: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>,
  x: (p) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>,
  filter: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/></svg>,
  arrowR: (p) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>,
  reset: (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg>,
  more: (p) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg>,
};

// ─────────── Brand mark ───────────
function BrandMark({ size = 32 }) {
  return (
    <div className="brand-mark" style={{ width: size, height: size, fontSize: size * 0.42 }}>
      橋
    </div>
  );
}

// ─────────── Hashimoto wordmark (Variant B) ───────────
function HashimotoLogo({ size = 24 }) {
  // Render as inline SVG-like layout: L mark + HASHIMOTO text
  return (
    <div style={{ display: "inline-flex", alignItems: "center", gap: 10, height: size * 1.6 }}>
      <HashimotoMark size={size * 1.6} />
      <span style={{
        fontFamily: '"Helvetica Neue", "Arial Black", Inter, sans-serif',
        fontWeight: 900,
        fontSize: size,
        letterSpacing: "0.06em",
        color: "var(--text)",
      }}>HASHIMOTO</span>
    </div>
  );
}

function HashimotoMark({ size = 32 }) {
  // Distinctive black-L + teal vertical, per brand HP
  const s = size;
  return (
    <svg viewBox="0 0 32 40" width={s * 0.8} height={s} aria-label="HASHIMOTO" style={{ display: "block" }}>
      {/* Black short vertical */}
      <rect x="0" y="14" width="9" height="26" fill="currentColor"/>
      {/* Teal taller vertical */}
      <rect x="12" y="0" width="9" height="40" fill="#2BB0AC"/>
      {/* Black serif notch at bottom-left */}
      <path d="M0 40 L0 32 L9 32 L9 40 Z" fill="currentColor"/>
    </svg>
  );
}

// ─────────── Brand hero (tagline) ───────────
function BrandHero() {
  return (
    <div style={{ padding: "8px 0" }}>
      <h2 className="hero-tagline">Always the<br/>best service.</h2>
      <div className="hero-sub">「最高のサービス」をこれからもずっと。</div>
    </div>
  );
}

// ─────────── Confidence Bar ───────────
function ConfidenceBar({ value = 0.5 }) {
  const pct = Math.round(value * 100);
  const tone = value >= 0.85 ? "var(--success)" : value >= 0.7 ? "var(--accent-strong, var(--primary))" : "var(--warning)";
  return (
    <div style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
      <div style={{ width: 28, height: 4, background: "var(--surface-3)", borderRadius: 2, overflow: "hidden" }}>
        <div style={{ width: `${pct}%`, height: "100%", background: tone, transition: "width .3s ease" }} />
      </div>
      <span className="mono" style={{ fontSize: 10, color: "var(--text-3)", fontVariantNumeric: "tabular-nums" }}>{pct}%</span>
    </div>
  );
}

// ─────────── Fake QR (decorative, deterministic from string) ───────────
function FakeQR({ value = "", size = 96, fg = "var(--text)", bg = "var(--surface)" }) {
  // Generate 21x21 deterministic pattern with corner finders
  const cells = useMemo(() => {
    const N = 21;
    const grid = Array.from({ length: N }, () => Array(N).fill(0));
    // Position finders
    const finder = (r, c) => {
      for (let dr = 0; dr < 7; dr++) for (let dc = 0; dc < 7; dc++) {
        const onBorder = dr === 0 || dr === 6 || dc === 0 || dc === 6;
        const inner = dr >= 2 && dr <= 4 && dc >= 2 && dc <= 4;
        grid[r + dr][c + dc] = (onBorder || inner) ? 1 : 0;
      }
    };
    finder(0, 0); finder(0, N - 7); finder(N - 7, 0);
    // Hash from value
    let h = 0;
    for (let i = 0; i < value.length; i++) { h = (h * 31 + value.charCodeAt(i)) | 0; }
    const rand = () => { h = (h * 1664525 + 1013904223) | 0; return (h >>> 0) / 0xffffffff; };
    // Fill data cells
    for (let r = 0; r < N; r++) for (let c = 0; c < N; c++) {
      const inFinder = (r < 8 && c < 8) || (r < 8 && c >= N - 8) || (r >= N - 8 && c < 8);
      if (inFinder) continue;
      grid[r][c] = rand() > 0.55 ? 1 : 0;
    }
    return grid;
  }, [value]);
  const cs = size / cells.length;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${cells.length} ${cells.length}`} style={{ display: "block", background: bg, borderRadius: 6 }}>
      {cells.map((row, r) => row.map((v, c) => v ? (
        <rect key={`${r}-${c}`} x={c} y={r} width="1" height="1" fill={fg} />
      ) : null))}
    </svg>
  );
}

// ─────────── Status badge ───────────
function StatusBadge({ status }) {
  const s = STATUS_LABELS[status] || STATUS_LABELS.intake;
  return (
    <span className={`badge ${s.className}`}>
      <span className="dot" />{s.label}
    </span>
  );
}

// ─────────── Case Key ───────────
function CaseKey({ value, size = "md", showCopy = true, onCopy }) {
  const [copied, setCopied] = useState(false);
  const handle = () => {
    setCopied(true);
    if (onCopy) onCopy(value);
    setTimeout(() => setCopied(false), 1500);
  };
  if (size === "lg") {
    return (
      <div onClick={handle} style={{ display: "inline-flex", flexDirection: "column", alignItems: "flex-start", gap: 6, cursor: "pointer" }}>
        <div className="tiny">案件キー</div>
        <div className="casekey-big mono">{value}</div>
        {showCopy && (
          <div className="copy-pill">
            {copied ? <><Ico.checkSmall /> コピーしました</> : <><Ico.copy /> タップでコピー</>}
          </div>
        )}
      </div>
    );
  }
  return (
    <span className="casekey mono" style={{ fontSize: 13, color: "var(--text-3)" }}>{value}</span>
  );
}

// ─────────── Mic + Waveform ───────────
function Waveform({ active, level = 0.6 }) {
  const bars = 11;
  const [heights, setHeights] = useState(Array(bars).fill(6));
  useEffect(() => {
    if (!active) {
      setHeights(Array(bars).fill(6));
      return;
    }
    const t = setInterval(() => {
      setHeights(Array.from({ length: bars }, (_, i) => {
        const center = Math.abs(i - bars / 2) / (bars / 2);
        const base = (1 - center) * 22 + 6;
        return base + Math.random() * 8 * level;
      }));
    }, 110);
    return () => clearInterval(t);
  }, [active, level]);
  return (
    <div className={`waveform ${active ? "active" : ""}`}>
      {heights.map((h, i) => (
        <div key={i} className="bar" style={{ height: h }} />
      ))}
    </div>
  );
}

function MicButton({ recording, onClick }) {
  return (
    <button className={`mic ${recording ? "recording" : ""}`} onClick={onClick} aria-label={recording ? "録音停止" : "録音開始"}>
      {recording ? <Ico.stop /> : <Ico.mic />}
    </button>
  );
}

// ─────────── Field ───────────
function Field({ label, value, required, low, empty, animateKey, children, onClick, right, placeholder, multiline, confidence }) {
  const cls = ["field"];
  if (low) cls.push("low");
  if (empty || (!value && !children)) cls.push("empty");
  if (animateKey) cls.push("ai-just-filled");
  return (
    <div className={cls.join(" ")} onClick={onClick} key={animateKey || undefined}>
      <div className="field-label">
        {label}
        {required && <span className="req">*</span>}
        {right}
      </div>
      {children ? children : (
        <div className={`field-value ${!value ? "placeholder" : ""}`} style={multiline ? { whiteSpace: "pre-wrap" } : undefined}>
          {value || placeholder || "—"}
        </div>
      )}
      {(animateKey || low || confidence != null) && (
        <div className="ai-pill">
          {confidence != null ? (
            <>
              <Ico.sparkle />
              <span style={{ marginLeft: 2 }}>{low ? "要確認" : "自動入力"}</span>
              <span className="mono" style={{ marginLeft: 4, opacity: 0.8 }}>{Math.round(confidence * 100)}%</span>
            </>
          ) : (
            <><Ico.sparkle /> {low ? "要確認" : "AI"}</>
          )}
        </div>
      )}
    </div>
  );
}

// ─────────── Chip multi-select ───────────
function ChipMulti({ options, value, onChange }) {
  const toggle = (v) => {
    if (value.includes(v)) onChange(value.filter(x => x !== v));
    else onChange([...value, v]);
  };
  return (
    <div className="chip-row">
      {options.map(opt => (
        <button key={opt} className={`chip ${value.includes(opt) ? "on" : ""}`} onClick={() => toggle(opt)}>
          {value.includes(opt) && <Ico.checkSmall />}
          {opt}
        </button>
      ))}
    </div>
  );
}

// ─────────── Pill radio (segmented) ───────────
function PillRadio({ options, value, onChange }) {
  return (
    <div className="pill-row">
      {options.map(opt => (
        <button key={opt} className={value === opt ? "on" : ""} onClick={() => onChange(opt)}>{opt}</button>
      ))}
    </div>
  );
}

// ─────────── Bottom Sheet ───────────
function Sheet({ open, onClose, title, children }) {
  return (
    <>
      <div className={`scrim ${open ? "show" : ""}`} onClick={onClose} />
      <div className={`sheet ${open ? "show" : ""}`}>
        <div className="sheet-handle" />
        <div className="sheet-head">
          <div className="sheet-title">{title}</div>
          <button className="appbar icon-btn" onClick={onClose} style={{ width: 32, height: 32, padding: 0 }}>
            <Ico.x />
          </button>
        </div>
        <div className="sheet-body">{children}</div>
      </div>
    </>
  );
}

// ─────────── Status stepper ───────────
function StatusStepper({ current }) {
  const steps = ["受付", "整備", "集配", "納車"];
  const idx = steps.indexOf({ intake: "受付", progress: "整備", delivery: "集配", done: "納車" }[current] || "受付");
  return (
    <div className="stepper">
      {steps.map((s, i) => (
        <React.Fragment key={s}>
          <div className={`node ${i === idx ? "cur" : i < idx ? "done" : ""}`}>
            <div className="dot">{i < idx ? <Ico.checkSmall /> : i + 1}</div>
            <div>{s}</div>
          </div>
          {i < steps.length - 1 && <div className={`conn ${i < idx ? "done" : ""}`} />}
        </React.Fragment>
      ))}
    </div>
  );
}

// ─────────── Toast ───────────
function Toast({ show, children }) {
  return <div className={`toast ${show ? "show" : ""}`}>{children}</div>;
}

// ─────────── Tab bar ───────────
function TabBar({ active, onNav }) {
  return (
    <div className="tabbar">
      <button className={`tab ${active === "home" ? "on" : ""}`} onClick={() => onNav("home")}>
        <Ico.home className="ico" /> ホーム
      </button>
      <button className={`tab ${active === "list" ? "on" : ""}`} onClick={() => onNav("list")}>
        <Ico.list className="ico" /> 案件
      </button>
      <button className="tab" onClick={() => onNav("intake")} style={{ paddingTop: 0 }}>
        <div className="tab-fab"><Ico.plus /></div>
        <span style={{ marginTop: 4 }}>新規受付</span>
      </button>
      <button className={`tab ${active === "notif" ? "on" : ""}`} onClick={() => onNav("notif")}>
        <Ico.bell className="ico" /> 通知
      </button>
      <button className={`tab ${active === "me" ? "on" : ""}`} onClick={() => onNav("me")}>
        <Ico.user className="ico" /> 自分
      </button>
    </div>
  );
}

// ─────────── App Bar (per-screen) ───────────
function AppBar({ title, sub, brand, left, right, big, variant = "navy" }) {
  return (
    <div className={`appbar ${brand ? "brand" : ""}`}>
      <div className="appbar-row">
        {left}
        <div style={{ flex: 1 }}>
          {brand && variant === "navy" && (
            <div className="brand-wrap">
              <BrandMark />
              <div>
                <div className="brand-name">橋本商会ポータル</div>
                <div className="brand-sub">{sub || "Always the best service."}</div>
              </div>
            </div>
          )}
          {brand && variant === "brand" && (
            <div className="brand-wrap" style={{ alignItems: "center" }}>
              <HashimotoLogo size={14} />
              <div className="brand-sub" style={{ marginLeft: "auto" }}>{sub}</div>
            </div>
          )}
          {!brand && !big && (
            <div>
              <div className="brand-name">{title}</div>
              {sub && <div className="brand-sub">{sub}</div>}
            </div>
          )}
        </div>
        {right}
      </div>
      {big && (
        <>
          <h1>{title}</h1>
          {sub && <div className="sub">{sub}</div>}
        </>
      )}
    </div>
  );
}

Object.assign(window, {
  Ico, BrandMark, HashimotoLogo, HashimotoMark, BrandHero, ConfidenceBar, FakeQR,
  StatusBadge, CaseKey, MicButton, Waveform,
  Field, ChipMulti, PillRadio, Sheet, StatusStepper, Toast, TabBar, AppBar,
});
