/* Desk team, your profile, and auth.
   Team is instant (nothing on it commits); the profile is Staged with one Save;
   auth is its own shell with no navigation owner (AGENTS §7.1) and every form
   on it is Staged. */
(() => {
  const {
    Card, CardHeader, CardTitle, CardDescription, CardPanel, CardFooter,
    Table, TableHeader, TableBody, TableRow, TableHead, TableCell,
    Button, Badge, Avatar, Alert, AlertTitle, AlertDescription, Separator, Switch, Select,
    Field, FieldLabel, FieldDescription, FieldError, Input, InputGroup, InputGroupInput, InputGroupAddon,
    Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent,
  } = window.OriginDesignSystem_7c998b;

  const BRAND_MARK = "../../assets/templates/logos/12-logo-demo.svg";

  /* ── /team ─────────────────────────────────────────────────────────────── */
  function TeamScreen({ data, now, session, onNavigate }) {
    const desk = deskLoad(data.staff, data.applications, data.interviews, now);
    const panel = panelLoad(data.staff, data.applications, data.interviews, now);
    const unowned = liveApplications(data.applications).filter((a) => !a.ownerId);

    return (
      <div className="rd-page">
        <PageHead path="/team" title="Desk team"
          note={"Who owns what, and what the panel owes us. Load counts live applications only — " + plural(liveApplications(data.applications).length, "application", "applications") + " in total."} />

        {unowned.length ? (
          <Alert variant="warning">
            <Icon name="user-round-x" size={16} />
            <AlertTitle>{plural(unowned.length, "application", "applications")} with no owner</AlertTitle>
            <AlertDescription>Unowned applications appear in nobody's queue. {unowned.map((a) => a.candidate.name).join(", ")}.</AlertDescription>
          </Alert>
        ) : null}

        <Card>
          <CardHeader>
            <CardTitle>Recruiters and coordination</CardTitle>
            <CardDescription>Live applications owned, and how many of them the desk owes a move on.</CardDescription>
          </CardHeader>
          <CardPanel>
            <div className="rd-card-table">
              <Table variant="card">
                <TableHeader>
                  <TableRow>
                    <TableHead>Person</TableHead>
                    <TableHead className="rd-num">Owns</TableHead>
                    <TableHead className="rd-num">Waiting on them</TableHead>
                    <TableHead className="rd-num">Over service level</TableHead>
                    <TableHead className="rd-drop-md">Load</TableHead>
                    <TableHead className="rd-num rd-drop-lg">Interviews booked</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {desk.map((row) => (
                    <TableRow key={row.person.id}>
                      <TableCell><StaffCell person={row.person} /></TableCell>
                      <TableCell className="rd-num">{row.owned.length}</TableCell>
                      <TableCell className="rd-num">{row.awaitingUs}</TableCell>
                      <TableCell className="rd-num">{row.stalled || "—"}</TableCell>
                      <TableCell className="rd-drop-md" style={{ minWidth: "8rem" }}>
                        <Bar ratio={row.owned.length / Math.max(1, liveApplications(data.applications).length)} tone={row.stalled ? "warn" : "soft"} />
                      </TableCell>
                      <TableCell className="rd-num rd-drop-lg">{row.interviews}</TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
          </CardPanel>
          <CardFooter className="rd-card-foot">
            <span className="rd-foot">Load is each person's owned applications as a share of the {liveApplications(data.applications).length} live ones.</span>
          </CardFooter>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle>Hiring managers and the panel</CardTitle>
            <CardDescription>A different question over a different array: what clinicians and managers owe the desk.</CardDescription>
          </CardHeader>
          <CardPanel>
            <div className="rd-card-table">
              <Table variant="card">
                <TableHeader>
                  <TableRow>
                    <TableHead>Person</TableHead>
                    <TableHead className="rd-drop-md">Department</TableHead>
                    <TableHead className="rd-num">Booked ahead</TableHead>
                    <TableHead className="rd-num">Scorecards owed</TableHead>
                    <TableHead className="rd-num rd-drop-lg">Watching</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {panel.map((row) => (
                    <TableRow key={row.person.id} className={row.outstanding ? undefined : "rd-row--recessed"}>
                      <TableCell><StaffCell person={row.person} /></TableCell>
                      <TableCell className="rd-drop-md">{labelOf(DEPARTMENTS, row.person.department)}</TableCell>
                      <TableCell className="rd-num">{row.booked || "—"}</TableCell>
                      <TableCell className="rd-num">
                        {row.outstanding ? <Badge size="sm" variant="warning">{row.outstanding}</Badge> : "—"}
                      </TableCell>
                      <TableCell className="rd-num rd-drop-lg">{row.watching || "—"}</TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
          </CardPanel>
          <CardFooter className="rd-card-foot">
            <span className="rd-foot">Rows with nothing owed are recessed, not hidden — a quiet panel member is still on the panel.</span>
            <Button variant="outline" size="sm" onClick={() => onNavigate("/interviews")}>Open interviews</Button>
          </CardFooter>
        </Card>
      </div>
    );
  }

  /* ── /me/profile — Staged: nothing applies until Save. ─────────────────── */
  function ProfileScreen({ data, now, session, onNavigate, preferences, onSavePreferences, onSavePhoto }) {
    const me = staffById(data.staff, session.personId);
    const [draft, setDraft] = React.useState(preferences);
    const [photo, setPhoto] = React.useState(me.photo);
    const [photoError, setPhotoError] = React.useState(null);
    const [over, setOver] = React.useState(false);
    const photoInput = React.useRef(null);
    React.useEffect(() => setDraft(preferences), [preferences]);
    React.useEffect(() => { setPhoto(me.photo); setPhotoError(null); }, [me.photo]);
    const dirty = JSON.stringify(draft) !== JSON.stringify(preferences) || photo !== me.photo;
    const set = (key, value) => setDraft((d) => Object.assign({}, d, { [key]: value }));
    const owned = liveApplications(ownedBy(data.applications, me.id));

    /* Same control as the create form: dashed drop zone, real preview, the file
       input driven by buttons. Staged like everything else on this screen — the
       face does not change on the rest of the product until Save. */
    const readPhoto = (file) => {
      if (!file) return;
      if (!/^image\/(png|jpeg|webp)$/.test(file.type)) { setPhotoError("JPG, PNG or WebP only — that file is " + (file.type || "an unknown type") + "."); return; }
      if (file.size > 2 * 1024 * 1024) { setPhotoError("That is " + (file.size / 1048576).toFixed(1) + " MB. Up to 2 MB."); return; }
      setPhotoError(null);
      const reader = new FileReader();
      reader.onload = () => setPhoto(reader.result);
      reader.readAsDataURL(file);
    };

    return (
      <div className="rd-page">
        <PageHead path="/me/profile" title={me.name} avatar={me}
          note={me.title + " · " + labelOf(SITES, me.site) + " · owns " + plural(owned.length, "live application", "live applications")} />

        {/* Two column stacks, never three loose cards (AGENTS §5.1): you and
            what you hear about on the left, the queue's own defaults beside it. */}
        <div className="rd-columns">
          <div className="rd-col">
          <Card>
            <CardHeader>
              <CardTitle>You</CardTitle>
              <CardDescription>Your photograph is what the desk sees on every note you write and every panel you sit on.</CardDescription>
            </CardHeader>
            <CardPanel>
              <div className="rd-stack">
                <div className={"rd-upload" + (over ? " rd-upload--over" : "")}
                  onDragOver={(e) => { e.preventDefault(); setOver(true); }}
                  onDragLeave={() => setOver(false)}
                  onDrop={(e) => { e.preventDefault(); setOver(false); readPhoto(e.dataTransfer.files && e.dataTransfer.files[0]); }}>
                  <span className="rd-upload__face">
                    {photo ? <img src={photo} alt={"Photograph of " + me.name} /> : <Icon name="user-round" size={26} />}
                  </span>
                  <div className="rd-upload__body">
                    <span className="rd-upload__note">
                      {photo === me.photo
                        ? (photo ? "The photograph on your account." : "No photograph — your initials stand in wherever a face appears.")
                        : (photo ? "New photograph staged. It is not on your account until you save." : "Your photograph will be removed when you save.")}
                    </span>
                    <span className="rd-upload__actions">
                      <Button variant="outline" size="sm" onClick={() => photoInput.current.click()}>
                        <Icon name="upload" size={14} />{photo ? "Replace" : "Upload a photo"}
                      </Button>
                      {photo ? <Button variant="ghost" size="sm" onClick={() => { setPhoto(null); setPhotoError(null); }}>Remove</Button> : null}
                      {photo !== me.photo ? <Button variant="ghost" size="sm" onClick={() => { setPhoto(me.photo); setPhotoError(null); }}>Undo</Button> : null}
                    </span>
                    {photoError
                      ? <FieldError>{photoError}</FieldError>
                      : <span className="rd-foot">Drop an image here, or pick one. JPG, PNG or WebP; square reads best; up to 2 MB.</span>}
                  </div>
                  <input ref={photoInput} className="rd-sr" type="file" accept="image/png,image/jpeg,image/webp" aria-label="Choose your photograph"
                    onChange={(e) => { readPhoto(e.target.files && e.target.files[0]); e.target.value = ""; }} />
                </div>
                <Separator />
                <KeyValues items={[
                  { label: "Role", value: labelOf(DESK_ROLES, me.role) },
                  { label: "Site", value: labelOf(SITES, me.site) },
                  { label: "Email", value: me.email, note: "Held in the staff directory, not here" },
                  { label: "Live applications", value: owned.length, note: "Counted from the queue" },
                ]} />
              </div>
            </CardPanel>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>What you hear about</CardTitle>
              <CardDescription>Notifications from the bell and by email. Staged: nothing changes until you save.</CardDescription>
            </CardHeader>
            <CardPanel>
              <div className="rd-checks">
                {[
                  { key: "notifyMentions", label: "When somebody mentions you on a thread", note: "You are mentioned on " + plural(data.notes.filter((n) => mentionIds(n.body).indexOf(me.id) > -1).length, "note", "notes") + " at the moment." },
                  { key: "notifyScorecards", label: "When a scorecard lands on an application you own" },
                  { key: "notifyOffers", label: "When an offer is accepted or runs out" },
                  { key: "notifyStalled", label: "When something you own goes over its service level", note: "Counted per stage, from the same rule the queue uses." },
                ].map((row) => (
                  <label className="rd-check" key={row.key}>
                    <Switch checked={!!draft[row.key]} onCheckedChange={(v) => set(row.key, v)} aria-label={row.label} />
                    <span className="rd-check__text"><span>{row.label}</span>{row.note ? <span className="rd-foot">{row.note}</span> : null}</span>
                  </label>
                ))}
              </div>
            </CardPanel>
          </Card>
          </div>

          <div className="rd-col">
          <Card>
            <CardHeader>
              <CardTitle>How the queue opens</CardTitle>
              <CardDescription>Your own defaults on Applications.</CardDescription>
            </CardHeader>
            <CardPanel>
              <div className="rd-fields">
                <Field>
                  <FieldLabel htmlFor="pf-view">Default view</FieldLabel>
                  <Select id="pf-view" value={draft.defaultView} onValueChange={(v) => set("defaultView", v)}
                    items={[
                      { value: "ours", label: "Waiting on us" },
                      { value: "theirs", label: "Waiting on others" },
                      { value: "all", label: "Everything" },
                    ]} />
                  <FieldDescription>Waiting on us is the desk's default, and the one the sidebar badge counts.</FieldDescription>
                </Field>
                <Field>
                  <FieldLabel htmlFor="pf-mine">Only your own applications</FieldLabel>
                  <label className="rd-check">
                    <Switch checked={!!draft.onlyMine} onCheckedChange={(v) => set("onlyMine", v)} aria-label="Filter the queue to applications you own" />
                    <span className="rd-check__text">
                      <span>Open the queue filtered to you</span>
                      <span className="rd-foot">You own {owned.length} of the {liveApplications(data.applications).length} live applications.</span>
                    </span>
                  </label>
                </Field>
              </div>
            </CardPanel>
          </Card>
          </div>
        </div>

        <FormBar dirty={dirty} label="Save your profile" onCancel={() => { setDraft(preferences); setPhoto(me.photo); setPhotoError(null); }}
          note={dirty
            ? (photo !== me.photo ? "Your photograph and " : "") + "four notification switches and two queue defaults, applied to your account only."
            : "Nothing has changed."}
          onSave={() => { if (photo !== me.photo) onSavePhoto(photo); onSavePreferences(draft); }} />
      </div>
    );
  }

  /* ── Auth ──────────────────────────────────────────────────────────────────
     One layout variant for the product: centred card, 23rem column, the mark
     above the form as the only navigation. One primary credential strategy:
     password, with a reveal toggle. Two auth screens are designed here — sign
     in and signed out — and because the product does not include a reset flow,
     it does not link to one: the support line is the way out. */
  function AuthFrame({ children }) {
    return (
      <div className="rd-auth">
        <div className="rd-auth__col">
          <div className="rd-auth__mark">
            <img src={BRAND_MARK} alt="" width="32" height="32" />
            <span className="rd-auth__words">
              <span className="rd-brand__name">{RD_ORG.desk}</span>
              <span className="rd-brand__sub">{RD_ORG.name}</span>
            </span>
          </div>
          {children}
        </div>
      </div>
    );
  }

  function SignInScreen({ onAuthenticated, attempts, onFailedAttempt }) {
    const [email, setEmail] = React.useState("");
    const [password, setPassword] = React.useState("");
    const [reveal, setReveal] = React.useState(false);
    const [state, setState] = React.useState("idle");
    const [errors, setErrors] = React.useState({});
    const dirty = !!email || !!password;
    const locked = attempts >= 3;

    const submit = () => {
      const next = {};
      if (!email.trim() || email.indexOf("@") === -1) next.email = "Use your Larkspur address.";
      if (!password) next.password = "Enter your password.";
      setErrors(next);
      if (Object.keys(next).length) { setState("invalid"); return; }
      /* One state at a time: a server answer replaces field errors, never both. */
      if (password.length < 8) { setErrors({}); setState("rejected"); setPassword(""); onFailedAttempt(); return; }
      setState("submitting");
      window.setTimeout(onAuthenticated, 400);
    };

    return (
      <AuthFrame>
        <Card>
          <CardHeader>
            <CardTitle>Sign in</CardTitle>
            <CardDescription>The recruitment desk for {RD_ORG.name}. Your Larkspur account, the same one as the staff intranet.</CardDescription>
          </CardHeader>
          <CardPanel>
            <div className="rd-fields">
              {locked ? (
                <Alert variant="destructive">
                  <Icon name="lock" size={16} />
                  <AlertTitle>Too many attempts</AlertTitle>
                  <AlertDescription>This account is locked for 15 minutes. The IT service desk on 2200 can unlock it sooner.</AlertDescription>
                </Alert>
              ) : state === "rejected" ? (
                <Alert variant="destructive">
                  <Icon name="triangle-alert" size={16} />
                  <AlertTitle>Email or password is incorrect</AlertTitle>
                  <AlertDescription>{plural(3 - attempts, "attempt", "attempts")} left before the account locks for 15 minutes.</AlertDescription>
                </Alert>
              ) : null}
              <Field>
                <FieldLabel htmlFor="au-email">Email</FieldLabel>
                <Input id="au-email" type="email" autoComplete="email" value={email} invalid={!!errors.email} disabled={locked}
                  placeholder={"nadia.ferreira@" + RD_ORG.domain} onChange={(e) => setEmail(e.target.value)} />
                {errors.email ? <FieldError>{errors.email}</FieldError> : null}
              </Field>
              <Field>
                <FieldLabel htmlFor="au-password">Password</FieldLabel>
                <InputGroup>
                  <InputGroupInput id="au-password" type={reveal ? "text" : "password"} autoComplete="current-password" value={password}
                    invalid={!!errors.password} disabled={locked} onChange={(e) => setPassword(e.target.value)} />
                  <InputGroupAddon align="inline-end">
                    <Button variant="ghost" size="icon-xs" aria-label={reveal ? "Hide the password" : "Show the password"} onClick={() => setReveal(!reveal)}>
                      <Icon name={reveal ? "eye-off" : "eye"} size={14} />
                    </Button>
                  </InputGroupAddon>
                </InputGroup>
                {errors.password ? <FieldError>{errors.password}</FieldError> : null}
              </Field>
              <Button disabled={!dirty || locked || state === "submitting"} onClick={submit}>
                {state === "submitting" ? "Signing in…" : "Sign in"}
              </Button>
            </div>
          </CardPanel>
        </Card>
        <p className="rd-auth__foot">
          Trouble getting in? The IT service desk on 2200 handles Larkspur accounts — password resets are not done in this app.
        </p>
      </AuthFrame>
    );
  }

  function SignedOutScreen({ person, onNavigate }) {
    return (
      <AuthFrame>
        <Card>
          <CardPanel>
            <Empty>
              <EmptyHeader>
                <EmptyMedia variant="icon"><Icon name="door-open" size={18} /></EmptyMedia>
                <EmptyTitle>You are signed out</EmptyTitle>
                <EmptyDescription>
                  {person ? person.name.split(" ")[0] + ", your" : "Your"} session on this browser is closed. Anything you had open was saved as you went — this product has no draft to lose.
                </EmptyDescription>
              </EmptyHeader>
              <EmptyContent><Button onClick={() => onNavigate("/signin")}>Sign in</Button></EmptyContent>
            </Empty>
          </CardPanel>
        </Card>
        <p className="rd-auth__foot">Candidate data stays on Larkspur systems. Close the browser on a shared machine.</p>
      </AuthFrame>
    );
  }

  Object.assign(window, { TeamScreen, ProfileScreen, SignInScreen, SignedOutScreen });
})();
