import { useEffect, useState } from 'react'
import { Link, useNavigate, useLocation } from 'react-router-dom'
import MoonDot from '../../components/MoonDot.jsx'
import ProviderIcon from '../../components/ProviderIcon.jsx'
import { useAuth } from '../../contexts/AuthContext.jsx'
import { api } from '../../api/client.js'

// Friendly copy for the ?sso_error codes the SSO callback can redirect back with.
const SSO_ERRORS = {
  not_linked: 'That account is not linked to an admin user. Sign in with your password, then link it under Account.',
  disabled: 'This account is not active. Contact an administrator.',
  denied: 'Sign-in was cancelled.',
  unavailable: 'That sign-in method is not available right now.',
  bad_state: 'Your sign-in session expired. Please try again.',
  error: 'Could not complete sign-in. Please try again.',
}

const BG =
  "linear-gradient(180deg,rgba(11,15,20,0.72),rgba(11,15,20,0.9)),url('/assets/img/uomysticmoon-main-hero.png')"

// Hidden anti-bot field. Off-screen via CSS (NOT display:none/hidden, which bots
// skip) so real users never fill it but naive scripted bots do. Name must match
// the server's HONEYPOT_FIELD ('company').
const honeypotStyle = {
  position: 'absolute',
  left: '-9999px',
  top: 'auto',
  width: '1px',
  height: '1px',
  opacity: 0,
  pointerEvents: 'none',
}

