import { useEffect, useMemo, useState } from 'react'
import { Loader2, Save, Shield } from 'lucide-react'
import { cn } from '@/lib/utils'
import { toast } from '@/lib/toast'
import { useAuthStore } from '@/store/authStore'
import { accountSecurityApi, type SessionPolicyResponse } from '@/api/accountSecurity'
import { RevokeSessionsModal } from '@/components/account/RevokeSessionsModal'

type Preset = 'strict' | 'standard' | 'custom'

const PRESETS: Record<Exclude<Preset, 'custom'>, { idle: number; absolute: number; label: string; sub: string }> = {
  strict: { idle: 4320, absolute: 20160, label: 'Strict', sub: '3 days idle · 14 days absolute' },
  standard: { idle: 10080, absolute: 43200, label: 'Standard', sub: '7 days idle · 30 days absolute' },
}

function detectPreset(idle: number, absolute: number): Preset {
  if (idle === PRESETS.strict.idle && absolute === PRESETS.strict.absolute) return 'strict'
  if (idle === PRESETS.standard.idle && absolute === PRESETS.standard.absolute) return 'standard'
  return 'custom'
}

function relativeFromNow(iso: string | null): string {
  if (!iso) return 'unknown'
  const diffMs = Date.now() - new Date(iso).getTime()
  const m = Math.round(diffMs / 60_000)
  if (m < 1) return 'just now'
  if (m < 60) return `${m}m ago`
  const h = Math.round(m / 60)
  if (h < 24) return `${h}h ago`
  const d = Math.round(h / 24)
  if (d < 30) return `${d}d ago`
  return new Date(iso).toLocaleDateString()
}

