"use client";

import { useEffect, useRef, useState } from "react";
import { Icon, Avatar, GoogleMark, MicrosoftMark, AppleMark } from "./icons";
import { buildOAuthUrl, passwordStrength, type LegalDoc } from "./data";

/* ---- spinner ---- */
export function Spinner({ lg }: { lg?: boolean }) {
  return <span className={lg ? "spinner spinner-lg" : "spinner"} role="status" aria-label="Loading" />;
}

/* ---- badge ---- */
export function Badge({ tone = "gray", children }: { tone?: "blue" | "green" | "gray" | "amber"; children: React.ReactNode }) {
  return <span className={`badge badge-${tone}`}>{children}</span>;
}

/* ---- back button ---- */
export function StepBack({ onClick, label = "Back" }: { onClick: () => void; label?: string }) {
  return (
    <button className="step-back" onClick={onClick} type="button">
      <Icon name="chevL" size={16} /> {label}
    </button>
  );
}

/* ---- account pill ---- */
export function AccountPill({ initials, email, onChange }: { initials: string; email: string; onChange: () => void }) {
  return (
    <div className="account-pill">
      <Avatar initials={initials} size={34} />
      <span className="ap-email">{email}</span>
      <button className="link ap-change" onClick={onChange} type="button">Change</button>
    </div>
  );
}

/* ---- flash note ---- */
export function FlashNote({ tone = "info", children }: { tone?: "info" | "warn" | "error" | "success"; children: React.ReactNode }) {
  const icon = tone === "error" || tone === "warn" ? "alert" : tone === "success" ? "check" : "info";
  return (
    <div className={`flash flash-${tone}`} role="status">
      <Icon name={icon} size={16} />
      <span>{children}</span>
    </div>
  );
}

/* ---- method row ---- */
export function MethodRow({
  icon, title, sub, badge, onClick,
}: { icon: string; title: string; sub?: string; badge?: string; onClick: () => void }) {
  return (
    <button className="method-row" onClick={onClick} type="button">
      <span className="mr-tile"><Icon name={icon} size={19} /></span>
      <span className="mr-text">
        <span className="mr-title">{title} {badge && <span className="mr-badge">{badge}</span>}</span>
        {sub && <span className="mr-sub">{sub}</span>}
      </span>
      <Icon name="chevR" size={18} />
    </button>
  );
}

/* ---- remember device ---- */
export function RememberDevice({ checked, onChange, note }: { checked: boolean; onChange: (v: boolean) => void; note?: string }) {
  return (
    <label className="remember-card">
      <input type="checkbox" checked={checked} onChange={(e) => onChange(e.target.checked)} />
      <span className="col" style={{ gap: 2 }}>
        <span style={{ fontWeight: 600, fontSize: 13.5 }}>Remember this device for 90 days</span>
        {note && <span className="faint" style={{ fontSize: 12 }}>{note}</span>}
      </span>
    </label>
  );
}

/* ---- OTP boxes ---- */
export function OtpBoxes({
  length = 6, onComplete, error, onChange,
}: { length?: number; onComplete?: (code: string) => void; error?: boolean; onChange?: (code: string) => void }) {
  const [vals, setVals] = useState<string[]>(Array(length).fill(""));
  const refs = useRef<Array<HTMLInputElement | null>>([]);

  function emit(next: string[]) {
    setVals(next);
    const code = next.join("");
    onChange?.(code);
    if (code.length === length && !next.includes("")) onComplete?.(code);
  }
  function setAt(i: number, v: string) {
    const d = v.replace(/\D/g, "").slice(-1);
    const next = [...vals]; next[i] = d; emit(next);
    if (d && i < length - 1) refs.current[i + 1]?.focus();
  }
  function onPaste(e: React.ClipboardEvent) {
    const text = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, length);
    if (!text) return;
    e.preventDefault();
    const next = Array(length).fill("");
    text.split("").forEach((c, i) => (next[i] = c));
    emit(next);
    refs.current[Math.min(text.length, length - 1)]?.focus();
  }
  return (
    <div className={`otp-boxes ${error ? "otp-error" : ""}`} onPaste={onPaste}>
      {vals.map((d, i) => (
        <input
          key={i}
          ref={(el) => { refs.current[i] = el; }}
          className="otp-box"
          inputMode="numeric"
          autoComplete="one-time-code"
          maxLength={1}
          value={d}
          autoFocus={i === 0}
          aria-label={`Digit ${i + 1}`}
          onChange={(e) => setAt(i, e.target.value)}
          onKeyDown={(e) => { if (e.key === "Backspace" && !vals[i] && i > 0) refs.current[i - 1]?.focus(); }}
        />
      ))}
    </div>
  );
}

/* ---- resend link with cooldown ---- */
export function ResendLink({ seconds = 30, onResend }: { seconds?: number; onResend?: () => void }) {
  const [left, setLeft] = useState(seconds);
  useEffect(() => {
    if (left <= 0) return;
    const t = setTimeout(() => setLeft((l) => l - 1), 1000);
    return () => clearTimeout(t);
  }, [left]);
  if (left > 0) return <span className="faint" style={{ fontSize: 13 }}>Resend code in {left}s</span>;
  return (
    <button className="link" type="button" onClick={() => { setLeft(seconds); onResend?.(); }}>
      Resend code
    </button>
  );
}