export default function AdminLogin() {
  const { user, login, loginTotp, ssoLoginTotp } = useAuth()
  const navigate = useNavigate()
  const location = useLocation()
  const dest = location.state?.from?.pathname || '/admin'

  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  const [company, setCompany] = useState('') // honeypot — must stay empty
  const [error, setError] = useState('')
  const [busy, setBusy] = useState(false)

  // Two-factor step state. `ssoTotp` marks the SSO variant: the challenge lives in
  // an httpOnly cookie (not React state), so the code posts to a different endpoint.
  const [stage, setStage] = useState('creds') // 'creds' | 'totp'
  const [challenge, setChallenge] = useState('')
  const [code, setCode] = useState('')
  const [ssoTotp, setSsoTotp] = useState(false)

  // SSO providers to offer (empty if none configured) + any error the callback
  // bounced us back with (?sso_error=...).
  const [providers, setProviders] = useState([])
  const ssoError = SSO_ERRORS[new URLSearchParams(location.search).get('sso_error')] || ''

  // Already signed in → go straight to the panel.
  useEffect(() => {
    if (user) navigate(dest, { replace: true })
  }, [user, dest, navigate])

  // The SSO callback bounces 2FA accounts back here with ?sso_totp=1 after the IdP
  // step: it has staged an httpOnly TOTP challenge and needs the authenticator code
  // before it will issue a session. Jump straight to the code step.
  useEffect(() => {
    if (new URLSearchParams(location.search).get('sso_totp')) {
      setStage('totp')
      setSsoTotp(true)
    }
  }, [location.search])

  // Load enabled SSO providers for the buttons. Failure is non-fatal — the page
  // still works with password login and simply shows no provider buttons.
  useEffect(() => {
    let active = true
    api
      .authProviders()
      .then((list) => active && setProviders(Array.isArray(list) ? list : []))
      .catch(() => active && setProviders([]))
    return () => {
      active = false
    }
  }, [])

  // Full-page redirect into the provider's OAuth flow, preserving the intended
  // destination so the callback can return the user there.
  function startSso(provider) {
    const q = dest && dest !== '/admin' ? `?returnTo=${encodeURIComponent(dest)}` : ''
    window.location.assign(provider.loginUrl + q)
  }

  async function onSubmit(e) {
    e.preventDefault()
    setError('')
    setBusy(true)
    try {
      const data = await login(username, password, { company })
      if (data.totpRequired) {
        setChallenge(data.challenge)
        setStage('totp')
        setBusy(false)
        return
      }
      navigate(dest, { replace: true })
    } catch (err) {
      setError(err.status === 401 ? 'Incorrect username or password.' : 'Could not sign in right now.')
      setBusy(false)
    }
  }

  async function onSubmitTotp(e) {
    e.preventDefault()
    setError('')
    setBusy(true)
    try {
      if (ssoTotp) {
        const { returnTo } = await ssoLoginTotp(code)
        navigate(returnTo || '/admin', { replace: true })
      } else {
        await loginTotp(challenge, code)
        navigate(dest, { replace: true })
      }
    } catch (err) {
      const expired = err.status === 401 && /expired/i.test(err.message)
      setError(
        expired
          ? 'Your verification session expired. Please sign in again.'
          : 'Invalid verification code.',
      )
      setBusy(false)
      if (expired) {
        setStage('creds')
        setSsoTotp(false)
      }
    }
  }

  return (
    <main
      style={{
        minHeight: '100vh',
        display: 'grid',
        placeItems: 'center',
        padding: '40px 18px',
        overflow: 'hidden',
        backgroundColor: 'var(--bg-deep)',
        backgroundImage: BG,
        backgroundPosition: 'center',
        backgroundSize: 'cover',
      }}
    >
      <div style={{ width: '100%', maxWidth: 400 }}>
        <div style={{ textAlign: 'center', marginBottom: 26 }}>
          <div style={{ marginBottom: 14 }}>
            <MoonDot size={15} glow={0.55} />
          </div>
          <h1 className="display" style={{ margin: 0, fontSize: '1.7rem', letterSpacing: '0.04em', color: 'var(--head)' }}>
            UOMysticmoon
          </h1>
          <p className="sans" style={{ margin: '6px 0 0', color: '#9aa6b4', fontSize: '0.8rem', letterSpacing: '0.16em', textTransform: 'uppercase' }}>
            Admin Panel
          </p>
        </div>

        <form
          onSubmit={stage === 'totp' ? onSubmitTotp : onSubmit}
          style={{
            border: '1px solid var(--line)',
            borderRadius: 12,
            padding: 28,
            background: 'linear-gradient(180deg,rgba(25,34,49,0.92),rgba(20,26,33,0.92))',
            backdropFilter: 'blur(6px)',
            boxShadow: '0 24px 60px rgba(0,0,0,0.5)',
          }}
        >
          {stage === 'creds' ? (
            <>
              <label style={{ display: 'block', marginBottom: 16 }}>
                <span className="field-label">Username</span>
                <input
                  type="text"
                  autoComplete="username"
                  autoFocus
                  value={username}
                  onChange={(e) => setUsername(e.target.value)}
                  className="input"
                />
              </label>
              <label style={{ display: 'block', marginBottom: 22 }}>
                <span className="field-label">Password</span>
                <input
                  type="password"
                  autoComplete="current-password"
                  value={password}
                  onChange={(e) => setPassword(e.target.value)}
                  className="input"
                />
              </label>

              {/* Honeypot: hidden from humans, left empty; bots that fill it are rejected. */}
              <div style={honeypotStyle} aria-hidden="true">
                <label>
                  Company
                  <input
                    type="text"
                    name="company"
                    tabIndex={-1}
                    autoComplete="off"
                    value={company}
                    onChange={(e) => setCompany(e.target.value)}
                  />
                </label>
              </div>
            </>
          ) : (
            <label style={{ display: 'block', marginBottom: 22 }}>
              <span className="field-label">Authentication code</span>
              <input
                type="text"
                inputMode="numeric"
                autoComplete="one-time-code"
                autoFocus
                placeholder="6-digit code"
                value={code}
                onChange={(e) => setCode(e.target.value)}
                className="input"
              />
              <span className="sans" style={{ display: 'block', marginTop: 8, color: 'var(--dim)', fontSize: '0.76rem' }}>
                Enter the code from your authenticator app.
              </span>
            </label>
          )}

          {(error || (stage === 'creds' && ssoError)) && (
            <p className="sans" style={{ margin: '0 0 14px', color: '#d98b84', fontSize: '0.85rem', textAlign: 'center', lineHeight: 1.5 }}>
              {error || ssoError}
            </p>
          )}

          <button
            type="submit"
            disabled={busy}
            className="btn btn-primary"
            style={{ display: 'block', width: '100%', borderRadius: 8, padding: 12, textAlign: 'center' }}
          >
            {busy ? 'Signing in…' : stage === 'totp' ? 'Verify' : 'Sign in'}
          </button>

          {/* SSO providers — only on the credentials step, only if any are enabled. */}
          {stage === 'creds' && providers.length > 0 && (
            <div style={{ marginTop: 20 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, margin: '0 0 16px', color: 'var(--dim)' }}>
                <span style={{ flex: 1, height: 1, background: 'var(--line)' }} />
                <span className="sans" style={{ fontSize: '0.72rem', letterSpacing: '0.14em', textTransform: 'uppercase' }}>or</span>
                <span style={{ flex: 1, height: 1, background: 'var(--line)' }} />
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                {providers.map((p) => (
                  <button
                    key={p.id}
                    type="button"
                    onClick={() => startSso(p)}
                    className="btn"
                    style={{
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'center',
                      gap: 10,
                      width: '100%',
                      borderRadius: 8,
                      padding: 11,
                      border: '1px solid var(--line)',
                      background: 'rgba(255,255,255,0.04)',
                      color: 'var(--ink)',
                    }}
                  >
                    <span style={{ display: 'inline-flex', width: 18, height: 18 }}>
                      <ProviderIcon icon={p.icon} size={18} />
                    </span>
                    Continue with {p.name}
                  </button>
                ))}
              </div>
            </div>
          )}

          <p className="sans" style={{ margin: '16px 0 0', textAlign: 'center', color: 'var(--dim)', fontSize: '0.76rem' }}>
            Protected area — not indexed. Sessions expire after 1 day.
          </p>
        </form>
        <p style={{ textAlign: 'center', margin: '20px 0 0' }}>
          <Link to="/" className="sans" style={{ color: 'var(--accent)', fontSize: '0.84rem', textDecoration: 'none' }}>
            ← Back to site
          </Link>
        </p>
      </div>
    </main>
  )
}
