import React, { useEffect, useState, useRef } from 'react';
import { KanbanComponent } from '@syncfusion/ej2-react-kanban';
import { fetchClients, updateClientGroup } from './apiClients';
import { fetchGroups, createGroup, deleteGroup, renameGroup } from './apiGroups';
import type { Client } from './apiClients';
import type { KanbanComponent as KanbanComponentType } from '@syncfusion/ej2-react-kanban';
import { DialogComponent } from '@syncfusion/ej2-react-popups';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { TextBoxComponent } from '@syncfusion/ej2-react-inputs';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import type { ChangedEventArgs as TextBoxChangedArgs } from '@syncfusion/ej2-react-inputs';
import type { ChangeEventArgs as DropDownChangeArgs } from '@syncfusion/ej2-react-dropdowns';
import { useToast } from './components/ToastProvider';
import { L10n } from '@syncfusion/ej2-base';

interface KanbanClient extends Client {
  Id: string;
  Status: string; // Raumgruppe (Gruppenname)
  Summary: string; // Anzeigename
}

interface Group {
  id: number;
  name: string;
  // weitere Felder möglich
}

interface KanbanDragEventArgs {
  element: HTMLElement | HTMLElement[];
  data: KanbanClient | KanbanClient[];
  event?: { event?: MouseEvent };
  [key: string]: unknown;
}

interface KanbanComponentWithClear extends KanbanComponentType {
  clearSelection: () => void;
}

const de = {
  title: 'Gruppen',
  newGroup: 'Neue Raumgruppe',
  renameGroup: 'Gruppe umbenennen',
  deleteGroup: 'Gruppe löschen',
  add: 'Hinzufügen',
  cancel: 'Abbrechen',
  rename: 'Umbenennen',
  confirmDelete: 'Löschbestätigung',
  reallyDelete: (name: string) => `Möchten Sie die Gruppe <b>${name}</b> wirklich löschen?`,
  clientsMoved: 'Alle Clients werden nach "Nicht zugeordnet" verschoben.',
  groupCreated: 'Gruppe angelegt',
  groupDeleted: 'Gruppe gelöscht. Alle Clients wurden nach "Nicht zugeordnet" verschoben.',
  groupRenamed: 'Gruppe umbenannt',
  selectGroup: 'Gruppe wählen',
  newName: 'Neuer Name',
  warning: 'Achtung:',
  yesDelete: 'Ja, löschen',
};

L10n.load({
  de: {
    kanban: {
      items: 'Clients',
      addTitle: 'Neue Karte hinzufügen',
      editTitle: 'Karte bearbeiten',
      deleteTitle: 'Karte löschen',
      edit: 'Bearbeiten',
      delete: 'Löschen',
      save: 'Speichern',
      cancel: 'Abbrechen',
      yes: 'Ja',
      no: 'Nein',
      noCard: 'Keine Clients vorhanden',
    },
  },
});

