// frontend\src\pages\devices\EditDeviceModal.tsx

import { useState, type ComponentProps, type FormEvent } from 'react'
import { DialogTitle } from '@headlessui/react'
import { XMarkIcon } from '@heroicons/react/24/outline'
import {
  ChatBubbleLeftEllipsisIcon,
  CheckIcon,
  IdentificationIcon,
  MapPinIcon,
  PencilSquareIcon,
  PlusCircleIcon,
  VideoCameraIcon,
  WrenchScrewdriverIcon,
} from '@heroicons/react/20/solid'
import Modal from '../../components/Modal'
import Journal from '../../components/Journal'
import Button from '../../components/Button'
import LoadingSpinner from '../../components/LoadingSpinner'
import type {
  Device,
  DeviceHistoryChange,
  DeviceHistoryEntry,
} from '../../components/types'
import DeviceFormFields, {
  SectionHeader,
  sectionClassName,
} from './DeviceFormFields'
import DeviceModalTabs, { type DeviceModalTabId } from './DeviceModalTabs'

type EditDeviceModalProps = {
  open: boolean
  setOpen: (open: boolean) => void
  isSaving: boolean
  error: string | null
  device: Device | null
  devices: Device[]
  relatedDeviceIds: string[]
  onToggleRelatedDevice: (deviceId: string) => void
  onSubmit: (event: FormEvent<HTMLFormElement>) => void
  deviceHistory: DeviceHistoryEntry[]
  isHistoryLoading: boolean
  historyError: string | null
  isJournalSubmitting?: boolean
  onJournalEntrySubmit?: (content: string) => void | Promise<void>
  onJournalEntryUpdate?: (itemId: string | number, content: string) => void | Promise<void>
}

type JournalItems = ComponentProps<typeof Journal>['items']

const editDeviceTabs = [
  {
    id: 'masterData' as const,
    name: 'Stammdaten',
    icon: IdentificationIcon,
  },
  {
    id: 'location' as const,
    name: 'Standort',
    icon: MapPinIcon,
  },
  {
    id: 'accessories' as const,
    name: 'Zubehör',
    icon: WrenchScrewdriverIcon,
  },
  {
    id: 'history' as const,
    name: 'Journal',
    icon: ChatBubbleLeftEllipsisIcon,
  },
]

function formatHistoryDate(value: string) {
  try {
    return new Intl.DateTimeFormat('de-DE', {
      dateStyle: 'short',
      timeStyle: 'short',
    }).format(new Date(value))
  } catch {
    return value
  }
}

function formatHistoryChange(change: DeviceHistoryChange) {
  const oldValue = change.oldValue || '—'
  const newValue = change.newValue || '—'

  return `${change.label}: ${oldValue} → ${newValue}`
}

function getTabForInvalidField(fieldName: string): DeviceModalTabId {
  if (
    [
      'inventoryNumber',
      'manufacturer',
      'model',
      'serialNumber',
      'macAddress',
      'ipAddress',
      'firmwareVersion',
      'loanStatus',
    ].includes(fieldName)
  ) {
    return 'masterData'
  }

  if (['location', 'comment', 'isBaoDevice'].includes(fieldName)) {
    return 'location'
  }

  return 'accessories'
}

function classNames(...classes: Array<string | false | null | undefined>) {
  return classes.filter(Boolean).join(' ')
}

