// ForestLynk — magic-link sign-in screen.
// Two-step flow: email entry → awaiting-link. Same screen, state swap.

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

const TAGLINES = {
  link:   'A link in your inbox is the whole sign-in.',
  send:   "We'll send a link to your inbox.",
  sign:   'Sign in with a link in your inbox.',
  none:   null,
};

// SignInScreen — pure, state-driven. Wrap with a state owner for interactive use.
//
// props.state ∈
//   'empty' | 'typing-invalid' | 'typing-valid'
//   'submitting'
//   'error'           — server error after submit, returns to form
//   'awaiting'        — link sent, resend throttled (countdown)
//   'awaiting-ready'  — countdown elapsed, resend re-enabled
//   'awaiting-resent' — just resent (brief beat)
//   'remembered'      — email cached locally but session is gone — one-tap relog
function SignInScreen({
  state = 'empty',
  email = '',
  errorMessage = null,
  tagline = TAGLINES.link,
  resendIn = 24,
  onEmailChange,
  onSubmit,
  onResend,
  onEditEmail,
  onUseDifferent,
  variant = 'canonical',   // canonical | threshold | voice | grain
  focused = false,
}) {
  const isAwaiting = state === 'awaiting' || state === 'awaiting-ready' || state === 'awaiting-resent';
  const isRemembered = state === 'remembered';
  const inputState =
    state === 'typing-invalid' && email.length > 4 ? 'invalid' :
    state === 'error' ? 'invalid' :
    'idle';
  const ctaDisabled =
    state === 'empty' || state === 'typing-invalid' || state === 'error';
  const ctaLoading = state === 'submitting';
  const inlineError =
    state === 'error'           ? (errorMessage || "Couldn't send the link. Try again.") :
    state === 'typing-invalid' && email.length > 4 ? "Doesn't look like an email yet." :
    null;

  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: variant === 'grain' ? '#0B1306' : '#0B1306',
      display: 'flex', flexDirection: 'column',
      padding: '0 28px',
      overflow: 'hidden',
    }}>
      {/* Optional background ornament for the "grain" variant */}
      {variant === 'grain' && <GrainBackground/>}
      {variant === 'threshold' && isAwaiting === false && <BreathingGlow/>}

      {/* Hero lockup — anchored where the lowercase wordmark used to sit */}
      <div style={{
        flexShrink: 0,
        paddingTop: '19%',
        display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 14,
        position: 'relative', zIndex: 2,
      }}>
        {variant === 'voice' ? (
          <VoiceHero tagline={tagline} />
        ) : variant === 'threshold' ? (
          <ThresholdHero awaiting={isAwaiting} />
        ) : (
          <>
            <LogoWordmark scale={1}/>
            {tagline && (
              <p style={{
                font: '400 14.5px/1.45 var(--font-sans)',
                color: '#8A9678', margin: '2px 0 0', maxWidth: 280,
              }}>{tagline}</p>
            )}
          </>
        )}
      </div>

      {/* Form / awaiting block */}
      <div style={{
        flex: 1, paddingTop: 36,
        display: 'flex', flexDirection: 'column', gap: 12,
        position: 'relative', zIndex: 2, minHeight: 0,
      }}>
        {!isAwaiting && !isRemembered && (
          <>
            {/* Email field — labelled by the placeholder/voice; no floating label */}
            <FLField
              value={email}
              onChange={onEmailChange}
              placeholder="you@example.com"
              type="email"
              state={inputState}
              focused={focused}
              ariaLabel="Email address"
            />

            {/* Inline error slot — reserves space so layout doesn't jump */}
            <div style={{ minHeight: 18 }}>
              {inlineError && (
                <FLHelper tone="error">{inlineError}</FLHelper>
              )}
            </div>

            <FLPrimaryButton onClick={onSubmit} disabled={ctaDisabled} loading={ctaLoading}>
              {ctaLoading ? 'Sending…' : 'Send link'}
            </FLPrimaryButton>

            {/* Footnote */}
            <p style={{
              font: '400 11.5px/1.5 var(--font-sans)',
              color: '#5A6450', margin: '14px 0 0', textAlign: 'left',
            }}>
              We don't store passwords. The link sits in your inbox until you tap it.
            </p>
          </>
        )}
        {isRemembered && (
          <RememberedBlock
            email={email}
            loading={ctaLoading}
            onSubmit={onSubmit}
            onUseDifferent={onUseDifferent}
          />
        )}
        {isAwaiting && (
          <AwaitingBlock
            email={email}
            state={state}
            resendIn={resendIn}
            onResend={onResend}
            onEditEmail={onEditEmail}
          />
        )}
      </div>
    </div>
  );
}

