import { useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { Plus, Trash2, UserCheck, Server as ServerIcon, Lock, Eye, EyeOff, Loader2, X } from '../../../lib/icons'
import { Section, Row } from '../_ui'
import { jellyfinClient, getKnownServers, getStoredAuth, removeKnownServer } from '../../../api/jellyfin'
import type { AuthState as PrevAuth } from '../../../api/types'
import { toast } from '../../../stores/toast-store'
import type { AuthState } from '../../../api/types'

/**
 * Multi-server picker. Lists every server the user has signed into and
 * lets them switch active server with one click, prune the list, or add
 * a new one inline. Activating just rewrites `jf_auth` + reloads;
 * tokens for each server are kept in the encrypted servers list.
 */
export function ServersSection() {
  const [knownTick, setKnownTick] = useState(0) // force re-read after mutate
  const known = getKnownServers()
  const current = getStoredAuth()
  const [adding, setAdding] = useState(false)

  function bust() {
    setKnownTick(t => t + 1)
  }
  void knownTick

  function activate(s: AuthState) {
    jellyfinClient.activateServer(s)
    window.location.reload()
  }

  function forget(s: AuthState) {
    if (!confirm(`Forget ${labelFor(s)}? You'll need to sign in again to use it.`)) return
    removeKnownServer({ serverUrl: s.serverUrl, userId: s.userId })
    bust()
  }

  return (
    <Section
      id="servers"
      title="Servers"
      description="Sign in to more than one Jellyfin server and switch between them without re-entering credentials"
    >
      {known.map(s => {
        const isActive = !!current && current.serverUrl === s.serverUrl && current.userId === s.userId
        return (
          <Row key={s.serverUrl + s.userId} label={labelFor(s)} hint={isActive ? 'Active' : hostOf(s.serverUrl)}>
            <div className="flex items-center gap-1.5">
              {!isActive && (
                <button
                  onClick={() => activate(s)}
                  className="inline-flex items-center gap-1.5 h-9 px-3 rounded-md text-[12px] font-medium bg-elevated/60 text-text-2 border border-border hover:border-border-hover hover:text-text-1 transition-all duration-150 focus-ring"
                >
                  <UserCheck size={13} stroke={2} />
                  Use
                </button>
              )}
              {isActive && (
                <span className="inline-flex items-center gap-1.5 h-9 px-3 rounded-md text-[11.5px] font-medium text-accent border border-accent/30 bg-accent/10">
                  Active
                </span>
              )}
              {!isActive && (
                <button
                  onClick={() => forget(s)}
                  title="Forget this server"
                  aria-label="Forget this server"
                  className="w-9 h-9 grid place-items-center rounded-md text-text-3 hover:text-error hover:bg-error/8 transition-colors focus-ring"
                >
                  <Trash2 size={13} stroke={2} />
                </button>
              )}
            </div>
          </Row>
        )
      })}
      <Row label="Add another server" hint="Sign in to a second Jellyfin server">
        <button
          onClick={() => setAdding(true)}
          className="inline-flex items-center gap-1.5 h-9 px-3 rounded-md text-[12px] font-medium bg-elevated/60 text-text-2 border border-border hover:border-border-hover hover:text-text-1 transition-all duration-150 focus-ring"
        >
          <Plus size={13} stroke={2} />
          Add
        </button>
      </Row>

      <AnimatePresence>
        {adding && <AddServerModal onClose={() => setAdding(false)} onAdded={bust} />}
      </AnimatePresence>
    </Section>
  )
}

function labelFor(s: AuthState): string {
  if (s.userName) return `${s.userName} on ${hostOf(s.serverUrl)}`
  return hostOf(s.serverUrl)
}

function hostOf(url: string): string {
  try {
    return new URL(url).host
  } catch {
    return url
  }
}

function AddServerModal({ onClose, onAdded }: { onClose: () => void; onAdded: () => void }) {
  const [serverUrl, setServerUrl] = useState('')
  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')
  const [showPassword, setShowPassword] = useState(false)
  const [error, setError] = useState('')
  const [loading, setLoading] = useState(false)

  async function submit(e: React.FormEvent) {
    e.preventDefault()
    if (!serverUrl.trim() || !username.trim()) {
      setError('Server URL and username are required')
      return
    }
    setError('')
    setLoading(true)
    // Snapshot the active server so we can put the global API back if
    // the login attempt against the new URL fails. Without this rollback
    // the rest of the app would be left talking to the new (unauthed)
    // server while the modal sits there with an error message.
    const previous: PrevAuth | null = getStoredAuth()
    try {
      jellyfinClient.connect(serverUrl.trim())
      await jellyfinClient.login(username.trim(), password)
      toast('Server added', 'success')
      onAdded()
      window.location.reload()
    } catch (err: any) {
      if (previous) jellyfinClient.activateServer(previous)
      setError(err?.response?.data?.message || err?.message || 'Could not connect to that server.')
      setLoading(false)
    }
  }

  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
      transition={{ duration: 0.18 }}
      className="fixed inset-0 z-toast grid place-items-center bg-black/65 backdrop-blur-sm"
      onClick={onClose}
    >
      <motion.form
        initial={{ y: 16, scale: 0.96 }}
        animate={{ y: 0, scale: 1 }}
        exit={{ y: 16, scale: 0.96 }}
        transition={{ duration: 0.28, ease: [0.16, 1, 0.3, 1] }}
        onClick={e => e.stopPropagation()}
        onSubmit={submit}
        className="bg-[#0c0a08]/97 backdrop-blur-2xl border border-white/14 rounded-2xl w-[420px] max-w-[88vw] p-6 shadow-[0_30px_80px_-20px_rgba(0,0,0,0.85)]"
      >
        <header className="flex items-center justify-between mb-5">
          <h2 className="font-display text-lg font-bold text-white tracking-tight">Add a server</h2>
          <button
            type="button"
            onClick={onClose}
            className="w-8 h-8 grid place-items-center rounded-full text-white/70 hover:text-white hover:bg-white/10 transition-colors focus-ring"
            aria-label="Close"
          >
            <X size={15} />
          </button>
        </header>
        <div className="space-y-3">
          <Field label="Server URL" icon={ServerIcon} value={serverUrl} onChange={setServerUrl} placeholder="https://jellyfin.example.com" type="url" autoFocus />
          <Field label="Username" value={username} onChange={setUsername} placeholder="Your username" />
          <Field
            label="Password"
            icon={Lock}
            type={showPassword ? 'text' : 'password'}
            value={password}
            onChange={setPassword}
            placeholder="Password"
            trailing={
              <button
                type="button"
                onClick={() => setShowPassword(s => !s)}
                className="text-text-4 hover:text-text-2 transition-colors p-1 rounded-md focus-ring"
                aria-label={showPassword ? 'Hide password' : 'Show password'}
              >
                {showPassword ? <EyeOff size={14} /> : <Eye size={14} />}
              </button>
            }
          />
        </div>
        {error && (
          <p className="mt-3 text-[12px] text-error/95 leading-relaxed">{error}</p>
        )}
        <button
          type="submit"
          disabled={loading}
          className="mt-5 w-full h-10 inline-flex items-center justify-center gap-2 rounded-lg bg-accent hover:bg-accent-hover text-void text-[13px] font-semibold tracking-tight disabled:opacity-50 disabled:cursor-not-allowed focus-ring"
        >
          {loading ? (
            <>
              <Loader2 size={14} className="animate-spin" />
              Connecting...
            </>
          ) : (
            'Add server'
          )}
        </button>
        <p className="mt-3 text-[11px] text-text-4 leading-snug">
          Adding a server switches to it. Your current server will stay signed in and selectable.
        </p>
      </motion.form>
    </motion.div>
  )
}