export default function EditDeviceModal({
  open,
  setOpen,
  isSaving,
  error,
  device,
  devices,
  relatedDeviceIds,
  onToggleRelatedDevice,
  onSubmit,
  deviceHistory,
  isHistoryLoading,
  historyError,
  isJournalSubmitting = false,
  onJournalEntrySubmit,
  onJournalEntryUpdate,
}: EditDeviceModalProps) {
  const [activeTab, setActiveTab] = useState<DeviceModalTabId>('masterData')

  function handleOpenChange(nextOpen: boolean) {
    if (!nextOpen && isSaving) {
      return
    }

    setOpen(nextOpen)

    if (!nextOpen) {
      setActiveTab('masterData')
    }
  }

  function handleInvalid(event: FormEvent<HTMLFormElement>) {
    const target = event.target as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement

    setActiveTab(getTabForInvalidField(target.name))
  }

  function handleFormSubmit(event: FormEvent<HTMLFormElement>) {
    if (activeTab === 'history') {
      event.preventDefault()
      return
    }

    onSubmit(event)
  }

  const historyFeedItems: JournalItems = device
    ? deviceHistory.map((entry) => {
        const journalChange = entry.changes.find((change) => change.field === 'journal')
        const isJournalEntry = entry.action === 'journal' || journalChange !== undefined

        return {
          id: entry.id,
          type: isJournalEntry
            ? ('journal' as const)
            : entry.action === 'created'
              ? ('created' as const)
              : ('edited' as const),
          person: {
            name: entry.userDisplayName || 'Unbekannt',
          },
          content: isJournalEntry
            ? journalChange?.newValue || 'hat einen Journal-Eintrag hinzugefügt.'
            : entry.action === 'created'
              ? 'hat das Gerät erstellt.'
              : entry.changes.length > 0
                ? `hat ${entry.changes.map(formatHistoryChange).join(', ')} geändert.`
                : 'hat das Gerät bearbeitet.',
          date: formatHistoryDate(entry.createdAt),
          datetime: entry.createdAt,
          editedDate:
            isJournalEntry && entry.updatedAt && entry.updatedAt !== entry.createdAt
              ? formatHistoryDate(entry.updatedAt)
              : undefined,
          editedDatetime:
            isJournalEntry && entry.updatedAt && entry.updatedAt !== entry.createdAt
              ? entry.updatedAt
              : undefined,
          canEdit: isJournalEntry && entry.canEdit,
          icon: isJournalEntry
            ? ChatBubbleLeftEllipsisIcon
            : entry.action === 'created'
              ? PlusCircleIcon
              : PencilSquareIcon,
          iconBackground: isJournalEntry
            ? 'bg-indigo-500'
            : entry.action === 'created'
              ? 'bg-green-500'
              : 'bg-blue-500',
        }
      })
    : []

  return (
    <Modal
      open={open && Boolean(device)}
      setOpen={handleOpenChange}
      zIndexClassName="z-[9999]"
      panelClassName="max-h-[calc(100dvh-2rem)] max-w-4xl bg-white dark:bg-gray-900"
    >
      <form
        key={device?.id ?? 'edit-device'}
        onSubmit={handleFormSubmit}
        onInvalidCapture={handleInvalid}
        className="flex h-[calc(100dvh-2rem)] max-h-[calc(100dvh-2rem)] flex-col"
      >
        <div className="flex items-start justify-between border-b border-gray-200 bg-gray-100 px-4 py-4 sm:px-6 dark:border-white/10 dark:bg-gray-800">
          <div>
            <DialogTitle className="text-base font-semibold text-gray-900 dark:text-white">
              Gerät bearbeiten
              {device && (
                <span className="ml-2 font-normal text-gray-500 dark:text-gray-400">
                  {[
                    device.inventoryNumber,
                    device.milestoneDisplayName,
                  ]
                    .filter(Boolean)
                    .join(' · ')}
                </span>
              )}
            </DialogTitle>

            <div className="mt-1 space-y-1">
              <p className="text-sm text-gray-500 dark:text-gray-400">
                Bearbeite Gerätedaten, Standort, Verleih-Status und Zubehör.
              </p>

              {device?.milestoneHardwareId && (
                <p className="flex items-center gap-1.5 text-xs text-indigo-600 dark:text-indigo-400">
                  <VideoCameraIcon aria-hidden="true" className="size-4 shrink-0" />
                  <span>
                    {device.milestoneSyncedAt
                      ? `Zuletzt mit Milestone synchronisiert: ${formatHistoryDate(device.milestoneSyncedAt)}`
                      : 'Noch nicht mit Milestone synchronisiert.'}
                  </span>
                </p>
              )}
            </div>
          </div>

          <Button
            type="button"
            variant="secondary"
            color="gray"
            size="sm"
            disabled={isSaving}
            onClick={() => handleOpenChange(false)}
          >
            <span className="sr-only">Schließen</span>
            <XMarkIcon aria-hidden="true" className="size-5" />
          </Button>
        </div>

        <DeviceModalTabs
          tabs={editDeviceTabs}
          activeTab={activeTab}
          onChange={setActiveTab}
        />

        {error && (
          <div className="mx-4 mt-4 rounded-md bg-red-50 p-4 text-sm text-red-700 sm:mx-6 dark:bg-red-900/30 dark:text-red-300">
            {error}
          </div>
        )}

        <div className="min-h-0 flex-1 overflow-y-auto px-4 py-6 sm:px-6">
          {activeTab === 'history' ? (
            <section className={classNames(sectionClassName, 'sm:col-span-6')}>
              <SectionHeader
                title="Bearbeitungsverlauf"
                description="Änderungen an diesem Gerät."
              />

              <div className="mt-6">
                {isHistoryLoading && (
                  <div className="flex min-h-24 items-center justify-center rounded-md border border-dashed border-gray-200 p-4 dark:border-white/10">
                    <LoadingSpinner
                      size="md"
                      label="Verlauf wird geladen..."
                      className="text-indigo-600 dark:text-indigo-400"
                    />
                  </div>
                )}

                {historyError && (
                  <div className="rounded-md bg-red-50 p-3 text-sm text-red-700 dark:bg-red-900/30 dark:text-red-300">
                    {historyError}
                  </div>
                )}

                {!isHistoryLoading && !historyError && (
                  <Journal
                    items={historyFeedItems}
                    showEntryForm
                    isSubmitting={isJournalSubmitting}
                    emptyText="Noch keine Änderungen erfasst."
                    placeholder="Journal-Eintrag zum Gerät hinzufügen..."
                    submitLabel="Eintrag hinzufügen"
                    onEntrySubmit={onJournalEntrySubmit}
                    onEntryUpdate={onJournalEntryUpdate}
                  />
                )}
              </div>
            </section>
          ) : (
            <DeviceFormFields
              open={open}
              activeTab={activeTab}
              device={device ?? undefined}
              devices={devices}
              relatedDeviceIds={relatedDeviceIds}
              onToggleRelatedDevice={onToggleRelatedDevice}
            />
          )}
        </div>

        <div className="flex justify-end gap-x-3 border-t border-gray-200 px-4 py-4 sm:px-6 dark:border-white/10">
          <Button
            type="button"
            variant="secondary"
            color="gray"
            disabled={isSaving}
            onClick={() => handleOpenChange(false)}
          >
            {activeTab === 'history' ? 'Schließen' : 'Abbrechen'}
          </Button>

          {activeTab !== 'history' && (
            <Button
              type="submit"
              color="indigo"
              isLoading={isSaving}
              leadingIcon={<CheckIcon aria-hidden="true" className="size-4" />}
            >
              Änderungen speichern
            </Button>
          )}
        </div>
      </form>
    </Modal>
  )
}