// ─────────────────────────── Remembered-email block ───────────────────────────
// "We know you. Sign back in?" — the email is cached locally even though the
// session is gone. One-tap to send a fresh magic link to the same address;
// a quiet "Use a different email" link lets a guest on a shared device escape.
function RememberedBlock({ email, loading, onSubmit, onUseDifferent }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      {/* Recognition card */}
      <div style={{
        background: '#111D0A', border: '0.5px solid #2D3A22',
        borderRadius: 14, padding: '14px 14px',
        display: 'flex', alignItems: 'center', gap: 12,
      }}>
        {/* Calm leaf-dot avatar — we don't know their handle yet, just their email */}
        <div style={{
          width: 36, height: 36, borderRadius: '50%',
          background: '#1B3A1D', border: '0.5px solid #2C5F2E',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          font: '500 14px var(--font-mono)', color: '#A8C5A0',
          flexShrink: 0, letterSpacing: '-0.02em',
        }}>{(email[0] || '·').toLowerCase()}</div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            font: '500 10px var(--font-sans)', color: '#8A9678',
            letterSpacing: '0.08em', textTransform: 'uppercase',
          }}>Welcome back</div>
          <div style={{
            font: '500 15px var(--font-mono)', color: '#F2EDE4',
            letterSpacing: '-0.01em', marginTop: 2,
            overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          }}>{email}</div>
        </div>
      </div>

      <FLPrimaryButton onClick={onSubmit} loading={loading}>
        {loading ? 'Sending…' : 'Send me a new link'}
      </FLPrimaryButton>

      {/* Escape hatch — quiet, secondary affordance */}
      <button
        onClick={onUseDifferent}
        style={{
          width: '100%', padding: '10px',
          background: 'transparent', border: 'none',
          color: '#76AB78', font: '500 13px var(--font-sans)', cursor: 'pointer',
          textAlign: 'center',
        }}>
        Use a different email
      </button>

      <p style={{
        font: '400 11.5px/1.5 var(--font-sans)',
        color: '#5A6450', margin: '4px 0 0',
      }}>
        We remembered your address locally so you don't have to type it again. We never stored your password — there isn't one.
      </p>
    </div>
  );
}

