/* Settings — four views behind one account-menu entry, reached by a tab strip
   inside the settings surface rather than by a second row of navigation.

   Commit model: STAGED on every view that has a control. Nothing applies until
   Save, Save and Cancel are disabled until the form is dirty, Cancel appears
   only once it is, and errors render on validation. The photo obeys the same
   rule: picking one previews it in the draft avatar and only reaches the
   account menu on Save. Authority holds no controls at all — it is set by the
   carrier, not by the person it limits — so it carries no form bar.

   Nothing is offered here that no screen reads: each desk preference names the
   screen it changes, and the alerts list is the same ALERT_KINDS vocabulary
   every notification carries. */
(() => {
  const {
    Card, CardHeader, CardTitle, CardDescription, CardPanel, CardFooter,
    Field, FieldLabel, FieldDescription, FieldError, Input, Checkbox, Select, Button, Avatar,
  } = window.OriginDesignSystem_7c998b;

  const EMAIL = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
  /* Two letters at most, from the name the person actually typed — the fallback
     has to track the draft, not the saved user, or it lies while editing. */
  const initialsOf = (name) => name.trim().split(/\s+/).slice(0, 2).map((w) => w[0] || "").join("").toUpperCase() || "?";
  const PHOTO_MAX_MB = 5;

  function FormBar({ dirty, note, onCancel, onSave, label }) {
    return (
      <div className="cd-formbar">
        <span className="cd-formbar__note">{note}</span>
        {dirty ? <Button variant="outline" onClick={onCancel}>Cancel</Button> : null}
        <Button disabled={!dirty} onClick={onSave}>{label}</Button>
      </div>
    );
  }

  /* ── Profile ──────────────────────────────────────────────────────────── */

  function ProfileView({ user, onSave }) {
    const initial = React.useMemo(() => ({ name: user.name, role: user.role, email: user.email, avatar: user.avatar || null }), [user]);
    const [draft, setDraft] = React.useState(initial);
    const [submitted, setSubmitted] = React.useState(false);
    /* The picked file is previewed from an object URL held only while the draft
       is unsaved; anything this screen created gets revoked when it goes. */
    const madeHere = React.useRef([]);
    const fileRef = React.useRef(null);
    const [photoError, setPhotoError] = React.useState(null);
    React.useEffect(() => { setDraft(initial); setSubmitted(false); setPhotoError(null); }, [initial]);
    React.useEffect(() => () => { madeHere.current.forEach((url) => URL.revokeObjectURL(url)); }, []);
    const dirty = JSON.stringify(draft) !== JSON.stringify(initial);
    const errors = {};
    if (!draft.name.trim()) errors.name = "Enter the name that goes on a decision.";
    if (!EMAIL.test(draft.email)) errors.email = "Enter a valid email address.";
    const valid = Object.keys(errors).length === 0;

    const pickPhoto = (event) => {
      const file = event.target.files && event.target.files[0];
      event.target.value = "";
      if (!file) return;
      if (!/^image\/(png|jpeg|webp)$/.test(file.type)) { setPhotoError("Use a PNG, JPG or WebP image."); return; }
      if (file.size > PHOTO_MAX_MB * 1024 * 1024) { setPhotoError("That file is over " + PHOTO_MAX_MB + " MB. Use a smaller image."); return; }
      const url = URL.createObjectURL(file);
      madeHere.current.push(url);
      setPhotoError(null);
      setDraft(Object.assign({}, draft, { avatar: url }));
    };

    return (
      <>
        <Card>
          <CardHeader>
            <CardTitle>How you appear on a file</CardTitle>
            <CardDescription>Claimants and counterparties see the name and the title; the email is where their replies land.</CardDescription>
          </CardHeader>
          <CardPanel>
            <div className="cd-fields">
              <Field>
                <FieldLabel htmlFor="cd-p-photo">Photo</FieldLabel>
                <div className="cd-photo">
                  <Avatar size={72} src={draft.avatar || undefined} alt="" fallback={initialsOf(draft.name)} />
                  <div className="cd-photo__text">
                    <div className="cd-photo__actions">
                      <Button variant="outline" size="sm" onClick={() => fileRef.current && fileRef.current.click()}>{draft.avatar ? "Replace photo" : "Upload photo"}</Button>
                      {draft.avatar ? <Button variant="ghost" size="sm" onClick={() => { setPhotoError(null); setDraft(Object.assign({}, draft, { avatar: null })); }}>Remove</Button> : null}
                    </div>
                    <input ref={fileRef} id="cd-p-photo" className="o-sr" type="file" accept="image/png,image/jpeg,image/webp" onChange={pickPhoto} />
                    {photoError ? <FieldError>{photoError}</FieldError> : <FieldDescription>Square PNG, JPG or WebP under {PHOTO_MAX_MB} MB. Without one, your initials stand in.</FieldDescription>}
                  </div>
                </div>
              </Field>
              <Field>
                <FieldLabel htmlFor="cd-p-name">Name</FieldLabel>
                <Input id="cd-p-name" autoComplete="name" value={draft.name} invalid={submitted && !!errors.name} onChange={(e) => setDraft(Object.assign({}, draft, { name: e.target.value }))} />
                {submitted && errors.name ? <FieldError>{errors.name}</FieldError> : null}
              </Field>
              <Field>
                <FieldLabel htmlFor="cd-p-role">Title</FieldLabel>
                <Input id="cd-p-role" value={draft.role} onChange={(e) => setDraft(Object.assign({}, draft, { role: e.target.value }))} />
                <FieldDescription>Shown under your name in the account menu and on outgoing correspondence.</FieldDescription>
              </Field>
              <Field>
                <FieldLabel htmlFor="cd-p-email">Email</FieldLabel>
                <Input id="cd-p-email" type="email" autoComplete="email" value={draft.email} invalid={submitted && !!errors.email} onChange={(e) => setDraft(Object.assign({}, draft, { email: e.target.value }))} />
                {submitted && errors.email ? <FieldError>{errors.email}</FieldError> : <FieldDescription>Where exports, alerts and replies are sent.</FieldDescription>}
              </Field>
            </div>
          </CardPanel>
        </Card>
        <FormBar
          dirty={dirty}
          note={dirty ? "Unsaved changes to your profile." : "Everything here is as it was last saved."}
          onCancel={() => { setDraft(initial); setSubmitted(false); setPhotoError(null); }}
          onSave={() => { setSubmitted(true); if (valid) onSave(draft); }}
          label="Save profile"
        />
      </>
    );
  }

  /* ── Authority ────────────────────────────────────────────────────────── */

  function AuthorityView({ data, now, onNavigate }) {
    /* Authority is not editable by the person it limits. What this view can
       honestly show is what it costs today: the claims whose payable figure is
       above it, counted with the predicate the decision screen uses, and the
       ones already sitting with the manager because of it. */
    const limit = CLAIM_POLICY.authorityLimitCents;
    const above = data.claims.filter((claim) => {
      const payable = payableOf(claim);
      return payable !== null && CLAIM_FLAGS.needsSignoff(payable);
    });
    const waiting = awaitingSignoff(data.claims);

    return (
      <>
        <Card>
          <CardHeader>
            <CardTitle>Your authority</CardTitle>
            <CardDescription>Set by the carrier, not by you — it is shown here so nothing about a sign-off is a surprise.</CardDescription>
          </CardHeader>
          <CardPanel>
            <dl className="cd-defs">
              <dt>Decide alone up to</dt><dd className="cd-amount">{formatMoney(limit)}</dd>
              <dt>Signs off above it</dt><dd>{CLAIMS_MANAGER.name} · {CLAIMS_MANAGER.role}</dd>
              <dt>Claims on the desk above it</dt><dd>{above.length} of {data.claims.length}</dd>
              <dt>Waiting on a signature now</dt><dd>{waiting.length ? formatPlural(waiting.length, "decision") + " · " + formatMoney(signoffValue(waiting)) : "None"}</dd>
            </dl>
          </CardPanel>
          <CardFooter className="cd-card-footer">
            <span className="cd-footnote">{above.length ? above.map((c) => c.id).join(", ") + " would need a signature today." : "Nothing on the desk needs a signature today."}</span>
            <Button variant="outline" size="sm" onClick={() => onNavigate(waiting.length ? "/signoff" : "/")}>{waiting.length ? "Open sign-off" : "Open the queue"}</Button>
          </CardFooter>
        </Card>
      </>
    );
  }

  /* ── Alerts ───────────────────────────────────────────────────────────── */

  function AlertsView({ user, data, now, onNavigate, onSave }) {
    const initial = React.useMemo(() => ({ alerts: (user.alerts || []).slice() }), [user]);
    const [draft, setDraft] = React.useState(initial);
    React.useEffect(() => { setDraft(initial); }, [initial]);
    const dirty = JSON.stringify(draft) !== JSON.stringify(initial);
    const toggle = (value) => setDraft({ alerts: draft.alerts.indexOf(value) > -1 ? draft.alerts.filter((v) => v !== value) : draft.alerts.concat([value]) });
    /* What each kind has actually raised, so a choice is made against the
       traffic rather than against the label. */
    const raised = (kind) => notificationsOfKind(data.notifications, kind).length;
    const covered = data.notifications.filter((n) => draft.alerts.indexOf(n.kind) > -1);

    return (
      <>
        <Card>
          <CardHeader>
            <CardTitle>What we email you</CardTitle>
            <CardDescription>Every kind is raised on the desk either way; these choose which also reach {user.email}.</CardDescription>
          </CardHeader>
          <CardPanel>
            <div className="cd-checks">
              {ALERT_KINDS.map((kind) => (
                <label className="cd-check" key={kind.value}>
                  <Checkbox checked={draft.alerts.indexOf(kind.value) > -1} onCheckedChange={() => toggle(kind.value)} />
                  <span className="cd-check__text">
                    <span>{kind.label}</span>
                    <span className="cd-record__meta">{kind.hint}</span>
                  </span>
                  <span className="cd-check__count">{raised(kind.value) ? formatPlural(raised(kind.value), "notification") : "None raised"}</span>
                </label>
              ))}
            </div>
          </CardPanel>
          <CardFooter className="cd-card-footer">
            <span className="cd-footnote">
              {draft.alerts.length} of {ALERT_KINDS.length} kinds selected — {formatCount(covered.length)} of the {formatCount(data.notifications.length)} notifications on the desk would have been emailed.
            </span>
            <button type="button" className="cd-record__link" onClick={() => onNavigate("/notifications")}>Open notifications</button>
          </CardFooter>
        </Card>
        <FormBar
          dirty={dirty}
          note={dirty ? "Unsaved changes to your alerts." : "Everything here is as it was last saved."}
          onCancel={() => setDraft(initial)}
          onSave={() => onSave(draft)}
          label="Save alerts"
        />
      </>
    );
  }

  /* ── Desk ─────────────────────────────────────────────────────────────── */

  function DeskView({ desk, onSave }) {
    const initial = React.useMemo(() => Object.assign({}, DESK_DEFAULTS, desk), [desk]);
    const [draft, setDraft] = React.useState(initial);
    React.useEffect(() => { setDraft(initial); }, [initial]);
    const dirty = JSON.stringify(draft) !== JSON.stringify(initial);
    const set = (fields) => setDraft(Object.assign({}, draft, fields));
    const landingItems = CLAIMS_DESTINATIONS.map((route) => ({ value: route.path, label: route.label }));
    const tabItems = QUEUE_TABS.map((tab) => ({ value: tab.value, label: tab.label }));

    return (
      <>
        <Card>
          <CardHeader>
            <CardTitle>How the desk opens</CardTitle>
            <CardDescription>Three settings, each naming the screen it changes. Nothing here is cosmetic.</CardDescription>
          </CardHeader>
          <CardPanel>
            <div className="cd-fields">
              <Field>
                <FieldLabel htmlFor="cd-d-landing">Where signing in lands you</FieldLabel>
                <Select id="cd-d-landing" items={landingItems} value={draft.landing} onValueChange={(v) => set({ landing: v })} />
                <FieldDescription>The first screen after you sign in.</FieldDescription>
              </Field>
              <Field>
                <FieldLabel htmlFor="cd-d-tab">The work queue's first tab</FieldLabel>
                <Select id="cd-d-tab" items={tabItems} value={draft.queueTab} onValueChange={(v) => set({ queueTab: v })} />
                <FieldDescription>Which set of claims the queue shows before you touch a filter.</FieldDescription>
              </Field>
              <Field>
                <FieldLabel>Opening a claim</FieldLabel>
                <label className="cd-check">
                  <Checkbox checked={!!draft.openDecidable} onCheckedChange={() => set({ openDecidable: !draft.openDecidable })} />
                  <span className="cd-check__text">
                    <span>Open a decidable claim at its decision</span>
                    <span className="cd-record__meta">Claims with every mandatory document on file skip the assessment and open on the decision surface. Everything else opens on the assessment as usual.</span>
                  </span>
                </label>
              </Field>
            </div>
          </CardPanel>
        </Card>
        <FormBar
          dirty={dirty}
          note={dirty ? "Unsaved changes to your desk." : "Everything here is as it was last saved."}
          onCancel={() => setDraft(initial)}
          onSave={() => onSave(draft)}
          label="Save desk"
        />
      </>
    );
  }

  /* ── The settings surface ─────────────────────────────────────────────── */

  const LEDES = {
    profile: "The name, title and face that go on every decision, offer and recovery notice.",
    authority: "What you can settle alone, who signs above it, and what that costs the desk today.",
    alerts: "Which of the things this desk raises also reach your inbox.",
    desk: "How the desk opens, and where a claim opens from the queue.",
  };

  function SettingsScreen({ view, user, desk, data, now, onNavigate, onSaveProfile, onSaveAlerts, onSaveDesk }) {
    const spec = SETTINGS_VIEWS.find((v) => v.value === view) || SETTINGS_VIEWS[0];
    return (
      <div className="cd-page">
        <PageHead path={spec.route.path} title="Settings" lede={LEDES[spec.value]} />
        <SettingsTabs view={spec.value} onNavigate={onNavigate} />
        {spec.value === "profile" ? <ProfileView user={user} onSave={onSaveProfile} /> : null}
        {spec.value === "authority" ? <AuthorityView data={data} now={now} onNavigate={onNavigate} /> : null}
        {spec.value === "alerts" ? <AlertsView user={user} data={data} now={now} onNavigate={onNavigate} onSave={onSaveAlerts} /> : null}
        {spec.value === "desk" ? <DeskView desk={desk} onSave={onSaveDesk} /> : null}
      </div>
    );
  }

  Object.assign(window, { SettingsScreen, FormBar });
})();
