import React, { useEffect, useState } from 'react';
import {
  ScheduleComponent,
  ViewsDirective,
  ViewDirective,
  Inject,
  TimelineViews,
  Resize,
  DragAndDrop,
  ResourcesDirective,
  ResourceDirective,
} from '@syncfusion/ej2-react-schedule';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { fetchGroupsWithClients, type Group } from './apiClients';
import { fetchEvents } from './apiEvents';
import { getGroupColor } from './groupColors';
import './ressourcen.css';

interface ScheduleEvent {
  Id: number;
  Subject: string;
  StartTime: Date;
  EndTime: Date;
  ResourceId: number;
  EventType?: string;
}

type TimelineView = 'day' | 'week';

const Ressourcen: React.FC = () => {
  const [scheduleData, setScheduleData] = useState<ScheduleEvent[]>([]);
  const [groups, setGroups] = useState<Group[]>([]);
  const [groupOrder, setGroupOrder] = useState<number[]>([]);
  const [showOrderPanel, setShowOrderPanel] = useState<boolean>(false);
  const [timelineView] = useState<TimelineView>('day');
  const [viewDate] = useState<Date>(() => {
    const now = new Date();
    now.setHours(0, 0, 0, 0);
    return now;
  });
  const [loading, setLoading] = useState<boolean>(false);
  const scheduleRef = React.useRef<ScheduleComponent>(null);

  // Calculate dynamic height based on number of groups
  const calculatedHeight = React.useMemo(() => {
    const rowHeight = 65; // px per row
    const headerHeight = 100; // approx header height
    const totalHeight = groups.length * rowHeight + headerHeight;
    return `${totalHeight}px`;
  }, [groups.length]);

  // Load groups on mount
  useEffect(() => {
    const loadGroups = async () => {
      try {
        console.log('[Ressourcen] Loading groups...');
        const fetchedGroups = await fetchGroupsWithClients();
        console.log('[Ressourcen] Fetched groups:', fetchedGroups);
        // Filter out "Nicht zugeordnet" but show all other groups even if empty
        const filteredGroups = fetchedGroups.filter(
          (group) => group.name !== 'Nicht zugeordnet'
        );
        console.log('[Ressourcen] Filtered groups:', filteredGroups);
        setGroups(filteredGroups);
      } catch (error) {
        console.error('Fehler beim Laden der Gruppen:', error);
      }
    };
    loadGroups();
  }, []);

  // Helper: Parse ISO date string
  const parseUTCDate = React.useCallback((dateStr: string): Date => {
    const utcStr = dateStr.endsWith('Z') ? dateStr : dateStr + 'Z';
    return new Date(utcStr);
  }, []);

  // Calculate date range based on view
  const getDateRange = React.useCallback((): { start: Date; end: Date } => {
    const start = new Date(viewDate);
    start.setHours(0, 0, 0, 0);

    const end = new Date(start);
    if (timelineView === 'day') {
      end.setHours(23, 59, 59, 999);
    } else if (timelineView === 'week') {
      end.setDate(start.getDate() + 6);
      end.setHours(23, 59, 59, 999);
    }
    return { start, end };
  }, [viewDate, timelineView]);

  // Load events for all groups
  useEffect(() => {
    if (groups.length === 0) {
      console.log('[Ressourcen] No groups to load events for');
      setScheduleData([]);
      return;
    }

    const loadEventsForAllGroups = async () => {
      setLoading(true);
      console.log('[Ressourcen] Loading events for', groups.length, 'groups');
      try {
        const { start, end } = getDateRange();
        const events: ScheduleEvent[] = [];
        let eventId = 1;

        // Create events for each group
        for (const group of groups) {
          try {
            console.log(`[Ressourcen] Fetching events for group "${group.name}" (ID: ${group.id})`);
            const apiEvents = await fetchEvents(group.id.toString(), false, {
              start,
              end,
            });
            console.log(`[Ressourcen] Got ${apiEvents?.length || 0} events for group "${group.name}"`);

            if (Array.isArray(apiEvents) && apiEvents.length > 0) {
              const event = apiEvents[0];
              const eventTitle = event.subject || event.title || 'Unnamed Event';
              const eventType = event.type || event.event_type || 'other';
              const eventStart = event.startTime || event.start;
              const eventEnd = event.endTime || event.end;

              if (eventStart && eventEnd) {
                const parsedStart = parseUTCDate(eventStart);
                const parsedEnd = parseUTCDate(eventEnd);

                // Capitalize first letter of event type
                const formattedType = eventType.charAt(0).toUpperCase() + eventType.slice(1);

                events.push({
                  Id: eventId++,
                  Subject: `${formattedType} - ${eventTitle}`,
                  StartTime: parsedStart,
                  EndTime: parsedEnd,
                  ResourceId: group.id,
                  EventType: eventType,
                });
                console.log(`[Ressourcen] Group "${group.name}" has event: ${eventTitle}`);
              }
            }
          } catch (error) {
            console.error(`Fehler beim Laden von Ereignissen für Gruppe ${group.name}:`, error);
          }
        }

        console.log('[Ressourcen] Final events:', events);
        setScheduleData(events);
      } finally {
        setLoading(false);
      }
    };

    loadEventsForAllGroups();
  }, [groups, timelineView, viewDate, parseUTCDate, getDateRange]);

  // Load saved group order from backend on mount
  useEffect(() => {
    const loadGroupOrder = async () => {
      try {
        console.log('[Ressourcen] Loading saved group order from backend...');
        const response = await fetch('/api/groups/order');
        if (response.ok) {
          const data = await response.json();
          console.log('[Ressourcen] Retrieved group order:', data);
          if (data.order && Array.isArray(data.order)) {
            // Filter order to only include IDs that exist in current groups
            const existingGroupIds = groups.map(g => g.id);
            const validOrder = data.order.filter((id: number) => existingGroupIds.includes(id));
            
            // Add any missing group IDs that aren't in the saved order
            const missingIds = existingGroupIds.filter(id => !validOrder.includes(id));
            const finalOrder = [...validOrder, ...missingIds];
            
            console.log('[Ressourcen] Synced order:', finalOrder);
            setGroupOrder(finalOrder);
          } else {
            // No saved order, use default (current group order)
            setGroupOrder(groups.map(g => g.id));
          }
        } else {
          console.log('[Ressourcen] No saved order found, using default');
          setGroupOrder(groups.map(g => g.id));
        }
      } catch (error) {
        console.error('[Ressourcen] Error loading group order:', error);
        // Fall back to default order
        setGroupOrder(groups.map(g => g.id));
      }
    };

    if (groups.length > 0 && groupOrder.length === 0) {
      loadGroupOrder();
    }
  }, [groups, groupOrder.length]);

  // Move group up in order
  const moveGroupUp = (groupId: number) => {
    const index = groupOrder.indexOf(groupId);
    if (index > 0) {
      const newOrder = [...groupOrder];
      [newOrder[index - 1], newOrder[index]] = [newOrder[index], newOrder[index - 1]];
      setGroupOrder(newOrder);
    }
  };

  // Move group down in order
  const moveGroupDown = (groupId: number) => {
    const index = groupOrder.indexOf(groupId);
    if (index < groupOrder.length - 1) {
      const newOrder = [...groupOrder];
      [newOrder[index], newOrder[index + 1]] = [newOrder[index + 1], newOrder[index]];
      setGroupOrder(newOrder);
    }
  };

  // Save group order to backend
  const saveGroupOrder = async () => {
    try {
      console.log('[Ressourcen] Saving group order:', groupOrder);
      const response = await fetch('/api/groups/order', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ order: groupOrder }),
      });
      if (!response.ok) throw new Error('Failed to save group order');
      console.log('[Ressourcen] Group order saved successfully');
    } catch (error) {
      console.error('Fehler beim Speichern der Reihenfolge:', error);
    }
  };

  // Get sorted groups based on current order
  const sortedGroups = React.useMemo(() => {
    if (groupOrder.length === 0) return groups;
    
    // Map order to actual groups
    const ordered = groupOrder
      .map(id => groups.find(g => g.id === id))
      .filter((g): g is Group => g !== undefined);
    
    // Add any groups not in the order (new groups)
    const orderedIds = new Set(ordered.map(g => g.id));
    const unordered = groups.filter(g => !orderedIds.has(g.id));
    
    return [...ordered, ...unordered];
  }, [groups, groupOrder]);

  return (
    <div className="ressourcen-container">
      <h1 className="ressourcen-title">📊 Ressourcen - Übersicht</h1>

      <div style={{ marginBottom: '15px' }}>
        <ButtonComponent
          cssClass={showOrderPanel ? 'e-success' : 'e-outline'}
          onClick={() => setShowOrderPanel(!showOrderPanel)}
        >
          {showOrderPanel ? '✓ Reihenfolge' : 'Reihenfolge ändern'}
        </ButtonComponent>
      </div>

      {/* Group Order Control Panel */}
      {showOrderPanel && (
      <div className="ressourcen-order-panel">
        <div className="ressourcen-order-header">
          <h3 style={{ margin: '0 0 12px 0', fontSize: '14px', fontWeight: 600 }}>
            📋 Reihenfolge der Gruppen
          </h3>
          <div className="ressourcen-order-list">
            {sortedGroups.map((group, index) => (
              <div key={group.id} className="ressourcen-order-item">
                <span className="ressourcen-order-position">{index + 1}.</span>
                <span className="ressourcen-order-name">{group.name}</span>
                <div className="ressourcen-order-buttons">
                  <ButtonComponent
                    cssClass="e-outline e-small"
                    onClick={() => moveGroupUp(group.id)}
                    disabled={index === 0}
                    title="Nach oben"
                    style={{ padding: '4px 8px', minWidth: '32px' }}
                  >
                    ↑
                  </ButtonComponent>
                  <ButtonComponent
                    cssClass="e-outline e-small"
                    onClick={() => moveGroupDown(group.id)}
                    disabled={index === sortedGroups.length - 1}
                    title="Nach unten"
                    style={{ padding: '4px 8px', minWidth: '32px' }}
                  >
                    ↓
                  </ButtonComponent>
                </div>
              </div>
            ))}
          </div>
          <ButtonComponent
            cssClass="e-success"
            onClick={saveGroupOrder}
            style={{ marginTop: '12px', width: '100%' }}
          >
            💾 Reihenfolge speichern
          </ButtonComponent>
        </div>
      </div>
      )}

      {/* Timeline Schedule */}
      {loading ? (
        <div className="ressourcen-loading">
          <p>Wird geladen...</p>
        </div>
      ) : (
        <div className="ressourcen-timeline-wrapper">
          <ScheduleComponent
            ref={scheduleRef}
            height={calculatedHeight}
            width="100%"
            eventSettings={{ dataSource: scheduleData }}
            selectedDate={viewDate}
            currentView={timelineView === 'day' ? 'TimelineDay' : 'TimelineWeek'}
            group={{ resources: ['Groups'], allowGroupEdit: false }}
            timeScale={{ interval: 60, slotCount: 1 }}
            rowAutoHeight={false}
          >
            <ViewsDirective>
              <ViewDirective option="TimelineDay" displayName="Tag"></ViewDirective>
              <ViewDirective option="TimelineWeek" displayName="Woche"></ViewDirective>
            </ViewsDirective>
            <ResourcesDirective>
              <ResourceDirective
                field="ResourceId"
                title="Gruppe"
                name="Groups"
                allowMultiple={false}
                dataSource={sortedGroups.map((g) => ({
                  text: g.name,
                  id: g.id,
                  color: getGroupColor(g.id.toString(), groups.map(grp => ({ id: grp.id.toString() }))),
                }))}
                textField="text"
                idField="id"
                colorField="color"
              />
            </ResourcesDirective>
            <Inject services={[TimelineViews, Resize, DragAndDrop]} />
          </ScheduleComponent>
        </div>
      )}
    </div>
  );
};

export default Ressourcen;