// ─────────────────────────── Awaiting-link block ───────────────────────────
function AwaitingBlock({ email, state, resendIn, onResend, onEditEmail }) {
  const canResend = state === 'awaiting-ready';
  const justResent = state === 'awaiting-resent';
  return (
    <div style={{
      display: 'flex', flexDirection: 'column', gap: 16,
    }}>
      {/* Envelope-ish ambient card */}
      <div style={{
        background: '#111D0A', border: '0.5px solid #2D3A22',
        borderRadius: 14, padding: '18px 16px',
        display: 'flex', flexDirection: 'column', gap: 10,
        position: 'relative', overflow: 'hidden',
      }}>
        <EnvelopeOrnament/>
        <div style={{
          font: '500 10px var(--font-sans)', color: '#8A9678',
          letterSpacing: '0.08em', textTransform: 'uppercase',
        }}>Check your inbox</div>
        <p style={{
          font: '500 17px/1.4 var(--font-sans)', color: '#F2EDE4', margin: 0,
          letterSpacing: '-0.01em',
        }}>
          We sent a link to <span style={{ fontFamily: 'var(--font-mono)', color: '#C9D2BB', fontSize: 15 }}>{email}</span>.
        </p>
        <p style={{ font: '400 13.5px/1.5 var(--font-sans)', color: '#8A9678', margin: 0 }}>
          Tap it from this phone to finish signing in. The link expires in 15 minutes.
        </p>
      </div>

      {/* Resend row */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        <button
          onClick={canResend ? onResend : undefined}
          disabled={!canResend}
          style={{
            flex: 1, padding: '12px 14px',
            background: 'transparent', color: canResend ? '#C9D2BB' : '#586552',
            border: `0.5px solid ${canResend ? '#445239' : '#2D3A22'}`,
            borderRadius: 12, font: '500 14px var(--font-sans)',
            cursor: canResend ? 'pointer' : 'default',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          }}>
          {justResent
            ? <><DotSent/> Link resent</>
            : canResend
              ? 'Resend link'
              : <>Resend in <span style={{ fontVariantNumeric: 'tabular-nums', color: '#8A9678' }}>{resendIn}s</span></>}
        </button>
        <button
          onClick={onEditEmail}
          style={{
            padding: '12px 14px',
            background: 'transparent', color: '#76AB78',
            border: 'none', borderBottom: '0.5px solid transparent',
            font: '500 13.5px var(--font-sans)', cursor: 'pointer',
          }}>
          Wrong email?
        </button>
      </div>

      {/* Spam folder hint */}
      <p style={{
        font: '400 12px/1.5 var(--font-sans)', color: '#5A6450',
        margin: '6px 0 0',
      }}>
        Nothing in your inbox after a minute? Check spam — magic links sometimes drift there.
      </p>
    </div>
  );
}

function DotSent() {
  return (
    <span style={{
      width: 8, height: 8, borderRadius: '50%', background: '#D4960C',
      boxShadow: '0 0 0 3px rgba(212,150,12,0.22)', display: 'inline-block',
    }}/>
  );
}

// Subtle envelope corner motif behind the awaiting card — a single diagonal hairline.
function EnvelopeOrnament() {
  return (
    <svg width="100%" height="100%" viewBox="0 0 360 120" preserveAspectRatio="none" style={{
      position: 'absolute', inset: 0, opacity: 0.25, pointerEvents: 'none',
    }}>
      <path d="M 0 -20 L 360 110" stroke="#2D3A22" strokeWidth="0.5" fill="none"/>
      <path d="M 360 -20 L 0 110" stroke="#2D3A22" strokeWidth="0.5" fill="none"/>
    </svg>
  );
}

// ─────────────────────────── Variant heroes ───────────────────────────
function ThresholdHero({ awaiting }) {
  return (
    <div style={{
      display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 18,
    }}>
      <div style={{
        position: 'relative',
        animation: awaiting ? 'none' : 'fl-breathe 4.2s ease-in-out infinite',
      }}>
        <ThresholdMark size={68} pulse/>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <LogoWordmark scale={0.95}/>
        <p style={{
          font: '400 italic 17px/1.45 var(--font-serif)', color: '#C9D2BB', margin: 0,
          maxWidth: 280, letterSpacing: '-0.01em',
        }}>Step into the forest.</p>
      </div>
    </div>
  );
}

function VoiceHero() {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
      <LogoWordmark scale={0.95}/>
      <div>
        <p style={{
          font: '400 italic 28px/1.25 var(--font-serif)', color: '#F2EDE4',
          margin: 0, letterSpacing: '-0.02em',
        }}>
          A quiet inbox is<br/>the whole front door.
        </p>
        <p style={{
          font: '400 13.5px/1.5 var(--font-sans)', color: '#8A9678',
          margin: '14px 0 0', maxWidth: 280,
        }}>Type your email, we'll send a link.</p>
      </div>
    </div>
  );
}