function Field({
  label,
  icon: Icon,
  value,
  onChange,
  placeholder,
  type = 'text',
  autoFocus,
  trailing,
}: {
  label: string
  icon?: typeof ServerIcon
  value: string
  onChange: (v: string) => void
  placeholder?: string
  type?: string
  autoFocus?: boolean
  trailing?: React.ReactNode
}) {
  return (
    <label className="block">
      <span className="block text-[10.5px] uppercase tracking-[0.16em] font-semibold text-text-3 mb-1.5">{label}</span>
      <div className="relative">
        {Icon && (
          <Icon
            size={13}
            className="absolute left-3 top-1/2 -translate-y-1/2 text-text-4 pointer-events-none"
          />
        )}
        <input
          type={type}
          value={value}
          onChange={e => onChange(e.target.value)}
          placeholder={placeholder}
          autoFocus={autoFocus}
          className={`w-full h-10 ${Icon ? 'pl-9' : 'pl-3'} ${trailing ? 'pr-10' : 'pr-3'} bg-void/55 rounded-md text-[12.5px] text-text-1 placeholder:text-text-4 border border-border focus:outline-none focus:border-accent/50 focus:ring-2 focus:ring-accent/20 transition-all`}
        />
        {trailing && <div className="absolute right-2 top-1/2 -translate-y-1/2">{trailing}</div>}
      </div>
    </label>
  )
}