export default function AccountSecuritySettingsPage() {
  const currentUserId = useAuthStore((s) => s.user?.id) ?? null

  const [data, setData] = useState<SessionPolicyResponse | null>(null)
  const [loading, setLoading] = useState(true)
  const [preset, setPreset] = useState<Preset>('strict')
  const [idleMin, setIdleMin] = useState<string>('')
  const [absMin, setAbsMin] = useState<string>('')
  const [saving, setSaving] = useState(false)
  const [success, setSuccess] = useState(false)
  const [modalScope, setModalScope] = useState<'all' | 'others' | null>(null)

  useEffect(() => {
    void load()
  }, [])

  const load = async () => {
    setLoading(true)
    try {
      const res = await accountSecurityApi.get()
      setData(res)
      const eff = res
      const detected = detectPreset(eff.effective_idle_minutes, eff.effective_absolute_minutes)
      setPreset(detected)
      setIdleMin(String(eff.effective_idle_minutes))
      setAbsMin(String(eff.effective_absolute_minutes))
    } catch {
      toast.error('Could not load security settings')
    } finally {
      setLoading(false)
    }
  }

  const customDisabled = preset !== 'custom'

  // Sync the inputs to the chosen preset so the visible values track the radio.
  const handlePresetChange = (next: Preset) => {
    setPreset(next)
    if (next === 'strict') {
      setIdleMin(String(PRESETS.strict.idle))
      setAbsMin(String(PRESETS.strict.absolute))
    } else if (next === 'standard') {
      setIdleMin(String(PRESETS.standard.idle))
      setAbsMin(String(PRESETS.standard.absolute))
    }
  }

  const validation = useMemo(() => {
    if (!data) return { idleErr: null, absErr: null, ok: false }
    const idle = parseInt(idleMin, 10)
    const abs = parseInt(absMin, 10)
    let idleErr: string | null = null
    let absErr: string | null = null
    if (!Number.isFinite(idle)) idleErr = 'Required'
    else if (idle < data.idle_minutes_min || idle > data.idle_minutes_max) {
      idleErr = `Between ${data.idle_minutes_min} and ${data.idle_minutes_max}`
    }
    if (!Number.isFinite(abs)) absErr = 'Required'
    else if (abs < data.absolute_minutes_min || abs > data.absolute_minutes_max) {
      absErr = `Between ${data.absolute_minutes_min} and ${data.absolute_minutes_max}`
    }
    if (!idleErr && !absErr && idle > abs) {
      idleErr = 'Idle cannot exceed absolute'
    }
    return { idleErr, absErr, ok: !idleErr && !absErr }
  }, [data, idleMin, absMin])

  const handleSave = async () => {
    if (!validation.ok || !data) return
    setSaving(true)
    setSuccess(false)
    try {
      const body =
        preset === 'custom'
          ? { idle_minutes: parseInt(idleMin, 10), absolute_minutes: parseInt(absMin, 10) }
          : preset === 'strict'
            ? { idle_minutes: PRESETS.strict.idle, absolute_minutes: PRESETS.strict.absolute }
            : { idle_minutes: PRESETS.standard.idle, absolute_minutes: PRESETS.standard.absolute }
      const updated = await accountSecurityApi.update(body)
      setData(updated)
      setSuccess(true)
      setTimeout(() => setSuccess(false), 3000)
    } catch {
      // Global axios interceptor surfaces 422 via toast.
    } finally {
      setSaving(false)
    }
  }

  const handleRevokeConfirm = async () => {
    if (!modalScope) return
    const scope = modalScope
    try {
      const res = await accountSecurityApi.revokeSessions(scope)
      toast.success(`Signed out ${res.revoked_count} sessions`)
      setModalScope(null)
      if (scope === 'all') {
        // Per plan §4.8 D4: small delay so the user sees the toast,
        // then clear local state and redirect to /login.
        setTimeout(() => {
          localStorage.removeItem('access_token')
          localStorage.removeItem('refresh_token')
          useAuthStore.getState().logout()
          window.location.href = '/login'
        }, 1500)
      } else {
        // scope=others: reload to reflect the new (shorter) active-users list.
        await load()
      }
    } catch {
      // global handler
    }
  }

  if (loading || !data) {
    return (
      <div className="flex items-center justify-center py-20">
        <Loader2 className="animate-spin text-primary" size={24} />
      </div>
    )
  }

  const activeUserCount = data.active_users.length
  const solo = activeUserCount <= 1

  return (
    <div className="max-w-2xl mx-auto py-8 px-6 space-y-6">
      <div className="flex items-center gap-3">
        <Shield size={20} className="text-primary" />
        <h1 className="text-xl font-heading font-bold text-foreground">Session Security</h1>
      </div>
      <p className="text-sm text-muted-foreground">
        Control how long sessions can last before users must sign in again.
      </p>

      {/* ── Policy card ────────────────────────────────────────────────── */}
      <div className="card-flat rounded-2xl p-6 space-y-5">
        <fieldset className="space-y-3">
          <legend className="text-sm font-medium text-foreground mb-1">Policy</legend>

          {(['strict', 'standard', 'custom'] as const).map((p) => {
            const isSelected = preset === p
            const labels = p === 'custom'
              ? { label: 'Custom', sub: 'Set your own idle and absolute windows below' }
              : PRESETS[p]
            return (
              <label
                key={p}
                className={cn(
                  'flex items-start gap-3 rounded-lg border p-3 cursor-pointer transition-colors',
                  isSelected
                    ? 'border-primary/40 bg-primary/[0.06]'
                    : 'border-border hover:bg-card-hover',
                )}
              >
                <input
                  type="radio"
                  name="preset"
                  value={p}
                  checked={isSelected}
                  onChange={() => handlePresetChange(p)}
                  className="mt-0.5"
                />
                <div className="flex-1">
                  <div className="text-sm font-medium text-foreground">{labels.label}</div>
                  <div className="text-xs text-muted-foreground mt-0.5">{labels.sub}</div>
                </div>
              </label>
            )
          })}
        </fieldset>

        {/* Custom inputs — always visible, disabled outside Custom */}
        <div className="grid grid-cols-2 gap-3">
          <div>
            <label className="font-sans text-xs uppercase tracking-widest text-muted-foreground block mb-1.5">
              Idle minutes
            </label>
            <input
              type="number"
              value={idleMin}
              onChange={(e) => setIdleMin(e.target.value)}
              disabled={customDisabled}
              min={data.idle_minutes_min}
              max={data.idle_minutes_max}
              className={cn(
                'w-full rounded-xl border bg-card text-foreground text-sm px-4 py-2.5',
                'focus:outline-hidden focus:border-primary/30',
                'disabled:opacity-50 disabled:cursor-not-allowed',
                validation.idleErr && !customDisabled && 'border-danger/50',
              )}
              style={{
                borderColor:
                  validation.idleErr && !customDisabled ? undefined : 'var(--color-border-default)',
              }}
            />
            <p className="text-[11px] text-muted-foreground mt-1">
              {validation.idleErr && !customDisabled
                ? validation.idleErr
                : `Between ${data.idle_minutes_min} and ${data.idle_minutes_max} min`}
            </p>
          </div>
          <div>
            <label className="font-sans text-xs uppercase tracking-widest text-muted-foreground block mb-1.5">
              Absolute minutes
            </label>
            <input
              type="number"
              value={absMin}
              onChange={(e) => setAbsMin(e.target.value)}
              disabled={customDisabled}
              min={data.absolute_minutes_min}
              max={data.absolute_minutes_max}
              className={cn(
                'w-full rounded-xl border bg-card text-foreground text-sm px-4 py-2.5',
                'focus:outline-hidden focus:border-primary/30',
                'disabled:opacity-50 disabled:cursor-not-allowed',
                validation.absErr && !customDisabled && 'border-danger/50',
              )}
              style={{
                borderColor:
                  validation.absErr && !customDisabled ? undefined : 'var(--color-border-default)',
              }}
            />
            <p className="text-[11px] text-muted-foreground mt-1">
              {validation.absErr && !customDisabled
                ? validation.absErr
                : `Between ${data.absolute_minutes_min} and ${data.absolute_minutes_max} min`}
            </p>
          </div>
        </div>

        <div className="flex items-center gap-3 pt-2">
          <button
            type="button"
            onClick={handleSave}
            disabled={saving || !validation.ok}
            className="bg-primary text-white font-semibold text-sm rounded-lg px-5 py-2.5 hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-40 flex items-center gap-2"
          >
            {saving ? <Loader2 size={14} className="animate-spin" /> : <Save size={14} />}
            Save Policy
          </button>
          {success && <span className="text-sm text-emerald-400">Settings saved</span>}
        </div>

        <p className="text-xs text-muted-foreground border-t border-border pt-3">
          New policy applies the next time each person signs in. Use{' '}
          <span className="font-medium text-foreground">Active sessions</span> below to force it
          immediately.
        </p>
      </div>

      {/* ── Active sessions card ───────────────────────────────────────── */}
      <div className="card-flat rounded-2xl p-6 space-y-4">
        <div>
          <h2 className="text-sm font-medium text-foreground">Active sessions</h2>
          <p className="text-xs text-muted-foreground mt-1">
            {solo
              ? 'Only you are signed in to this account.'
              : `${activeUserCount} people are signed in to this account.`}
          </p>
        </div>

        <ul className="space-y-2">
          {data.active_users.map((u) => {
            const isMe = u.user_id === currentUserId
            return (
              <li
                key={u.user_id}
                className="flex items-center gap-3 rounded-lg border border-border bg-card px-3 py-2"
              >
                <div className="min-w-0 flex-1">
                  <div className="flex items-center gap-2 text-sm font-medium text-foreground">
                    <span className="truncate">{u.name}</span>
                    {isMe && (
                      <span className="text-[10px] uppercase tracking-wider text-muted-foreground">
                        (you)
                      </span>
                    )}
                  </div>
                  <div className="text-xs text-muted-foreground truncate">
                    {u.email} · last signed in {relativeFromNow(u.last_login_at)}
                  </div>
                </div>
              </li>
            )
          })}
        </ul>

        <div className="flex flex-wrap gap-2 pt-2">
          {!solo && (
            <button
              type="button"
              onClick={() => setModalScope('others')}
              className="rounded-md border border-border bg-transparent px-3 py-1.5 text-sm font-medium text-foreground hover:bg-card-hover"
            >
              Sign out everyone except me
            </button>
          )}
          <button
            type="button"
            onClick={() => setModalScope('all')}
            className="rounded-md border border-danger/40 bg-danger/10 px-3 py-1.5 text-sm font-medium text-danger hover:bg-danger/15"
          >
            {solo ? 'Sign me out everywhere' : 'Sign me out and everyone else'}
          </button>
        </div>
      </div>

      <RevokeSessionsModal
        isOpen={modalScope !== null}
        scope={modalScope ?? 'others'}
        activeUserCount={activeUserCount}
        onClose={() => setModalScope(null)}
        onConfirm={handleRevokeConfirm}
      />
    </div>
  )
}
