// v0.17.0 — roadmap item #16. The claim flow's landing page.
//
// The admin's invite email carries a link to /invites/claim?token=…;
// the invitee clicks through and lands here. The page reads the
// token from the URL, posts it to /api/invites/claim, and on success
// routes either to the passcode-set screen (if v0.10.0 passcode flow
// is in play and the user has no passcode yet) or to home.
//
// Anonymous-reachable: the entire point of the call is to establish
// the session; we do not pre-check authentication.
//
// Failure modes the backend distinguishes:
//   * 410 — token is expired or already claimed (the row is dead).
//   * 400 — token doesn't match any active invite (forged, revoked,
//     or wiped).
//
// We surface both as the same "this invite link isn't valid" shape
// for the invitee — the detail message from the server reads
// distinctively enough that the admin can debug from logs, and the
// invitee just needs to know they should contact the admin for a
// fresh link.

import { useEffect, useState } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import { claimInvite } from '../api.js'
import { EVENTS, identify, track } from '../lib/analytics.js'

export default function InviteClaim() {
  const location = useLocation()
  const navigate = useNavigate()
  const [status, setStatus] = useState('working') // 'working' | 'ok' | 'failed'
  const [error, setError] = useState(null)
  const [trustDevice, setTrustDevice] = useState(false)
  const [submitted, setSubmitted] = useState(false)
  const [user, setUser] = useState(null)
  const [needsPasscode, setNeedsPasscode] = useState(false)

  const params = new URLSearchParams(location.search)
  const token = params.get('token') || ''

  async function performClaim() {
    if (!token) {
      setStatus('failed')
      setError('No invite token in the URL.')
      return
    }
    setSubmitted(true)
    setStatus('working')
    setError(null)
    try {
      const result = await claimInvite(token, { trustDevice })
      setUser(result.user)
      setNeedsPasscode(!!result.needs_passcode)
      // v0.17.0 + #21 Part C — identify the new user with their OHM
      // user_id BEFORE firing any track() event, so the Amplitude
      // user record is created with the OHM id from the first event
      // rather than as an anonymous device that retroactively links.
      // setOnce on invited_at + invited_by_admin_id + initial_role so
      // these are immutable user-history markers on the Amplitude
      // record.
      if (result.user?.id != null) {
        const setOnceProps = {
          claim_method: 'admin-invite',
        }
        if (result.invited_at) setOnceProps.invited_at = ['__setOnce__', result.invited_at]
        if (result.invited_by_admin_id != null) {
          setOnceProps.invited_by_admin_id = ['__setOnce__', String(result.invited_by_admin_id)]
        }
        if (result.user.role) setOnceProps.initial_role = ['__setOnce__', result.user.role]
        identify({
          user_id: String(result.user.id),
          properties: setOnceProps,
        })
      }
      track(EVENTS.INVITE_CLAIMED, {
        invited_by_admin_id: result.invited_by_admin_id != null
          ? String(result.invited_by_admin_id) : null,
        initial_role: result.user?.role,
        needs_passcode: !!result.needs_passcode,
        trust_device: trustDevice,
      })
      setStatus('ok')
    } catch (e) {
      setStatus('failed')
      setError(e.message || 'Unable to claim invite')
    }
  }

  // Pre-flight: if the URL has no token at all, fail fast so the
  // invitee sees the missing-token shape immediately rather than
  // an empty form.
  useEffect(() => {
    if (!token) {
      setStatus('failed')
      setError('This claim link is missing its token.')
    }
  }, [token])

  // On a successful claim, route the user onward. The brief calls
  // this out: route to passcode-set if v0.10.0 passcode flow is in
  // play and the user has no passcode yet; otherwise route to home.
  useEffect(() => {
    if (status !== 'ok') return
    const timeout = setTimeout(() => {
      if (needsPasscode) {
        navigate('/settings/notifications#sign-in', { replace: true })
      } else {
        navigate('/', { replace: true })
      }
    }, 1200)
    return () => clearTimeout(timeout)
  }, [status, needsPasscode, navigate])

  return (
    <div className="invite-claim-page">
      <div className="invite-claim-panel">
        <h1>Claim your account</h1>
        {!submitted && status === 'working' && token && (
          <>
            <p>
              You've been invited to this deployment. Click the button below
              to claim your account and sign in. This link is single-use and
              expires 7 days after it was sent.
            </p>
            <label className="claim-trust-toggle">
              <input
                type="checkbox"
                checked={trustDevice}
                onChange={e => setTrustDevice(e.target.checked)}
              />
              {' '}Trust this device for 30 days (skip the email step on
              your next visit from this browser).
            </label>
            <div className="claim-actions">
              <button
                type="button"
                className="btn-primary"
                onClick={performClaim}
              >Claim my account</button>
            </div>
          </>
        )}
        {submitted && status === 'working' && (
          <p>Claiming…</p>
        )}
        {status === 'ok' && (
          <>
            <p className="settings-note success">
              Welcome{user?.display_name ? `, ${user.display_name}` : ''}!
              You're signed in.
            </p>
            <p className="muted">
              {needsPasscode
                ? 'Redirecting you to set a passcode so you can sign in without an email roundtrip next time…'
                : 'Redirecting you to the home page…'}
            </p>
          </>
        )}
        {status === 'failed' && (
          <>
            <p className="settings-note warning">
              {error || "This invite link isn't valid."}
            </p>
            <p className="muted">
              If you believe this is a mistake, contact the admin who
              sent you the invite — they can issue a fresh link.
            </p>
          </>
        )}
      </div>
    </div>
  )
}
