import type { ScheduleDay, ScheduleShift, UserDayData } from '../types/departmentSchedule';

export type MergedCellType = 'shift' | 'vacation' | 'sick' | 'free';

export interface MergedCell {
  startIndex: number;
  span: number;
  type: MergedCellType;
  date: string;
  shifts?: ScheduleShift[];
  vacationId?: number;
  vacationStatus?: 'approved' | 'submitted';
  sickId?: number;
  sickStatus?: 'approved' | 'submitted';
  isWeekend: boolean;
}

function getUserDayData(day: ScheduleDay, userId: number): UserDayData | undefined {
  return day.users_data.find((ud) => ud.usr_id === userId);
}

function isWeekendDay(dayName: string): boolean {
  return dayName === 'Saturday' || dayName === 'Sunday';
}

/**
 * Computes merged cells for a user across all days of the month.
 * Consecutive vacation days (same zvr_id) are merged into a single cell.
 * Consecutive sick days (same zsr_id) are merged into a single cell.
 * Shifts and free days are always single-day cells (span=1).
 */
export function computeMergedCells(userId: number, days: ScheduleDay[]): MergedCell[] {
  const cells: MergedCell[] = [];
  let i = 0;

  while (i < days.length) {
    const day = days[i];
    const userData = getUserDayData(day, userId);
    const weekend = isWeekendDay(day.day_name);

    if (!userData || userData.is_free) {
      // Free day — no merging
      cells.push({
        startIndex: i,
        span: 1,
        type: 'free',
        date: day.date,
        isWeekend: weekend,
      });
      i++;
      continue;
    }

    // Check for vacation
    if (userData.vacation) {
      const vacationId = userData.vacation.zvr_id;
      let span = 1;
      let nextIdx = i + 1;

      while (nextIdx < days.length) {
        const nextUserData = getUserDayData(days[nextIdx], userId);
        if (nextUserData?.vacation?.zvr_id === vacationId) {
          span++;
          nextIdx++;
        } else {
          break;
        }
      }

      cells.push({
        startIndex: i,
        span,
        type: 'vacation',
        date: day.date,
        vacationId,
        vacationStatus: userData.vacation!.status,
        isWeekend: weekend,
      });
      i = nextIdx;
      continue;
    }

    // Check for sick leave
    if (userData.sick_leave) {
      const sickId = userData.sick_leave.zsr_id;
      let span = 1;
      let nextIdx = i + 1;

      while (nextIdx < days.length) {
        const nextUserData = getUserDayData(days[nextIdx], userId);
        if (nextUserData?.sick_leave?.zsr_id === sickId) {
          span++;
          nextIdx++;
        } else {
          break;
        }
      }

      cells.push({
        startIndex: i,
        span,
        type: 'sick',
        date: day.date,
        sickId,
        sickStatus: userData.sick_leave!.status,
        isWeekend: weekend,
      });
      i = nextIdx;
      continue;
    }

    // Shift(s) — always single day
    if (userData.shifts.length > 0) {
      cells.push({
        startIndex: i,
        span: 1,
        type: 'shift',
        date: day.date,
        shifts: userData.shifts,
        isWeekend: weekend,
      });
      i++;
      continue;
    }

    // Fallback: free
    cells.push({
      startIndex: i,
      span: 1,
      type: 'free',
      date: day.date,
      isWeekend: weekend,
    });
    i++;
  }

  return cells;
}
