import { FormEvent, useEffect, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { baculaApi, BaculaClient, BaculaCapabilityHistory } from '@/api/bacula'

const backupTypeOptions = [
  { label: 'Files', value: 'files' },
  { label: 'Database', value: 'database' },
  { label: 'Application', value: 'application' },
  { label: 'Exchange', value: 'exchange' },
  { label: 'Mail', value: 'mail' },
]

function formatTimestamp(value?: string) {
  if (!value) {
    return 'Never'
  }
  const date = new Date(value)
  return date.toLocaleString()
}

export default function BaculaClientsPage() {
  const queryClient = useQueryClient()
  const { data: clients, isLoading, error } = useQuery({
    queryKey: ['bacula-clients'],
    queryFn: () => baculaApi.listClients(),
  })
  const [editingClientId, setEditingClientId] = useState<string | null>(null)
  const [selectedTypes, setSelectedTypes] = useState<string[]>([])
  const [notes, setNotes] = useState('')
  const [statusMessage, setStatusMessage] = useState('')

  const mutation = useMutation({
    mutationFn: ({ id, backupTypes, notes }: { id: string; backupTypes: string[]; notes: string }) =>
      baculaApi.updateCapabilities(id, { backup_types: backupTypes, notes }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['bacula-clients'] })
      setStatusMessage('Capability update requested. The agent will pull changes shortly.')
    },
    onError: () => {
      setStatusMessage('Failed to request capability update. Please try again.')
    },
  })

  const editingClient = (clients as BaculaClient[] | undefined)?.find((client: BaculaClient) => client.id === editingClientId) ?? null

  useEffect(() => {
    if (!editingClient) {
      setSelectedTypes([])
      setNotes('')
      return
    }

    setSelectedTypes(
      editingClient.pending_backup_types?.length
        ? editingClient.pending_backup_types
        : editingClient.backup_types
    )
    setNotes(editingClient.pending_notes ?? '')
  }, [editingClient])

  const toggleType = (type: string) => {
    setSelectedTypes((prev) =>
      prev.includes(type) ? prev.filter((value) => value !== type) : [...prev, type]
    )
  }

  const handleSubmit = (event: FormEvent) => {
    event.preventDefault()
    if (!editingClient) {
      return
    }

    mutation.mutate({ id: editingClient.id, backupTypes: selectedTypes, notes })
  }

  if (isLoading) {
    return <p className="text-white">Loading Bacula clients...</p>
  }

  if (error) {
    return <p className="text-red-400">Failed to load Bacula clients.</p>
  }

  return (
    <div className="space-y-6">
      <header>
        <h1 className="text-3xl font-bold text-white">Bacula Client Management</h1>
        <p className="text-sm text-text-secondary">Register agents, monitor their capabilities, and push updates.</p>
      </header>

      <section className="bg-card-dark border border-border-dark rounded-xl p-6 space-y-4">
        <div className="flex items-center justify-between">
          <div>
            <p className="text-sm font-semibold text-text-secondary">Edit capabilities</p>
            <p className="text-lg font-bold text-white">
              {editingClient ? editingClient.hostname : 'Select a client from the list'}
            </p>
          </div>
          {statusMessage && <p className="text-xs text-primary">{statusMessage}</p>}
        </div>

        <form className="space-y-4" onSubmit={handleSubmit}>
          <fieldset className="space-y-2">
            <legend className="text-sm font-semibold text-white">Backup types</legend>
            <div className="grid grid-cols-2 gap-2">
              {backupTypeOptions.map((option) => (
                <label
                  key={option.value}
                  className="flex items-center gap-2 rounded-lg border border-border-dark px-3 py-2 text-sm"
                >
                  <input
                    type="checkbox"
                    checked={selectedTypes.includes(option.value)}
                    onChange={() => toggleType(option.value)}
                    className="h-4 w-4 rounded border-border-dark text-primary focus:ring-primary"
                    disabled={!editingClient}
                  />
                  <span className="text-white">{option.label}</span>
                </label>
              ))}
            </div>
          </fieldset>

          <div className="space-y-2">
            <label className="text-sm font-semibold text-white" htmlFor="notes">
              Notes for agent
            </label>
            <textarea
              id="notes"
              rows={3}
              value={notes}
              onChange={(event) => setNotes(event.target.value)}
              className="w-full rounded-lg border border-border-dark bg-[#111a22] px-3 py-2 text-sm text-white placeholder:text-text-secondary focus:border-primary focus:outline-none"
              placeholder="Optional context for the capability update"
              disabled={!editingClient}
            />
          </div>

          <button
            type="submit"
            className="inline-flex items-center justify-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-semibold text-black"
            disabled={!editingClient || selectedTypes.length === 0 || mutation.isPending}
          >
            {mutation.isPending ? 'Requesting...' : 'Push capabilities'}
          </button>
        </form>
      </section>

      <section className="space-y-4">
        {(clients as BaculaClient[] | undefined)?.map((client: BaculaClient) => (
          <article key={client.id} className="rounded-xl border border-border-dark bg-card-dark p-5 text-sm text-white">
            <div className="flex flex-wrap items-center justify-between gap-4">
              <div>
                <p className="text-lg font-semibold text-white">{client.hostname}</p>
                <p className="text-xs text-text-secondary">{client.agent_version || 'Unknown version'}</p>
              </div>
              <div className="flex items-center gap-2">
                <span className="text-xs uppercase tracking-wide text-text-secondary">Status</span>
                <span className="text-sm font-semibold text-primary">{client.status}</span>
              </div>
              <button
                className="rounded-lg border border-border-dark px-3 py-1 text-xs font-semibold text-white"
                onClick={() => setEditingClientId(client.id)}
              >
                Edit capabilities
              </button>
            </div>

            <div className="mt-4 grid grid-cols-2 gap-4 text-xs">
              <div>
                <p className="text-[11px] uppercase tracking-wide text-text-secondary">Backup types</p>
                <p className="text-sm text-white">{client.backup_types.join(', ')}</p>
              </div>
              <div>
                <p className="text-[11px] uppercase tracking-wide text-text-secondary">Pending push</p>
                <p className="text-sm text-white">
                  {client.pending_backup_types?.length
                    ? client.pending_backup_types.join(', ')
                    : 'None'}
                </p>
              </div>
              <div>
                <p className="text-[11px] uppercase tracking-wide text-text-secondary">Last seen</p>
                <p className="text-sm text-white">{formatTimestamp(client.last_seen)}</p>
              </div>
              <div>
                <p className="text-[11px] uppercase tracking-wide text-text-secondary">Registered by</p>
                <p className="text-sm text-white">{client.registered_by}</p>
              </div>
            </div>

            <div className="mt-4 space-y-2 text-xs">
              <p className="text-[11px] uppercase tracking-wide text-text-secondary">Capability history</p>
              <ul className="space-y-1">
                {client.capability_history?.slice(0, 3).map((history: BaculaCapabilityHistory) => (
                  <li key={`${client.id}-${history.requested_at}`} className="flex justify-between text-white">
                    <span>
                      {history.source.toUpperCase()} • {history.backup_types.join(', ')}
                    </span>
                    <span className="text-text-secondary">{formatTimestamp(history.requested_at)}</span>
                  </li>
                ))}
                {!client.capability_history?.length && (
                  <li className="text-text-secondary">No history yet.</li>
                )}
              </ul>
            </div>
          </article>
        ))}
      </section>
    </div>
  )
}
