import { createSelector } from '@reduxjs/toolkit';
import type { RootState } from '@/store/store';
import type { 
  AttendanceAnalytics, 
  EmployeeAnalytics, 
  LeaveAnalytics, 
  HolidayAnalytics 
} from '../types/zohoPeopleTypes';

// Base selectors
export const selectZohoPeopleState = (state: RootState) => state.zohoPeople || {
  attendanceReport: null,
  employeeForms: null,
  holidays: null,
  leaveTracker: null,
  leaveData: null,
  loading: false,
  error: null,
  lastUpdated: null,
};

export const selectAttendanceReport = (state: RootState) => state.zohoPeople?.attendanceReport || null;
export const selectEmployeeForms = (state: RootState) => state.zohoPeople?.employeeForms || null;
export const selectHolidays = (state: RootState) => state.zohoPeople?.holidays || null;
export const selectLeaveTracker = (state: RootState) => state.zohoPeople?.leaveTracker || null;
export const selectLeaveData = (state: RootState) => state.zohoPeople?.leaveData || null;
export const selectZohoPeopleLoading = (state: RootState) => state.zohoPeople?.loading || false;
export const selectZohoPeopleError = (state: RootState) => state.zohoPeople?.error || null;
export const selectZohoPeopleLastUpdated = (state: RootState) => state.zohoPeople?.lastUpdated || null;

// Computed selectors
export const selectAttendanceAnalytics = createSelector(
  [selectAttendanceReport],
  (attendanceReport): AttendanceAnalytics | null => {
    if (!attendanceReport || attendanceReport.length === 0) {
      return null;
    }

    const today = new Date();
    const todayISO = today.toISOString().split('T')[0]; // YYYY-MM-DD
    const todayFormatted = todayISO.split('-').reverse().join('-'); // DD-MM-YYYY
    
    let presentToday = 0;
    let absentToday = 0;
    let weekendToday = 0;
    let totalWorkingHours = 0;
    let employeesWithHours = 0;

    console.log('Today ISO:', todayISO);
    console.log('Today Formatted:', todayFormatted);

    attendanceReport.forEach((employee) => {
      if (!employee.attendanceDetails) {
        return;
      }

      // Check all available date formats for today
      const todayAttendance = employee.attendanceDetails[todayFormatted] || 
                             employee.attendanceDetails[todayISO] ||
                             employee.attendanceDetails[todayISO.split('-').reverse().join('-')];

      console.log('Employee attendance keys:', Object.keys(employee.attendanceDetails));
      console.log('Today attendance found:', !!todayAttendance);

      if (todayAttendance) {
        const status = todayAttendance.Status?.toLowerCase() || '';
        console.log('Today status for employee:', status);
        
        if (status === 'present') {
          presentToday++;
        } else if (status === 'absent' || status === '') {
          // Empty status means absent as per Indian shift time (09:00 AM)
          absentToday++;
        } else if (status === 'weekend') {
          weekendToday++;
        }

        // Calculate working hours for today
        const workingHours = todayAttendance.WorkingHours || todayAttendance.TotalHours;
        if (workingHours && workingHours !== '00:00' && workingHours !== '0:00') {
          try {
            const [hours, minutes] = workingHours.split(':').map(Number);
            if (!isNaN(hours) && !isNaN(minutes)) {
              totalWorkingHours += hours + minutes / 60;
              employeesWithHours++;
            }
          } catch (error) {
            // Silently handle parsing errors
          }
        }
      } else {
        // If no attendance data for today, count as absent
        absentToday++;
      }
    });

    const totalEmployees = attendanceReport.length;
    const averageWorkingHours = employeesWithHours > 0 ? totalWorkingHours / employeesWithHours : 0;
    const attendanceRate = totalEmployees > 0 ? (presentToday / totalEmployees) * 100 : 0;

    console.log('Final counts - Present:', presentToday, 'Absent:', absentToday, 'Weekend:', weekendToday);

    return {
      totalEmployees,
      presentToday,
      absentToday,
      weekendToday,
      averageWorkingHours,
      attendanceRate,
    };
  }
);

export const selectEmployeeAnalytics = createSelector(
  [selectEmployeeForms],
  (employeeForms): EmployeeAnalytics | null => {
    if (!employeeForms || employeeForms.length === 0) {
      return null;
    }

    const totalEmployees = employeeForms.length;
    const activeEmployees = employeeForms.filter(emp => emp.Employeestatus === 'Active').length;
    
    const departmentDistribution: { [key: string]: number } = {};
    const genderDistribution: { [key: string]: number } = {};
    let totalAge = 0;
    let totalExperience = 0;
    let validAgeCount = 0;
    let validExpCount = 0;

    employeeForms.forEach((emp) => {
      // Department distribution
      const dept = emp.Department || 'Unknown';
      departmentDistribution[dept] = (departmentDistribution[dept] || 0) + 1;

      // Gender distribution
      const gender = emp.Gender || 'Unknown';
      genderDistribution[gender] = (genderDistribution[gender] || 0) + 1;

      // Age calculation
      if (emp.Age && !isNaN(Number(emp.Age))) {
        totalAge += Number(emp.Age);
        validAgeCount++;
      }

      // Experience calculation
      if (emp.Experience && !isNaN(Number(emp.Experience))) {
        totalExperience += Number(emp.Experience);
        validExpCount++;
      }
    });

    return {
      totalEmployees,
      activeEmployees,
      departmentDistribution,
      genderDistribution,
      averageAge: validAgeCount > 0 ? totalAge / validAgeCount : 0,
      averageExperience: validExpCount > 0 ? totalExperience / validExpCount : 0,
    };
  }
);