/* ---- social buttons (real OAuth or demo mode) ---- */
/** Returns true if it redirected to a real provider; false if demo mode. */
export function startSocial(provider: "google" | "microsoft" | "apple"): boolean {
  const url = buildOAuthUrl(provider);
  if (url) { window.location.href = url; return true; }
  return false;
}
export function SocialButtons({ onPick, verb = "Continue" }: { onPick: (p: "google") => void; verb?: string }) {
  // Only Google is offered (Microsoft/Apple intentionally hidden).
  return (
    <div className="col gap-3">
      <button className="btn btn-oauth" type="button" onClick={() => onPick("google")}>
        <GoogleMark /> {verb} with Google
      </button>
    </div>
  );
}

/* ---- password strength meter ---- */
export function PasswordStrength({ pw }: { pw: string }) {
  const s = passwordStrength(pw);
  if (!pw) return null;
  return (
    <div className="strength">
      <div className="strength-bars">
        {[0, 1, 2, 3].map((i) => (
          <span key={i} className={i < s.score ? `on s${s.score}` : ""} />
        ))}
      </div>
      <div className="strength-label">Password strength: <b className={`s${s.score}-text`}>{s.label}</b></div>
      <ul className="checklist">
        {s.checks.map((c) => (
          <li key={c.label} className={c.ok ? "ok" : ""}>
            <Icon name={c.ok ? "check" : "x"} size={13} /> {c.label}
          </li>
        ))}
      </ul>
    </div>
  );
}

/* ---- legal modal (scroll-to-end to accept) ---- */
export function LegalModal({ doc, onClose, onReviewed }: { doc: LegalDoc; onClose: () => void; onReviewed: () => void }) {
  const [reviewed, setReviewed] = useState(false);
  const bodyRef = useRef<HTMLDivElement>(null);
  // If the content fits without scrolling, there's nothing to scroll — mark reviewed.
  useEffect(() => {
    const el = bodyRef.current;
    if (el && el.scrollHeight <= el.clientHeight + 12) setReviewed(true);
  }, []);
  function onScroll(e: React.UIEvent<HTMLDivElement>) {
    const el = e.currentTarget;
    if (el.scrollTop + el.clientHeight >= el.scrollHeight - 10 && !reviewed) setReviewed(true);
  }
  return (
    <div className="modal-overlay" role="dialog" aria-modal="true" aria-label={doc.title}>
      <div className="modal anim-pop">
        <div className="modal-head">
          <div className="col" style={{ gap: 2 }}>
            <h3 style={{ fontSize: 17, fontWeight: 700 }}>{doc.title}</h3>
            <span className="faint" style={{ fontSize: 12 }}>{doc.updated}</span>
          </div>
          <button className="icon-btn" onClick={onClose} aria-label="Close"><Icon name="x" size={18} /></button>
        </div>
        <div className="modal-body" ref={bodyRef} onScroll={onScroll}>
          {doc.sections.map((s) => (
            <div key={s.h} style={{ marginBottom: 16 }}>
              <h4 style={{ fontSize: 14, fontWeight: 700, marginBottom: 6 }}>{s.h}</h4>
              <p style={{ fontSize: 13.5, color: "var(--muted)", lineHeight: 1.6 }}>{s.p}</p>
            </div>
          ))}
        </div>
        <div className="modal-foot">
          <span className={`review-note ${reviewed ? "done" : ""}`}>
            <Icon name={reviewed ? "check" : "info"} size={15} />
            {reviewed ? "Reviewed — you can now accept" : "Scroll to the end to mark as reviewed"}
          </span>
          <button className="btn btn-primary" style={{ width: "auto" }} disabled={!reviewed} onClick={() => { onReviewed(); onClose(); }}>
            I&apos;ve read this
          </button>
        </div>
      </div>
    </div>
  );
}

/* ---- cookie banner ---- */
export function CookieBanner() {
  const [show, setShow] = useState(false);
  useEffect(() => {
    try { if (!localStorage.getItem("lup_cookie")) setShow(true); } catch { setShow(true); }
  }, []);
  function choose(v: string) {
    try { localStorage.setItem("lup_cookie", v); } catch { /* ignore */ }
    setShow(false);
  }
  if (!show) return null;
  return (
    <div className="cookie" role="dialog" aria-label="Cookie consent">
      <div className="grow">
        <h4 style={{ fontSize: 14.5, fontWeight: 700 }}>We value your privacy</h4>
        <p style={{ fontSize: 12.5, color: "var(--muted)", margin: "5px 0 0", lineHeight: 1.5 }}>
          We use essential cookies to sign you in securely, and optional cookies for analytics. See our{" "}
          <button className="link" onClick={() => {}}>Cookie &amp; Privacy Policy</button>.
        </p>
      </div>
      <div className="row gap-2 cookie-actions">
        <button className="btn btn-sm" style={{ width: "auto" }} onClick={() => choose("essential")}>Reject non-essential</button>
        <button className="btn btn-primary btn-sm" style={{ width: "auto" }} onClick={() => choose("all")}>Accept all</button>
      </div>
    </div>
  );
}
