import { useState, useEffect, useCallback, useRef } from 'react';
import axios from 'axios';
import {
  DashboardProfile,
  ActiveSession,
  UpcomingShift,
  ActionItem,
  AttendanceAlert,
  DashboardOverviewResponse,
} from '../types/dashboard';

interface UseDashboardDataOptions {
  autoRefresh?: boolean;
  refreshInterval?: number;
  onNewAlert?: (alert: AttendanceAlert) => void;
  onNewSession?: (session: ActiveSession) => void;
  onBreakStatusChange?: (session: ActiveSession, isOnBreak: boolean) => void;
}

interface UseDashboardDataReturn {
  // Data
  profile: DashboardProfile | null;
  activeSessions: ActiveSession[];
  upcomingShifts: UpcomingShift[];
  actionItems: ActionItem[];
  attendanceAlerts: AttendanceAlert[];

  // Loading states
  loading: boolean;
  profileLoading: boolean;
  sessionsLoading: boolean;
  upcomingLoading: boolean;
  actionItemsLoading: boolean;
  alertsLoading: boolean;

  // Error states
  error: string | null;
  sessionsError: string | null;
  upcomingError: string | null;
  alertsError: string | null;

  // Actions
  refreshAll: () => Promise<void>;
  refreshSessions: () => Promise<void>;
  refreshUpcoming: (hours?: number, departmentId?: number | null) => Promise<void>;
  refreshAlerts: () => Promise<void>;
  refreshActionItems: () => Promise<void>;

  // Session actions
  clockOutSession: (sessionId: number) => Promise<void>;
  startBreak: (sessionId: number) => Promise<void>;
  endBreak: (sessionId: number) => Promise<void>;

  // Alert actions
  markAbsent: (alertId: string, userId: number) => Promise<void>;
  resolveAlert: (alertId: string, resolution: string) => Promise<void>;

  // Action item actions
  acceptShift: (assignmentId: number) => Promise<void>;
  declineShift: (assignmentId: number) => Promise<void>;
}

