/* Marketing Desk auth — its own shell: no sidebar, no pane, no navigation owner, no
   account menu (AGENTS §7.1). Layout variant: centred card, 23rem column, on the
   same tint the app sits on, so it reads as the same product with the pane taken
   away. Every screen here goes through AuthShell, which is what keeps the six of
   them visibly siblings rather than six pages that happen to be about accounts.

   Strategy, declared: PASSWORD. No providers, because this product ships no
   provider marks and §7.4 refuses hand-drawn ones.
   Commit model: STAGED, as every auth form is. Errors render on submission, not
   on first paint, and the password field is the only thing cleared.

   The reset flow is all five screens §7.5 asks for — request, sent confirmation,
   set-new behind the token, expired token, outcome — because building three of
   them would leave a user holding a dead link with nowhere to go. Every screen
   has a way back to sign in; nothing here links to signup, MFA or lockout,
   because those screens do not exist.

   Enumeration safety: the request screen's success copy never says whether an
   account exists, and the confirmation states the address the user typed rather
   than one the server confirmed. */
(() => {
  const {
    Button, Input, Field, FieldLabel, FieldDescription, FieldError,
    Alert, AlertTitle, AlertDescription,
  } = window.OriginDesignSystem_7c998b;

  /* One frame for all six screens. */
  function AuthShell({ title, lead, children, foot, workspace }) {
    return (
      <div className="md-auth">
        <div className="md-auth__col">
          <div className="md-auth__mark">
            <img className="md-brand__logo" src={BRAND_MARK} alt="" width="28" height="28" />
            <span className="md-brand__text">
              <span className="md-brand__name" style={{ fontSize: "var(--text-base)" }}>Marketing Desk</span>
              <span className="md-brand__workspace">{workspace.name}</span>
            </span>
          </div>
          <div className="md-auth__pane">
            <div>
              <h1 className="md-auth__title">{title}</h1>
              {lead ? <p className="md-auth__lead">{lead}</p> : null}
            </div>
            {children}
          </div>
          {foot ? <p className="md-auth__foot">{foot}</p> : null}
        </div>
      </div>
    );
  }

  function BackToSignIn({ onNavigate, label }) {
    return (
      <button type="button" className="md-link md-auth__back" onClick={() => onNavigate("/signin")}>{label || "Back to sign in"}</button>
    );
  }

  function SignInScreen({ workspace, onSignIn, onNavigate }) {
    const [values, setValues] = React.useState({ email: "", password: "" });
    const [submitted, setSubmitted] = React.useState(false);
    const [reveal, setReveal] = React.useState(false);
    const [rejected, setRejected] = React.useState(false);

    const errors = {};
    if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(values.email)) errors.email = "Enter a valid email address.";
    if (!values.password) errors.password = "Enter your password.";
    const valid = Object.keys(errors).length === 0;
    const dirty = values.email !== "" || values.password !== "";
    const set = (key, value) => { setValues((v) => Object.assign({}, v, { [key]: value })); setRejected(false); };

    /* One state per screen: a rejected credential replaces the field errors
       rather than stacking with them. */
    const submit = () => {
      setSubmitted(true);
      if (!valid) return;
      if (values.password === "password") {
        setRejected(true);
        setValues((v) => Object.assign({}, v, { password: "" }));
        return;
      }
      onSignIn();
    };

    return (
      <AuthShell workspace={workspace}
        title="Sign in"
        lead={"Marketing automation for " + workspace.name + "."}
        foot={"Sending from " + domainName(SENDING_DOMAINS, workspace.sendingDomainId) + ". If you cannot get in, the workspace owner can reissue your invitation."}
      >
        {rejected && submitted ? (
          <Alert variant="error">
            <Icon name="triangle-alert" size={16} />
            <AlertTitle>Email or password is incorrect</AlertTitle>
            <AlertDescription>Try again, or reset your password below.</AlertDescription>
          </Alert>
        ) : null}

        <div className="md-fields">
          <Field>
            <FieldLabel htmlFor="cd-email">Email</FieldLabel>
            <Input id="cd-email" type="email" autoComplete="email" placeholder="you@northwind.studio"
              value={values.email} invalid={submitted && !rejected && !!errors.email}
              onChange={(e) => set("email", e.target.value)} />
            {submitted && !rejected && errors.email ? <FieldError>{errors.email}</FieldError> : null}
          </Field>
          <Field>
            <span className="md-auth__labelrow">
              <FieldLabel htmlFor="cd-password">Password</FieldLabel>
              <button type="button" className="md-link" onClick={() => onNavigate("/forgot-password")}>Forgot password?</button>
            </span>
            <Input id="cd-password" type={reveal ? "text" : "password"} autoComplete="current-password"
              value={values.password} invalid={submitted && !rejected && !!errors.password}
              onChange={(e) => set("password", e.target.value)}
              onKeyDown={(e) => { if (e.key === "Enter") submit(); }}
              endAddon={
                <Button variant="ghost" size="icon-sm" aria-label={reveal ? "Hide password" : "Show password"} onClick={() => setReveal(!reveal)}>
                  <Icon name={reveal ? "eye-off" : "eye"} />
                </Button>
              } />
            {submitted && !rejected && errors.password ? <FieldError>{errors.password}</FieldError> : null}
          </Field>
          <Button onClick={submit} disabled={!dirty}>Sign in</Button>
        </div>
      </AuthShell>
    );
  }

  /* Request. Enumeration-safe: whatever is typed, the next screen is the same. */
  function ForgotPasswordScreen({ workspace, email, onSubmit, onNavigate }) {
    const [value, setValue] = React.useState(email || "");
    const [submitted, setSubmitted] = React.useState(false);
    const error = /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(value) ? null : "Enter a valid email address.";

    const submit = () => { setSubmitted(true); if (!error) onSubmit(value.trim()); };

    return (
      <AuthShell workspace={workspace}
        title="Reset your password"
        lead={"We will email a link that lets you set a new one. It works for " + RESET_LINK_MINUTES + " minutes."}
        foot="Changing your password signs you out of Marketing Desk everywhere else."
      >
        <div className="md-fields">
          <Field>
            <FieldLabel htmlFor="cd-fp-email">Email</FieldLabel>
            <Input id="cd-fp-email" type="email" autoComplete="email" placeholder="you@northwind.studio"
              value={value} invalid={submitted && !!error}
              onChange={(e) => setValue(e.target.value)}
              onKeyDown={(e) => { if (e.key === "Enter") submit(); }} />
            {submitted && error ? <FieldError>{error}</FieldError> : <FieldDescription>The address you sign in with.</FieldDescription>}
          </Field>
          <Button onClick={submit} disabled={value === ""}>Send reset link</Button>
          <BackToSignIn onNavigate={onNavigate} />
        </div>
      </AuthShell>
    );
  }

  /* The sent confirmation is a screen, not a toast: it states the address, the
     expiry and a resend with a real cooldown. It still says nothing about whether
     an account exists. */
  function ResetLinkSentScreen({ workspace, email, onNavigate }) {
    const COOLDOWN = 45;
    const [left, setLeft] = React.useState(COOLDOWN);
    const [resends, setResends] = React.useState(0);
    React.useEffect(() => {
      if (left <= 0) return undefined;
      const timer = setInterval(() => setLeft((n) => (n <= 1 ? 0 : n - 1)), 1000);
      return () => clearInterval(timer);
    }, [left]);

    return (
      <AuthShell workspace={workspace}
        title="Check your email"
        lead={"If an account exists for " + email + ", a link to set a new password is on its way. It works for " + RESET_LINK_MINUTES + " minutes from when it was sent."}
        foot="Nothing has changed yet. Your current password keeps working until you set a new one."
      >
        <div className="md-fields">
          <Alert>
            <Icon name="mail" size={16} />
            <AlertTitle>It can take a minute to arrive</AlertTitle>
            <AlertDescription>Look in spam before asking for another one — a second link cancels the first.</AlertDescription>
          </Alert>
          <Button variant="outline" disabled={left > 0} onClick={() => { setResends(resends + 1); setLeft(COOLDOWN); }}>
            {left > 0 ? "Resend in " + left + "s" : "Resend link"}
          </Button>
          {resends ? (
            <p className="md-footnote">
              {resends === 1 ? "One more link sent" : resends + " more links sent"} — only the newest one works.
            </p>
          ) : null}
          <BackToSignIn onNavigate={onNavigate} />
        </div>
      </AuthShell>
    );
  }

  /* Set-new, reached from the link. One password field with a reveal toggle, so
     §7.5 wants no confirm field; the checklist is live and reads PASSWORD_RULES,
     the same list the submit gate reads. */
  function SetNewPasswordScreen({ workspace, link, now, onSubmit, onNavigate }) {
    const [value, setValue] = React.useState("");
    const [reveal, setReveal] = React.useState(false);
    const [submitted, setSubmitted] = React.useState(false);
    const results = PASSWORD_RULES.map((rule) => ({ rule: rule, met: rule.test(value) }));
    const unmet = results.filter((r) => !r.met);
    const expiresAt = link.sentAt + RESET_LINK_MINUTES * 60e3;

    const submit = () => { setSubmitted(true); if (unmet.length === 0) onSubmit(value); };

    return (
      <AuthShell workspace={workspace}
        title="Set a new password"
        lead={"For " + link.email + ". This link stops working at " + formatWhen(expiresAt, now) + ", " + RESET_LINK_MINUTES + " minutes after it was sent."}
        foot="Setting it signs you out of every other browser and device."
      >
        <div className="md-fields">
          <Field>
            <FieldLabel htmlFor="cd-np">New password</FieldLabel>
            <Input id="cd-np" type={reveal ? "text" : "password"} autoComplete="new-password"
              value={value} invalid={submitted && unmet.length > 0}
              onChange={(e) => setValue(e.target.value)}
              onKeyDown={(e) => { if (e.key === "Enter") submit(); }}
              endAddon={
                <Button variant="ghost" size="icon-sm" aria-label={reveal ? "Hide password" : "Show password"} onClick={() => setReveal(!reveal)}>
                  <Icon name={reveal ? "eye-off" : "eye"} />
                </Button>
              } />
            {submitted && unmet.length ? <FieldError>{unmet.length === 1 ? "One requirement is still unmet." : unmet.length + " requirements are still unmet."}</FieldError> : null}
          </Field>
          <ul className="md-checklist">
            {results.map((result) => (
              <li key={result.rule.id} data-met={result.met ? "true" : "false"}>
                <Icon name={result.met ? "check" : "circle"} size={14} />
                {result.rule.label}
              </li>
            ))}
          </ul>
          <Button onClick={submit} disabled={value === ""}>Set new password</Button>
          <button type="button" className="md-link md-auth__back" onClick={() => onNavigate("/reset-password/expired")}>My link has stopped working</button>
        </div>
      </AuthShell>
    );
  }

  /* Expired or already used. One action, and it is the one that gets the user
     moving again. */
  function ResetLinkExpiredScreen({ workspace, onNavigate }) {
    return (
      <AuthShell workspace={workspace}
        title="This link has stopped working"
        lead={"A reset link works for " + RESET_LINK_MINUTES + " minutes and only once. This one has expired, or a newer link replaced it."}
        foot="Your current password still works. Nothing about your account has changed."
      >
        <div className="md-fields">
          <Button onClick={() => onNavigate("/forgot-password")}>Send reset link</Button>
          <BackToSignIn onNavigate={onNavigate} label="I remembered my password" />
        </div>
      </AuthShell>
    );
  }

  /* The outcome states the session consequence and routes somewhere real. */
  function PasswordResetDoneScreen({ workspace, email, onNavigate }) {
    return (
      <AuthShell workspace={workspace}
        title="Password changed"
        lead={"The password for " + email + " has been replaced. Every other browser and device has been signed out."}
        foot="If this was not you, ask the workspace owner to remove your access straight away."
      >
        <div className="md-fields">
          <Alert variant="success">
            <Icon name="check" size={16} />
            <AlertTitle>You are signed out everywhere else</AlertTitle>
            <AlertDescription>Anything scheduled keeps sending — signing out of a browser does not pause a journey or a broadcast.</AlertDescription>
          </Alert>
          <Button onClick={() => onNavigate("/signin")}>Sign in</Button>
        </div>
      </AuthShell>
    );
  }

  Object.assign(window, {
    AuthShell, SignInScreen, ForgotPasswordScreen, ResetLinkSentScreen,
    SetNewPasswordScreen, ResetLinkExpiredScreen, PasswordResetDoneScreen,
  });
})();
