/* Auth — the screens outside the product. No shell, no navigation owner.

   Layout: TWO panels side by side, and the primary one is on the RIGHT. The
   form is the work, so it sits on the left where reading starts; the right
   panel is the brand plane — --primary with --primary-foreground text, so it
   inverts correctly in dark mode without a second colour being invented — and
   carries one line per screen saying what this step is for. Below 900px the
   brand panel drops out entirely rather than stacking above the form: on a
   phone the form IS the screen.

   Commit model: STAGED on every one of them. Nothing validates until submit,
   and each screen has exactly one primary action.

   Six screens, one flow: sign in → the 2FA challenge → the product. A password
   that has been forgotten goes /forgot-password → /reset-password, and a person
   who would rather not type a password at all goes /verify-code. Every one of
   them can be reached directly from the page menu, because a person arrives at
   a reset link cold. */
(() => {
  const {
    Card, CardHeader, CardTitle, CardDescription, CardPanel, CardFooter,
    Field, FieldLabel, FieldDescription, FieldError, Input, InputGroup, InputGroupAddon, InputGroupInput,
    Button, Separator, Badge, Alert, AlertTitle, AlertDescription, Checkbox, OTPField,
  } = window.OriginDesignSystem_7c998b;

  const EMAIL = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;

  /* The two-panel shell. `aside` is one sentence about the step, never a second
     navigation surface — there is nowhere else to go from an auth screen. */
  function AuthShell({ children, footer, asideTitle, asideText, asideNote }) {
    return (
      <div className="fd-auth">
        <div className="fd-auth__form">
          <div className="fd-auth__col">
            <div className="fd-auth__mark">
              <img className="fd-auth__logo" src="../../assets/templates/logos/15-logo-demo.svg" alt="" width="32" height="32" />
              <span className="fd-brand__name">Meridian</span>
            </div>
            {children}
            {footer ? <p className="fd-auth__foot">{footer}</p> : null}
          </div>
        </div>
        <aside className="fd-auth__brand">
          <span className="fd-auth__dots" aria-hidden="true" />
          <div className="fd-auth__brandcol">
            <p className="fd-auth__eyebrow">{MERIDIAN_WORKSPACE.name}</p>
            <h1 className="fd-auth__title">{asideTitle}</h1>
            <p className="fd-auth__text">{asideText}</p>
            {asideNote ? <p className="fd-auth__note">{asideNote}</p> : null}
          </div>
        </aside>
      </div>
    );
  }

  /* ── Sign in ──────────────────────────────────────────────────────────── */

  function SignInScreen({ workspace, profile, onNavigate }) {
    const [values, setValues] = React.useState({ email: "", password: "" });
    const [submitted, setSubmitted] = React.useState(false);
    const [pending, setPending] = React.useState(false);
    const [reveal, setReveal] = React.useState(false);
    const errors = {};
    if (!EMAIL.test(values.email)) errors.email = "Enter a valid email address.";
    if (values.password.length < 8) errors.password = "Your password is at least 8 characters.";
    const valid = Object.keys(errors).length === 0;
    const dirty = values.email !== "" || values.password !== "";
    const submit = () => {
      setSubmitted(true);
      if (!valid) return;
      setPending(true);
      window.setTimeout(() => { setPending(false); onNavigate("/two-factor"); }, 600);
    };

    return (
      <AuthShell
        footer="Payment operations for platforms."
        asideTitle="Every figure on this desk can be checked."
        asideText="Meridian settles payments, sends payouts and holds what a dispute claims — and shows the arithmetic behind each one."
        asideNote={"Signing in to " + workspace.name + " · " + workspace.descriptor}
      >
        <Card>
          <CardHeader>
            <CardTitle>Sign in</CardTitle>
            <CardDescription>To {workspace.name} on Meridian.</CardDescription>
          </CardHeader>
          <CardPanel>
            <form className="fd-fields" onSubmit={(e) => { e.preventDefault(); submit(); }}>
              <Field>
                <FieldLabel htmlFor="fd-signin-email">Email</FieldLabel>
                <Input id="fd-signin-email" type="email" autoComplete="email" placeholder={profile.email} value={values.email}
                  invalid={submitted && !!errors.email} onChange={(e) => setValues(Object.assign({}, values, { email: e.target.value }))} />
                {submitted && errors.email ? <FieldError>{errors.email}</FieldError> : null}
              </Field>
              <Field>
                <FieldLabel htmlFor="fd-signin-password">Password</FieldLabel>
                <InputGroup data-invalid={submitted && !!errors.password ? "" : undefined}>
                  <InputGroupInput id="fd-signin-password" type={reveal ? "text" : "password"} autoComplete="current-password" value={values.password}
                    aria-invalid={(submitted && !!errors.password) || undefined} onChange={(e) => setValues(Object.assign({}, values, { password: e.target.value }))} />
                  <InputGroupAddon align="inline-end">
                    <Button variant="ghost" size="icon-xs" aria-label={reveal ? "Hide password" : "Show password"} onClick={() => setReveal(!reveal)}>
                      <Icon name={reveal ? "eye-off" : "eye"} size={14} />
                    </Button>
                  </InputGroupAddon>
                </InputGroup>
                {submitted && errors.password ? <FieldError>{errors.password}</FieldError> : <FieldDescription>At least 8 characters. A code from your authenticator comes next.</FieldDescription>}
              </Field>
              <Button type="submit" loading={pending} disabled={!dirty || pending}>Sign in</Button>
            </form>
          </CardPanel>
          <CardFooter className="fd-auth__actions">
            <Button variant="ghost" size="sm" onClick={() => onNavigate("/forgot-password")}>Forgot your password?</Button>
            <Button variant="outline" size="sm" onClick={() => onNavigate("/verify-code")}>Email me a code instead</Button>
          </CardFooter>
        </Card>
      </AuthShell>
    );
  }

  /* ── The 2FA challenge ────────────────────────────────────────────────── */

  function TwoFactorScreen({ profile, onNavigate, onSignIn }) {
    const [code, setCode] = React.useState("");
    const [submitted, setSubmitted] = React.useState(false);
    const [pending, setPending] = React.useState(false);
    const [trust, setTrust] = React.useState(false);
    const [recovery, setRecovery] = React.useState(false);
    const [backup, setBackup] = React.useState("");
    const error = recovery
      ? (backup.trim().length < 8 ? "A recovery code is eight characters." : null)
      : (code.length < 6 ? "The code is six digits." : null);
    const submit = () => {
      setSubmitted(true);
      if (error) return;
      setPending(true);
      window.setTimeout(() => { setPending(false); onSignIn(); }, 600);
    };

    return (
      <AuthShell
        footer="Codes rotate every 30 seconds. An old one will not be accepted."
        asideTitle="Money leaves this desk. A password alone is not enough."
        asideText="Approving a payout moves real money, so the second factor is required for everybody here — not offered as a setting."
        asideNote="Lost your device? A recovery code works once, then it is spent."
      >
        <Card>
          <CardHeader>
            <CardTitle>{recovery ? "Use a recovery code" : "Enter your code"}</CardTitle>
            <CardDescription>
              {recovery
                ? "One of the eight you saved when two-factor was switched on."
                : "From your authenticator app, for " + profile.email + "."}
            </CardDescription>
          </CardHeader>
          <CardPanel>
            <form className="fd-fields" onSubmit={(e) => { e.preventDefault(); submit(); }}>
              {recovery ? (
                <Field>
                  <FieldLabel htmlFor="fd-2fa-backup">Recovery code</FieldLabel>
                  <Input id="fd-2fa-backup" value={backup} placeholder="7HQ2-4KFD" invalid={submitted && !!error} onChange={(e) => setBackup(e.target.value)} />
                  {submitted && error ? <FieldError>{error}</FieldError> : <FieldDescription>Using one leaves you {7} of your {8}. Print a new set from your profile afterwards.</FieldDescription>}
                </Field>
              ) : (
                <Field>
                  <FieldLabel>Six-digit code</FieldLabel>
                  <OTPField length={6} size="lg" groupAfter={3} value={code} onValueChange={setCode} />
                  {submitted && error ? <FieldError>{error}</FieldError> : <FieldDescription>Paste the whole code and the cells fill themselves.</FieldDescription>}
                </Field>
              )}
              <label className="fd-check fd-check--inline">
                <Checkbox checked={trust} onCheckedChange={() => setTrust(!trust)} />
                <span className="fd-check__text"><span>Trust this device for 30 days</span></span>
              </label>
              <Button type="submit" loading={pending} disabled={pending}>Verify and continue</Button>
            </form>
          </CardPanel>
          <CardFooter className="fd-auth__actions">
            <Button variant="ghost" size="sm" onClick={() => { setRecovery(!recovery); setSubmitted(false); }}>
              {recovery ? "Use my authenticator instead" : "I do not have my device"}
            </Button>
            <Button variant="ghost" size="sm" onClick={() => onNavigate("/signin")}>Back to sign in</Button>
          </CardFooter>
        </Card>
      </AuthShell>
    );
  }

  /* ── Signing in with an emailed code ──────────────────────────────────── */

  function VerifyCodeScreen({ profile, onNavigate, onSignIn }) {
    const [stage, setStage] = React.useState("email");
    const [email, setEmail] = React.useState("");
    const [code, setCode] = React.useState("");
    const [submitted, setSubmitted] = React.useState(false);
    const [pending, setPending] = React.useState(false);
    const [seconds, setSeconds] = React.useState(0);

    React.useEffect(() => {
      if (stage !== "code" || seconds <= 0) return;
      const id = window.setTimeout(() => setSeconds(seconds - 1), 1000);
      return () => window.clearTimeout(id);
    }, [stage, seconds]);

    const error = stage === "email"
      ? (EMAIL.test(email) ? null : "Enter a valid email address.")
      : (code.length < 6 ? "The code is six digits." : null);

    const submit = () => {
      setSubmitted(true);
      if (error) return;
      setPending(true);
      window.setTimeout(() => {
        setPending(false);
        if (stage === "email") { setStage("code"); setSubmitted(false); setSeconds(30); }
        else onSignIn();
      }, 600);
    };

    return (
      <AuthShell
        footer="A sign-in code is good for ten minutes and can be used once."
        asideTitle="No password to remember, and none to leak."
        asideText="A code is mailed to the address on your account. It expires in ten minutes, works once, and can only be used on the device that asked for it."
      >
        <Card>
          <CardHeader>
            <CardTitle>{stage === "email" ? "Email me a code" : "Check your email"}</CardTitle>
            <CardDescription>
              {stage === "email"
                ? "We will send a six-digit code to the address on your account."
                : "We sent a six-digit code to " + (email || profile.email) + "."}
            </CardDescription>
          </CardHeader>
          <CardPanel>
            <form className="fd-fields" onSubmit={(e) => { e.preventDefault(); submit(); }}>
              {stage === "email" ? (
                <Field>
                  <FieldLabel htmlFor="fd-otp-email">Email</FieldLabel>
                  <Input id="fd-otp-email" type="email" autoComplete="email" placeholder={profile.email} value={email}
                    invalid={submitted && !!error} onChange={(e) => setEmail(e.target.value)} />
                  {submitted && error ? <FieldError>{error}</FieldError> : <FieldDescription>It has to be an address already on this workspace.</FieldDescription>}
                </Field>
              ) : (
                <Field>
                  <FieldLabel>Six-digit code</FieldLabel>
                  <OTPField length={6} size="lg" groupAfter={3} value={code} onValueChange={setCode} />
                  {submitted && error ? <FieldError>{error}</FieldError> : <FieldDescription>Paste the whole code and the cells fill themselves.</FieldDescription>}
                </Field>
              )}
              <Button type="submit" loading={pending} disabled={pending}>{stage === "email" ? "Send the code" : "Sign in"}</Button>
            </form>
          </CardPanel>
          <CardFooter className="fd-auth__actions">
            {stage === "code" ? (
              <Button variant="ghost" size="sm" disabled={seconds > 0} onClick={() => setSeconds(30)}>
                {seconds > 0 ? "Send another in " + seconds + "s" : "Send another code"}
              </Button>
            ) : null}
            <Button variant="ghost" size="sm" onClick={() => onNavigate("/signin")}>Use my password</Button>
          </CardFooter>
        </Card>
      </AuthShell>
    );
  }

  /* ── Forgotten password ───────────────────────────────────────────────── */

  function ForgotPasswordScreen({ profile, onNavigate }) {
    const [email, setEmail] = React.useState("");
    const [submitted, setSubmitted] = React.useState(false);
    const [pending, setPending] = React.useState(false);
    const [sent, setSent] = React.useState(false);
    const error = EMAIL.test(email) ? null : "Enter a valid email address.";
    const submit = () => {
      setSubmitted(true);
      if (error) return;
      setPending(true);
      window.setTimeout(() => { setPending(false); setSent(true); }, 600);
    };

    return (
      <AuthShell
        footer="Resetting a password does not sign you out of your other devices."
        asideTitle="A reset link, not a new password in an email."
        asideText="The link lasts an hour and can be opened once. Nobody at Meridian can read or set your password — including us."
      >
        <Card>
          <CardHeader>
            <CardTitle>{sent ? "Check your email" : "Reset your password"}</CardTitle>
            <CardDescription>
              {sent
                ? "If " + email + " is on this workspace, a reset link is on its way. It lasts an hour."
                : "We will email a link to set a new one."}
            </CardDescription>
          </CardHeader>
          <CardPanel>
            {sent ? (
              <div className="fd-stack">
                <Alert variant="info">
                  <AlertTitle>Nothing has changed yet</AlertTitle>
                  <AlertDescription>Your current password still works until you set a new one through the link.</AlertDescription>
                </Alert>
                <Button variant="outline" onClick={() => onNavigate("/reset-password")}>Open the link</Button>
              </div>
            ) : (
              <form className="fd-fields" onSubmit={(e) => { e.preventDefault(); submit(); }}>
                <Field>
                  <FieldLabel htmlFor="fd-forgot-email">Email</FieldLabel>
                  <Input id="fd-forgot-email" type="email" autoComplete="email" placeholder={profile.email} value={email}
                    invalid={submitted && !!error} onChange={(e) => setEmail(e.target.value)} />
                  {submitted && error ? <FieldError>{error}</FieldError> : <FieldDescription>We do not say whether an address is on the workspace — that would tell anybody who asked.</FieldDescription>}
                </Field>
                <Button type="submit" loading={pending} disabled={pending}>Email the reset link</Button>
              </form>
            )}
          </CardPanel>
          <CardFooter className="fd-auth__actions">
            <Button variant="ghost" size="sm" onClick={() => onNavigate("/signin")}>Back to sign in</Button>
          </CardFooter>
        </Card>
      </AuthShell>
    );
  }

  /* ── Setting the new one ──────────────────────────────────────────────── */

  function ResetPasswordScreen({ profile, onNavigate }) {
    const [values, setValues] = React.useState({ password: "", confirm: "" });
    const [submitted, setSubmitted] = React.useState(false);
    const [pending, setPending] = React.useState(false);
    const [reveal, setReveal] = React.useState(false);
    const set = (fields) => setValues(Object.assign({}, values, fields));

    /* Requirements are shown as they are met, not listed and then failed. */
    const rules = [
      { id: "length", label: "At least 12 characters", met: values.password.length >= 12 },
      { id: "case", label: "An upper and a lower case letter", met: /[a-z]/.test(values.password) && /[A-Z]/.test(values.password) },
      { id: "number", label: "A number or a symbol", met: /[0-9\W]/.test(values.password) },
    ];
    const errors = {};
    if (rules.some((r) => !r.met)) errors.password = "Your password does not meet all three requirements yet.";
    if (values.confirm !== values.password) errors.confirm = "The two do not match.";
    const valid = Object.keys(errors).length === 0;
    const submit = () => {
      setSubmitted(true);
      if (!valid) return;
      setPending(true);
      window.setTimeout(() => { setPending(false); onNavigate("/signin"); }, 600);
    };

    return (
      <AuthShell
        footer="Signing in again on this device will ask for your authenticator code."
        asideTitle="Set it once, and every other session ends."
        asideText="Changing your password signs out every device except this one. Anything you had approved stays approved — a session ending never touches the ledger."
        asideNote={"Resetting for " + profile.email}
      >
        <Card>
          <CardHeader>
            <CardTitle>Set a new password</CardTitle>
            <CardDescription>The link that brought you here is spent once this is saved.</CardDescription>
          </CardHeader>
          <CardPanel>
            <form className="fd-fields" onSubmit={(e) => { e.preventDefault(); submit(); }}>
              <Field>
                <FieldLabel htmlFor="fd-reset-password">New password</FieldLabel>
                <InputGroup data-invalid={submitted && !!errors.password ? "" : undefined}>
                  <InputGroupInput id="fd-reset-password" type={reveal ? "text" : "password"} autoComplete="new-password" value={values.password}
                    aria-invalid={(submitted && !!errors.password) || undefined} onChange={(e) => set({ password: e.target.value })} />
                  <InputGroupAddon align="inline-end">
                    <Button variant="ghost" size="icon-xs" aria-label={reveal ? "Hide password" : "Show password"} onClick={() => setReveal(!reveal)}>
                      <Icon name={reveal ? "eye-off" : "eye"} size={14} />
                    </Button>
                  </InputGroupAddon>
                </InputGroup>
                <span className="fd-rules">
                  {rules.map((rule) => (
                    <span className={"fd-rule" + (rule.met ? " fd-rule--met" : "")} key={rule.id}>
                      <Icon name={rule.met ? "check" : "circle"} size={12} />{rule.label}
                    </span>
                  ))}
                </span>
              </Field>
              <Field>
                <FieldLabel htmlFor="fd-reset-confirm">Type it again</FieldLabel>
                <Input id="fd-reset-confirm" type={reveal ? "text" : "password"} autoComplete="new-password" value={values.confirm}
                  invalid={submitted && !!errors.confirm} onChange={(e) => set({ confirm: e.target.value })} />
                {submitted && errors.confirm ? <FieldError>{errors.confirm}</FieldError> : null}
              </Field>
              <Button type="submit" loading={pending} disabled={pending}>Set password and sign in</Button>
            </form>
          </CardPanel>
          <CardFooter className="fd-auth__actions">
            <Button variant="ghost" size="sm" onClick={() => onNavigate("/signin")}>Back to sign in</Button>
          </CardFooter>
        </Card>
      </AuthShell>
    );
  }

  /* ── Signed out ───────────────────────────────────────────────────────── */

  function SignedOutScreen({ profile, onNavigate }) {
    return (
      <AuthShell
        footer="Closing the tab ends the session everywhere on this device."
        asideTitle="Nothing was left half done."
        asideText="Approvals in flight are exactly where they were, and every figure will read the same when you come back — none of them are stored, so none of them can drift."
      >
        <Card>
          <CardHeader>
            <CardTitle>You are signed out</CardTitle>
            <CardDescription>Nothing in {MERIDIAN_WORKSPACE.name} changed.</CardDescription>
          </CardHeader>
          <CardPanel className="fd-stack">
            <span className="fd-auth__who">
              <Face person={profile} size={40} />
              <span className="fd-record">
                <span className="fd-record__name">{profile.name}</span>
                <span className="fd-record__meta">{profile.role} · {profile.email}</span>
              </span>
            </span>
            <Separator />
            <Button onClick={() => onNavigate("/signin")}>Sign in</Button>
          </CardPanel>
        </Card>
      </AuthShell>
    );
  }

  Object.assign(window, {
    AuthShell, SignInScreen, SignedOutScreen,
    TwoFactorScreen, VerifyCodeScreen, ForgotPasswordScreen, ResetPasswordScreen,
  });
})();