const Infoscreen_groups: React.FC = () => {
  const toast = useToast();
  const [clients, setClients] = useState<KanbanClient[]>([]);
  const [groups, setGroups] = useState<{ keyField: string; headerText: string; id?: number }[]>([]);
  const [showDialog, setShowDialog] = useState(false);
  const [newGroupName, setNewGroupName] = useState('');
  const [draggedCard, setDraggedCard] = useState<{ id: string; fromColumn: string } | null>(null);
  const [renameDialog, setRenameDialog] = useState<{
    open: boolean;
    oldName: string;
    newName: string;
  }>({ open: false, oldName: '', newName: '' });
  const [deleteDialog, setDeleteDialog] = useState<{ open: boolean; groupName: string }>({
    open: false,
    groupName: '',
  });
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
  const kanbanRef = useRef<KanbanComponentType | null>(null); // Ref für Kanban

  // Lade Gruppen und Clients
  useEffect(() => {
    let groupMap: Record<number, string> = {};
    fetchGroups().then((groupData: Group[]) => {
      const kanbanGroups = groupData.map(g => ({
        keyField: g.name,
        headerText: g.name,
        id: g.id,
      }));
      setGroups(kanbanGroups);

      groupMap = Object.fromEntries(groupData.map(g => [g.id, g.name]));

      fetchClients().then(data => {
        setClients(
          data.map((c, i) => ({
            ...c,
            Id: c.uuid,
            Status:
              c.group_id === 1
                ? 'Nicht zugeordnet'
                : typeof c.group_id === 'number' && groupMap[c.group_id]
                  ? groupMap[c.group_id]
                  : 'Nicht zugeordnet',
            Summary: c.description || `Client ${i + 1}`,
          }))
        );
      });
    });
  }, []);

  // Neue Gruppe anlegen (persistiert per API)
  const handleAddGroup = async () => {
    if (!newGroupName.trim()) return;
    try {
      const newGroup = await createGroup(newGroupName);
      toast.show({
        content: de.groupCreated,
        cssClass: 'e-toast-success',
        timeOut: 5000,
        showCloseButton: false,
      });
      setGroups([
        ...groups,
        { keyField: newGroup.name, headerText: newGroup.name, id: newGroup.id },
      ]);
      setNewGroupName('');
      setShowDialog(false);
      
      // Update group order to include the new group
      try {
        const orderResponse = await fetch('/api/groups/order');
        if (orderResponse.ok) {
          const orderData = await orderResponse.json();
          const currentOrder = orderData.order || [];
          // Add new group ID to the end if not already present
          if (!currentOrder.includes(newGroup.id)) {
            await fetch('/api/groups/order', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ order: [...currentOrder, newGroup.id] }),
            });
          }
        }
      } catch (err) {
        console.error('Failed to update group order:', err);
      }
    } catch (err) {
      toast.show({
        content: (err as Error).message,
        cssClass: 'e-toast-danger',
        timeOut: 0,
        showCloseButton: true,
      });
    }
  };

  // Löschen einer Gruppe
  const handleDeleteGroup = async (groupName: string) => {
    try {
      // Find the group ID before deleting
      const groupToDelete = groups.find(g => g.headerText === groupName);
      const deletedGroupId = groupToDelete?.id;
      
      // Clients der Gruppe in "Nicht zugeordnet" verschieben
      const groupClients = clients.filter(c => c.Status === groupName);
      if (groupClients.length > 0) {
        // Ermittle die ID der Zielgruppe "Nicht zugeordnet"
        const target = groups.find(g => g.headerText === 'Nicht zugeordnet');
        if (!target || !target.id) throw new Error('Zielgruppe "Nicht zugeordnet" nicht gefunden');
        await updateClientGroup(
          groupClients.map(c => c.Id),
          target.id
        );
      }
      await deleteGroup(groupName);
      toast.show({
        content: de.groupDeleted,
        cssClass: 'e-toast-success',
        timeOut: 5000,
        showCloseButton: false,
      });
      
      // Update group order to remove the deleted group
      if (deletedGroupId) {
        try {
          const orderResponse = await fetch('/api/groups/order');
          if (orderResponse.ok) {
            const orderData = await orderResponse.json();
            const currentOrder = orderData.order || [];
            // Remove deleted group ID from order
            const updatedOrder = currentOrder.filter((id: number) => id !== deletedGroupId);
            await fetch('/api/groups/order', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ order: updatedOrder }),
            });
          }
        } catch (err) {
          console.error('Failed to update group order:', err);
        }
      }
      
      // Gruppen und Clients neu laden
      const groupData = await fetchGroups();
      const groupMap = Object.fromEntries(groupData.map((g: Group) => [g.id, g.name]));
      setGroups(groupData.map((g: Group) => ({ keyField: g.name, headerText: g.name, id: g.id })));
      const data = await fetchClients();
      setClients(
        data.map((c, i) => ({
          ...c,
          Id: c.uuid,
          Status:
            typeof c.group_id === 'number' && groupMap[c.group_id]
              ? groupMap[c.group_id]
              : 'Nicht zugeordnet',
          Summary: c.description || `Client ${i + 1}`,
        }))
      );
    } catch (err) {
      toast.show({
        content: (err as Error).message,
        cssClass: 'e-toast-danger',
        timeOut: 0,
        showCloseButton: true,
      });
    }
    setDeleteDialog({ open: false, groupName: '' });
  };

  // Umbenennen einer Gruppe
  const handleRenameGroup = async () => {
    try {
      await renameGroup(renameDialog.oldName, renameDialog.newName);
      toast.show({
        content: de.groupRenamed,
        cssClass: 'e-toast-success',
        timeOut: 5000,
        showCloseButton: false,
      });
      // Gruppen und Clients neu laden
      const groupData = await fetchGroups();
      const groupMap = Object.fromEntries(groupData.map((g: Group) => [g.id, g.name]));
      setGroups(groupData.map((g: Group) => ({ keyField: g.name, headerText: g.name, id: g.id })));
      const data = await fetchClients();
      setClients(
        data.map((c, i) => ({
          ...c,
          Id: c.uuid,
          Status:
            typeof c.group_id === 'number' && groupMap[c.group_id]
              ? groupMap[c.group_id]
              : 'Nicht zugeordnet',
          Summary: c.description || `Client ${i + 1}`,
        }))
      );
    } catch (err) {
      toast.show({
        content: (err as Error).message,
        cssClass: 'e-toast-danger',
        timeOut: 0,
        showCloseButton: true,
      });
    }
    setRenameDialog({ open: false, oldName: '', newName: '' });
  };

  const handleDragStart = (args: KanbanDragEventArgs) => {
    const element = Array.isArray(args.element) ? args.element[0] : args.element;
    const cardId = element.getAttribute('data-id');
    const fromColumn = element.getAttribute('data-key');
    setDraggedCard({ id: cardId || '', fromColumn: fromColumn || '' });
  };

  const handleCardDrop = async (args: KanbanDragEventArgs) => {
    if (!draggedCard) return;

    const mouseEvent = args.event?.event;
    let targetGroupName = '';

    if (mouseEvent && mouseEvent.clientX && mouseEvent.clientY) {
      const targetElement = document.elementFromPoint(mouseEvent.clientX, mouseEvent.clientY);
      const kanbanColumn =
        targetElement?.closest('[data-key]') || targetElement?.closest('.e-content-row');
      if (kanbanColumn) {
        const columnKey = kanbanColumn.getAttribute('data-key');
        if (columnKey) {
          targetGroupName = columnKey;
        } else {
          const headerElement = kanbanColumn.querySelector('.e-header-text');
          targetGroupName = headerElement?.textContent?.trim() || '';
        }
      }
    }

    // Fallback
    if (!targetGroupName) {
      const targetElement = Array.isArray(args.element) ? args.element[0] : args.element;
      const cardWrapper = targetElement.closest('.e-card-wrapper');
      const contentRow = cardWrapper?.closest('.e-content-row');
      const headerText = contentRow?.querySelector('.e-header-text');
      targetGroupName = headerText?.textContent?.trim() || '';
    }

    if (!targetGroupName || targetGroupName === draggedCard.fromColumn) {
      setDraggedCard(null);
      return;
    }

    const dropped = Array.isArray(args.data) ? args.data : [args.data];
    const clientIds = dropped.map((card: KanbanClient) => card.Id);

    try {
      // Ermittle Zielgruppen-ID anhand des Namens
      const target = groups.find(g => g.headerText === targetGroupName);
      if (!target || !target.id) throw new Error('Zielgruppe nicht gefunden');
      await updateClientGroup(clientIds, target.id);
      fetchGroups().then((groupData: Group[]) => {
        const groupMap = Object.fromEntries(groupData.map(g => [g.id, g.name]));
        setGroups(
          groupData.map(g => ({
            keyField: g.name,
            headerText: g.name,
            id: g.id,
          }))
        );
        fetchClients().then(data => {
          setClients(
            data.map((c, i) => ({
              ...c,
              Id: c.uuid,
              Status:
                typeof c.group_id === 'number' && groupMap[c.group_id]
                  ? groupMap[c.group_id]
                  : 'Nicht zugeordnet',
              Summary: c.description || `Client ${i + 1}`,
            }))
          );
          // Nach dem Laden: Karten deselektieren
          setTimeout(() => {
            (kanbanRef.current as KanbanComponentWithClear)?.clearSelection();
            setTimeout(() => {
              (kanbanRef.current as KanbanComponentWithClear)?.clearSelection();
            }, 100);
          }, 50);
        });
      });
    } catch {
      toast.show({
        content: 'Fehler beim Aktualisieren der Clients',
        cssClass: 'e-toast-danger',
        timeOut: 0,
        showCloseButton: true,
      });
    }
    setDraggedCard(null);
  };

  // Spalten-Array ohne Header-Buttons/Template
  const kanbanColumns = groups.map(group => ({
    keyField: group.keyField,
    headerText: group.headerText,
  }));

  return (
    <div id="dialog-target">
      <h2 style={{ fontSize: '1.25rem', fontWeight: 700, marginBottom: 16 }}>{de.title}</h2>
      <div
        style={{
          display: 'flex',
          flexWrap: 'wrap',
          gap: '12px',
          marginBottom: '16px',
        }}
      >
        <ButtonComponent cssClass="e-primary" onClick={() => setShowDialog(true)}>
          {de.newGroup}
        </ButtonComponent>
        <ButtonComponent cssClass="e-warning" onClick={() => setRenameDialog({ open: true, oldName: '', newName: '' })}>
          {de.renameGroup}
        </ButtonComponent>
        <ButtonComponent cssClass="e-danger" onClick={() => setDeleteDialog({ open: true, groupName: '' })}>
          {de.deleteGroup}
        </ButtonComponent>
      </div>
      <KanbanComponent
        locale="de"
        id="kanban"
        keyField="Status"
        dataSource={clients}
        cardSettings={{
          headerField: 'Summary',
          selectionType: 'Multiple',
        }}
        allowDragAndDrop={true}
        dragStart={handleDragStart}
        dragStop={handleCardDrop}
        ref={kanbanRef}
        columns={kanbanColumns}
      />
      {showDialog && (
        <DialogComponent
          visible={showDialog}
          header={de.newGroup}
          close={() => setShowDialog(false)}
          target="#dialog-target"
          width="420px"
          footerTemplate={() => (
            <div className="flex gap-2 justify-end">
              <ButtonComponent cssClass="e-primary" onClick={handleAddGroup} disabled={!newGroupName.trim()}>
                {de.add}
              </ButtonComponent>
              <ButtonComponent onClick={() => setShowDialog(false)}>{de.cancel}</ButtonComponent>
            </div>
          )}
        >
          <div className="mt-2">
            <TextBoxComponent
              value={newGroupName}
              placeholder="Raumname"
              floatLabelType="Auto"
              change={(args: TextBoxChangedArgs) => setNewGroupName(String(args.value ?? ''))}
            />
          </div>
        </DialogComponent>
      )}
      {renameDialog.open && (
        <DialogComponent
          visible={renameDialog.open}
          header={de.renameGroup}
          showCloseIcon={true}
          close={() => setRenameDialog({ open: false, oldName: '', newName: '' })}
          target="#dialog-target"
          width="480px"
          footerTemplate={() => (
            <div className="flex gap-2 justify-end">
              <ButtonComponent
                cssClass="e-primary"
                onClick={handleRenameGroup}
                disabled={!renameDialog.oldName || !renameDialog.newName}
              >
                {de.rename}
              </ButtonComponent>
              <ButtonComponent onClick={() => setRenameDialog({ open: false, oldName: '', newName: '' })}>
                {de.cancel}
              </ButtonComponent>
            </div>
          )}
        >
          <div className="flex flex-col gap-3 mt-2">
            <DropDownListComponent
              placeholder={de.selectGroup}
              dataSource={groups.filter(g => g.headerText !== 'Nicht zugeordnet').map(g => g.headerText)}
              value={renameDialog.oldName}
              change={(e: DropDownChangeArgs) =>
                setRenameDialog({
                  ...renameDialog,
                  oldName: String(e.value ?? ''),
                  newName: String(e.value ?? ''),
                })
              }
            />
            <TextBoxComponent
              placeholder={de.newName}
              value={renameDialog.newName}
              floatLabelType="Auto"
              change={(args: TextBoxChangedArgs) =>
                setRenameDialog({ ...renameDialog, newName: String(args.value ?? '') })
              }
            />
          </div>
        </DialogComponent>
      )}
      {deleteDialog.open && (
        <DialogComponent
          visible={deleteDialog.open}
          header={de.deleteGroup}
          showCloseIcon={true}
          close={() => setDeleteDialog({ open: false, groupName: '' })}
          target="#dialog-target"
          width="520px"
          footerTemplate={() => (
            <div className="flex gap-2 justify-end">
              <ButtonComponent
                cssClass="e-danger"
                onClick={() => setShowDeleteConfirm(true)}
                disabled={!deleteDialog.groupName}
              >
                {de.deleteGroup}
              </ButtonComponent>
              <ButtonComponent onClick={() => setDeleteDialog({ open: false, groupName: '' })}>
                {de.cancel}
              </ButtonComponent>
            </div>
          )}
        >
          <div className="flex flex-col gap-3 mt-2">
            <DropDownListComponent
              placeholder={de.selectGroup}
              dataSource={groups.filter(g => g.headerText !== 'Nicht zugeordnet').map(g => g.headerText)}
              value={deleteDialog.groupName}
              change={(e: DropDownChangeArgs) =>
                setDeleteDialog({ ...deleteDialog, groupName: String(e.value ?? '') })
              }
            />
            <p className="text-sm text-gray-600">{de.clientsMoved}</p>
            {deleteDialog.groupName && (
              <div className="bg-yellow-100 text-yellow-800 p-2 rounded text-sm">
                <strong>{de.warning}</strong> Möchten Sie die Gruppe <b>{deleteDialog.groupName}</b> wirklich löschen?
              </div>
            )}
          </div>
        </DialogComponent>
      )}
      {showDeleteConfirm && deleteDialog.groupName && (
        <DialogComponent
          width="380px"
          header={de.confirmDelete}
          visible={showDeleteConfirm}
          showCloseIcon={true}
          close={() => setShowDeleteConfirm(false)}
          target="#dialog-target"
          footerTemplate={() => (
            <div className="flex gap-2 justify-end">
              <ButtonComponent
                cssClass="e-danger"
                onClick={() => {
                  handleDeleteGroup(deleteDialog.groupName!);
                  setShowDeleteConfirm(false);
                }}
              >
                {de.yesDelete}
              </ButtonComponent>
              <ButtonComponent
                onClick={() => {
                  setShowDeleteConfirm(false);
                  setDeleteDialog({ open: false, groupName: '' });
                }}
              >
                {de.cancel}
              </ButtonComponent>
            </div>
          )}
        >
          <div>
            Möchten Sie die Gruppe <b>{deleteDialog.groupName}</b> wirklich löschen?
            <br />
            <span className="text-sm text-gray-500">{de.clientsMoved}</span>
          </div>
        </DialogComponent>
      )}
    </div>
  );
};

export default Infoscreen_groups;