export function useDashboardData(options: UseDashboardDataOptions = {}): UseDashboardDataReturn {
  const {
    autoRefresh = true,
    refreshInterval = 30000,
    onNewAlert,
    onNewSession,
    onBreakStatusChange,
  } = options;

  // Data state
  const [profile, setProfile] = useState<DashboardProfile | null>(null);
  const [activeSessions, setActiveSessions] = useState<ActiveSession[]>([]);
  const [upcomingShifts, setUpcomingShifts] = useState<UpcomingShift[]>([]);
  const [actionItems, setActionItems] = useState<ActionItem[]>([]);
  const [attendanceAlerts, setAttendanceAlerts] = useState<AttendanceAlert[]>([]);

  // Loading states
  const [loading, setLoading] = useState(true);
  const [profileLoading, setProfileLoading] = useState(true);
  const [sessionsLoading, setSessionsLoading] = useState(false);
  const [upcomingLoading, setUpcomingLoading] = useState(false);
  const [actionItemsLoading, setActionItemsLoading] = useState(false);
  const [alertsLoading, setAlertsLoading] = useState(false);

  // Error states
  const [error, setError] = useState<string | null>(null);
  const [sessionsError, setSessionsError] = useState<string | null>(null);
  const [upcomingError, setUpcomingError] = useState<string | null>(null);
  const [alertsError, setAlertsError] = useState<string | null>(null);

  // Refs for tracking previous data (for new item detection)
  const prevSessionsRef = useRef<ActiveSession[]>([]);
  const prevAlertsRef = useRef<AttendanceAlert[]>([]);

  // Fetch profile/overview
  const fetchProfile = useCallback(async () => {
    try {
      setProfileLoading(true);
      const response = await axios.get<DashboardOverviewResponse>(
        '/zeiterfassung/dashboard/my-overview'
      );
      setProfile(response.data.profile);
      setError(null);
    } catch (err: any) {
      setError(err.response?.data?.message || 'Failed to load profile');
      console.error('Error fetching dashboard profile:', err);
    } finally {
      setProfileLoading(false);
    }
  }, []);

  // Fetch active sessions - use existing work-sessions/active endpoint
  const refreshSessions = useCallback(async () => {
    try {
      setSessionsLoading(true);
      setSessionsError(null);
      const response = await axios.get('/zeiterfassung/work-sessions/active');

      // Transform snake_case API response to camelCase ActiveSession format
      const newSessions: ActiveSession[] = response.data.map((s: any) => ({
        sessionId: s.session_id,
        userId: s.user_id,
        userName: s.user_name,
        userInitials: s.user_initials,
        userPhoto: s.user_photo,
        shiftId: s.shift_id,
        shiftName: s.shift_name,
        shiftDate: s.shift_date,
        shiftStartTime: s.shift_start_time,
        shiftEndTime: s.shift_end_time,
        shiftColor: s.shift_color,
        roleId: s.role_id,
        roleName: s.role_name,
        roleColor: s.role_color,
        clockInTime: s.clock_in_time,
        clockInMethod: s.clock_in_method,
        clockInLocationValid: s.clock_in_location_valid,
        isOnBreak: s.is_on_break,
        breakDuration: s.break_duration,
        currentBreakStart: s.current_break_start,
        departmentId: null,
        departmentName: s.department_name,
        status: s.status,
        breaks: s.breaks || [],
        punctuality: s.punctuality,
      }));

      // Detect new sessions and break status changes (skip on initial load)
      if (prevSessionsRef.current.length > 0) {
        const prevSessionsMap = new Map(prevSessionsRef.current.map((s) => [s.sessionId, s]));

        newSessions.forEach((session) => {
          const prevSession = prevSessionsMap.get(session.sessionId);
          if (!prevSession) {
            // New session - someone clocked in
            if (onNewSession) {
              console.log('[useDashboardData] New session detected:', session.userName);
              onNewSession(session);
            }
          } else if (prevSession.isOnBreak !== session.isOnBreak) {
            // Break status changed
            if (onBreakStatusChange) {
              console.log('[useDashboardData] Break status changed:', session.userName, session.isOnBreak ? 'went on break' : 'back from break');
              onBreakStatusChange(session, session.isOnBreak);
            }
          }
        });
      }

      prevSessionsRef.current = newSessions;
      setActiveSessions(newSessions);
    } catch (err: any) {
      setSessionsError(err.response?.data?.message || 'Failed to load sessions');
      console.error('Error fetching active sessions:', err);
    } finally {
      setSessionsLoading(false);
    }
  }, [onNewSession, onBreakStatusChange]);

  // Fetch upcoming shifts
  const refreshUpcoming = useCallback(
    async (hours: number = 6, departmentId: number | null = null) => {
      try {
        setUpcomingLoading(true);
        setUpcomingError(null);
        const params: Record<string, any> = { hours };
        if (departmentId) {
          params.ber_id = departmentId;
        }
        const response = await axios.get<UpcomingShift[]>(
          '/zeiterfassung/dashboard/upcoming-shifts',
          { params }
        );
        setUpcomingShifts(response.data);
      } catch (err: any) {
        setUpcomingError(err.response?.data?.message || 'Failed to load upcoming shifts');
        console.error('Error fetching upcoming shifts:', err);
      } finally {
        setUpcomingLoading(false);
      }
    },
    []
  );

  // Fetch action items
  const refreshActionItems = useCallback(async () => {
    try {
      setActionItemsLoading(true);
      const response = await axios.get<ActionItem[]>(
        '/zeiterfassung/dashboard/action-items'
      );
      setActionItems(response.data);
    } catch (err: any) {
      console.error('Error fetching action items:', err);
    } finally {
      setActionItemsLoading(false);
    }
  }, []);

  // Fetch attendance alerts
  const refreshAlerts = useCallback(async () => {
    try {
      setAlertsLoading(true);
      setAlertsError(null);
      const response = await axios.get<AttendanceAlert[]>(
        '/zeiterfassung/dashboard/attendance-alerts'
      );

      const newAlerts = response.data;

      // Detect new alerts
      if (onNewAlert && prevAlertsRef.current.length > 0) {
        const prevIds = new Set(prevAlertsRef.current.map((a) => a.id));
        newAlerts.forEach((alert) => {
          if (!prevIds.has(alert.id) && !alert.resolved) {
            onNewAlert(alert);
          }
        });
      }

      prevAlertsRef.current = newAlerts;
      setAttendanceAlerts(newAlerts);
    } catch (err: any) {
      setAlertsError(err.response?.data?.message || 'Failed to load alerts');
      console.error('Error fetching attendance alerts:', err);
    } finally {
      setAlertsLoading(false);
    }
  }, [onNewAlert]);

  // Refresh all data
  const refreshAll = useCallback(async () => {
    setLoading(true);
    await Promise.all([
      fetchProfile(),
      refreshSessions(),
      refreshUpcoming(),
      refreshActionItems(),
      refreshAlerts(),
    ]);
    setLoading(false);
  }, [fetchProfile, refreshSessions, refreshUpcoming, refreshActionItems, refreshAlerts]);

  // Session actions
  const clockOutSession = useCallback(async (sessionId: number) => {
    await axios.post('/zeiterfassung/work-sessions/clock-out', {
      session_id: sessionId,
      method: 'manual',
    });
    await refreshSessions();
  }, [refreshSessions]);

  const startBreak = useCallback(async (sessionId: number) => {
    await axios.post('/zeiterfassung/work-sessions/break-start', {
      session_id: sessionId,
    });
    await refreshSessions();
  }, [refreshSessions]);

  const endBreak = useCallback(async (sessionId: number) => {
    await axios.post('/zeiterfassung/work-sessions/break-end', {
      session_id: sessionId,
    });
    await refreshSessions();
  }, [refreshSessions]);

  // Alert actions
  const markAbsent = useCallback(async (alertId: string, userId: number) => {
    await axios.post('/zeiterfassung/dashboard/mark-absent', {
      alert_id: alertId,
      user_id: userId,
    });
    await refreshAlerts();
  }, [refreshAlerts]);

  const resolveAlert = useCallback(async (alertId: string, resolution: string) => {
    await axios.post('/zeiterfassung/dashboard/resolve-alert', {
      alert_id: alertId,
      resolution,
    });
    await refreshAlerts();
  }, [refreshAlerts]);

  // Action item actions
  const acceptShift = useCallback(async (assignmentId: number) => {
    await axios.post(`/zeiterfassung/shift-assignments/${assignmentId}/accept`);
    await refreshActionItems();
  }, [refreshActionItems]);

  const declineShift = useCallback(async (assignmentId: number) => {
    await axios.post(`/zeiterfassung/shift-assignments/${assignmentId}/decline`);
    await refreshActionItems();
  }, [refreshActionItems]);

  // Initial load
  useEffect(() => {
    refreshAll();
  }, []);

  // Auto-refresh removed — sessions and alerts are now updated via FCM push notifications.
  // Components can still call refreshSessions() / refreshAlerts() manually when needed.

  return {
    // Data
    profile,
    activeSessions,
    upcomingShifts,
    actionItems,
    attendanceAlerts,

    // Loading states
    loading,
    profileLoading,
    sessionsLoading,
    upcomingLoading,
    actionItemsLoading,
    alertsLoading,

    // Error states
    error,
    sessionsError,
    upcomingError,
    alertsError,

    // Actions
    refreshAll,
    refreshSessions,
    refreshUpcoming,
    refreshAlerts,
    refreshActionItems,

    // Session actions
    clockOutSession,
    startBreak,
    endBreak,

    // Alert actions
    markAbsent,
    resolveAlert,

    // Action item actions
    acceptShift,
    declineShift,
  };
}

export default useDashboardData;