export const selectLeaveAnalytics = createSelector(
  [selectLeaveTracker, selectLeaveData],
  (leaveTracker, leaveData): LeaveAnalytics | null => {
    if (!leaveTracker || !leaveData) return null;

    let totalLeaveBalance = 0;
    let paidLeaveBalance = 0;
    let unpaidLeaveBalance = 0;
    let totalPaidBooked = 0;
    let totalUnpaidBooked = 0;

    // Calculate leave balances from tracker
    Object.values(leaveTracker.report).forEach(employeeReport => {
      totalLeaveBalance += employeeReport.totals.paidBalance + employeeReport.totals.unpaidBalance;
      paidLeaveBalance += employeeReport.totals.paidBalance;
      unpaidLeaveBalance += employeeReport.totals.unpaidBalance;
      totalPaidBooked += employeeReport.totals.paidBooked;
      totalUnpaidBooked += employeeReport.totals.unpaidBooked;
    });

    // Get upcoming leaves (next 30 days)
    const today = new Date();
    const thirtyDaysFromNow = new Date(today.getTime() + 30 * 24 * 60 * 60 * 1000);
    
    const upcomingLeaves = leaveData.filter(leave => {
      const fromDate = new Date(leave.From);
      return fromDate >= today && fromDate <= thirtyDaysFromNow;
    });

    const totalBooked = totalPaidBooked + totalUnpaidBooked;
    const leaveUtilizationRate = totalLeaveBalance > 0 ? (totalBooked / (totalLeaveBalance + totalBooked)) * 100 : 0;

    return {
      totalLeaveBalance,
      paidLeaveBalance,
      unpaidLeaveBalance,
      upcomingLeaves,
      leaveUtilizationRate,
    };
  }
);

export const selectHolidayAnalytics = createSelector(
  [selectHolidays],
  (holidays): HolidayAnalytics | null => {
    if (!holidays || holidays.length === 0) return null;

    const today = new Date();
    today.setHours(0, 0, 0, 0); // Reset time to start of day for accurate comparison
    
    console.log('Today date for holiday comparison:', today);
    console.log('All holidays:', holidays.map(h => ({ name: h.Name, date: h.Date })));

    const upcomingHolidays = holidays.filter(holiday => {
      // Try different date parsing methods
      let holidayDate;
      
      // Method 1: Direct parsing (works for DD-MMM-YYYY format like "02-Oct-2025")
      holidayDate = new Date(holiday.Date);
      
      // Method 2: If invalid, try parsing DD-MM-YYYY format
      if (isNaN(holidayDate.getTime())) {
        const parts = holiday.Date.split('-');
        if (parts.length === 3) {
          holidayDate = new Date(parseInt(parts[2]), parseInt(parts[1]) - 1, parseInt(parts[0]));
        }
      }
      
      // Method 3: Try YYYY-MM-DD format
      if (isNaN(holidayDate.getTime())) {
        const parts = holiday.Date.split('-');
        if (parts.length === 3) {
          holidayDate = new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));
        }
      }
      
      // Method 4: Try DD-MMM-YYYY format manually (e.g., "02-Oct-2025")
      if (isNaN(holidayDate.getTime())) {
        const parts = holiday.Date.split('-');
        if (parts.length === 3) {
          const day = parseInt(parts[0]);
          const monthStr = parts[1];
          const year = parseInt(parts[2]);
          
          // Map month names to numbers
          const monthMap: { [key: string]: number } = {
            'Jan': 0, 'Feb': 1, 'Mar': 2, 'Apr': 3, 'May': 4, 'Jun': 5,
            'Jul': 6, 'Aug': 7, 'Sep': 8, 'Oct': 9, 'Nov': 10, 'Dec': 11
          };
          
          const month = monthMap[monthStr];
          if (month !== undefined) {
            holidayDate = new Date(year, month, day);
          }
        }
      }
      
      holidayDate.setHours(0, 0, 0, 0); // Reset time to start of day
      
      console.log(`Holiday: ${holiday.Name}, Date: ${holiday.Date}, Parsed: ${holidayDate}, Is upcoming: ${holidayDate >= today}`);
      
      return holidayDate >= today;
    }).sort((a, b) => {
      // Use the same parsing logic for sorting
      const dateA = new Date(a.Date);
      const dateB = new Date(b.Date);
      return dateA.getTime() - dateB.getTime();
    });

    console.log('Upcoming holidays found:', upcomingHolidays.length);

    const totalHolidays = holidays.length;
    const restrictedHolidays = holidays.filter(h => h.isRestrictedHoliday).length;
    const halfDayHolidays = holidays.filter(h => h.isHalfday).length;

    return {
      upcomingHolidays,
      totalHolidays,
      restrictedHolidays,
      halfDayHolidays,
    };
  }
);