// Soft contour/topographic SVG behind the form.
function GrainBackground() {
  return (
    <svg width="100%" height="100%" viewBox="0 0 390 800" preserveAspectRatio="xMidYMid slice" style={{
      position: 'absolute', inset: 0, opacity: 0.55, pointerEvents: 'none',
    }}>
      {[120, 200, 290, 400, 530, 680].map((r, i) => (
        <circle key={i} cx="-40" cy="-40" r={r}
          stroke="#1F2B16" strokeWidth="0.5" fill="none" opacity={0.6 - i * 0.06}/>
      ))}
      {[420, 530, 660].map((r, i) => (
        <circle key={`b${i}`} cx="430" cy="900" r={r}
          stroke="#1F2B16" strokeWidth="0.5" fill="none" opacity={0.45 - i * 0.08}/>
      ))}
    </svg>
  );
}

// ─────────────────────────── Expired-link landing ───────────────────────────
// What the user sees when they tap a stale or already-used magic link
// (>15min old, already consumed on another device, or revoked by re-send).
// Calm — we never frame as "error", since failing to sign in is a normal
// condition of the place, not an alarm.
function ExpiredLinkScreen({ email = 'you@example.com', kind = 'expired', onResend, onUseDifferent }) {
  const copy = {
    expired: {
      eyebrow: 'Link expired',
      title: 'That link is no longer valid.',
      body: 'Magic links sit unread for 15 minutes, then sunset. Send yourself a fresh one — same email, same inbox.',
    },
    used: {
      eyebrow: 'Already used',
      title: 'That link was already opened.',
      body: 'For your safety, each link works once. If that wasn\'t you, request a new link and we\'ll invalidate any others in flight.',
    },
    invalid: {
      eyebrow: 'Link unrecognized',
      title: "We couldn't read that link.",
      body: 'It may have been mangled by your email client, or copied without the full URL. Try sending a fresh one.',
    },
  }[kind] || {};
  return (
    <div style={{
      position: 'absolute', inset: 0, background: '#0B1306',
      display: 'flex', flexDirection: 'column',
      padding: '0 28px', overflow: 'hidden',
    }}>
      <div style={{
        flexShrink: 0, paddingTop: '19%',
        display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 14,
      }}>
        <LogoWordmark scale={1}/>
      </div>

      <div style={{ paddingTop: 36, display: 'flex', flexDirection: 'column', gap: 14 }}>
        {/* Dimmed-mark card — the link has cooled. */}
        <div style={{
          background: '#111D0A', border: '0.5px solid #2D3A22',
          borderRadius: 14, padding: '18px 16px',
          display: 'flex', flexDirection: 'column', gap: 10,
          position: 'relative', overflow: 'hidden',
        }}>
          <div style={{
            position: 'absolute', top: 14, right: 14, opacity: 0.55,
          }}>
            <ThresholdMark size={28} dim/>
          </div>
          <div style={{
            font: '500 10px var(--font-sans)', color: '#D6BFA8',
            letterSpacing: '0.08em', textTransform: 'uppercase',
          }}>{copy.eyebrow}</div>
          <p style={{
            font: '500 17px/1.35 var(--font-sans)', color: '#F2EDE4', margin: 0,
            letterSpacing: '-0.01em', maxWidth: 280,
          }}>{copy.title}</p>
          <p style={{
            font: '400 13.5px/1.5 var(--font-sans)', color: '#8A9678', margin: 0,
            maxWidth: 300,
          }}>{copy.body}</p>
        </div>

        <FLPrimaryButton onClick={onResend}>
          Send a fresh link to <span style={{ fontFamily: 'var(--font-mono)', fontWeight: 400, opacity: 0.9, marginLeft: 4 }}>{email}</span>
        </FLPrimaryButton>

        <button onClick={onUseDifferent} style={{
          width: '100%', padding: '10px',
          background: 'transparent', border: 'none',
          color: '#76AB78', font: '500 13px var(--font-sans)', cursor: 'pointer',
          textAlign: 'center',
        }}>
          Use a different email
        </button>
      </div>
    </div>
  );
}

Object.assign(window, { SignInScreen, ExpiredLinkScreen, TAGLINES, EMAIL_RE });
