import {
  type Representative,
  DaysOfWeek,
  SensTrip,
  WeekType,
  type TransportSchedule,
  type DaySchedule,
} from '@/shared/types/passenger';
import type {
  DayScheduleEstablishmentDTO,
  EstablishmentTransportScheduleDTO,
} from '@/shared/types/passenger';
import type { EstablishmentSchedule } from '@/shared/components/form/etablissement-jours-field';
import type { AmendmentPassengerDetails } from '@/shared/types/ammendment-passenger';

export function apiToComponentStructure(
  apiSchedules: EstablishmentTransportScheduleDTO[]
): EstablishmentSchedule[] {
  if (!apiSchedules || apiSchedules.length === 0) {
    return [];
  }

  const groupedData: Record<
    number,
    Partial<Record<WeekType, EstablishmentTransportScheduleDTO[]>>
  > = {};

  apiSchedules.forEach((schedule) => {
    if (!groupedData[schedule.idEstablishment]) {
      groupedData[schedule.idEstablishment] = {};
    }

    if (!groupedData[schedule.idEstablishment]![schedule.weekType]) {
      groupedData[schedule.idEstablishment]![schedule.weekType] = [];
    }

    groupedData[schedule.idEstablishment]![schedule.weekType]!.push(schedule);
  });

  const result = Object.entries(groupedData).map(([idEstablishment, weekTypes]) => {
    const weekTypeEntries = Object.entries(
      weekTypes as Record<WeekType, EstablishmentTransportScheduleDTO[]>
    );
    const firstSchedule = weekTypeEntries[0][1][0];

    return {
      id: firstSchedule.id || '',
      idEstablishment: Number.parseInt(idEstablishment),
      establishmentName: firstSchedule.establishmentName,
      dayScheduleEstablishments: weekTypeEntries.map(([weekType, schedules]) => ({
        id: schedules[0].id || '',
        weekType: weekType as WeekType,
        schedules: schedules.flatMap((s) =>
          s.dayScheduleEstablishments.map((d) => ({
            id: d.id || '',
            dayOfWeek: d.dayOfWeek,
            periodOfDay: d.periodOfDay,
          }))
        ),
      })),
    };
  });

  return result;
}

export function componentToApiStructure(
  componentSchedules: EstablishmentSchedule[]
): EstablishmentTransportScheduleDTO[] {
  return componentSchedules.flatMap((establishment) => {
    if (
      !establishment.dayScheduleEstablishments ||
      establishment.dayScheduleEstablishments.length === 0
    ) {
      return [
        {
          id: establishment.dayScheduleEstablishments[0]?.id || '',
          idEstablishment: establishment.idEstablishment,
          establishmentName: establishment.establishmentName,
          weekType: WeekType.EVEN,
          dayScheduleEstablishments: [],
        },
      ];
    }

    const schedulesByWeekType: Record<WeekType, DayScheduleEstablishmentDTO[]> = {} as Record<
      WeekType,
      DayScheduleEstablishmentDTO[]
    >;

    establishment.dayScheduleEstablishments.forEach((weekSchedule) => {
      if (!schedulesByWeekType[weekSchedule.weekType]) {
        schedulesByWeekType[weekSchedule.weekType] = [];
      }

      weekSchedule.schedules.forEach((schedule) => {
        schedulesByWeekType[weekSchedule.weekType].push({
          id: schedule.id || '',
          dayOfWeek: schedule.dayOfWeek,
          periodOfDay: schedule.periodOfDay,
        });
      });
    });
    if (Object.keys(schedulesByWeekType).length === 0) {
      return [
        {
          id: establishment.dayScheduleEstablishments[0]?.id || '',
          idEstablishment: establishment.idEstablishment,
          establishmentName: establishment.establishmentName,
          weekType: WeekType.EVEN,
          dayScheduleEstablishments: [],
        },
      ];
    }

    const result = Object.entries(schedulesByWeekType).map(([weekType, daySchedules]) => ({
      id:
        weekType === WeekType.EVEN
          ? establishment.dayScheduleEstablishments[0]?.id
          : establishment.dayScheduleEstablishments[1]?.id || '',
      idEstablishment: establishment.idEstablishment,
      establishmentName: establishment.establishmentName,
      weekType: weekType as WeekType,
      dayScheduleEstablishments: daySchedules,
    }));
    return result;
  });
}
export const convertSchedulesToSelectedDays = (
  transportSchedules: Representative['transportSchedulesRepresentative']
) => {
  const selectedDays: any = {
    pair: {},
    impair: {},
  };

  // Mapping inverse pour convertir DaysOfWeek vers les clés françaises
  const dayOfWeekToFrenchMap: Record<DaysOfWeek, string> = {
    [DaysOfWeek.MONDAY]: 'lundi',
    [DaysOfWeek.TUESDAY]: 'mardi',
    [DaysOfWeek.WEDNESDAY]: 'mercredi',
    [DaysOfWeek.THURSDAY]: 'jeudi',
    [DaysOfWeek.FRIDAY]: 'vendredi',
    [DaysOfWeek.SATURDAY]: 'samedi',
    [DaysOfWeek.SUNDAY]: 'dimanche',
  };

  transportSchedules.forEach((schedule) => {
    const weekKey = schedule.weekType === WeekType.EVEN ? 'pair' : 'impair';

    schedule.dayScheduleRepresentative.forEach((daySchedule) => {
      const day = dayOfWeekToFrenchMap[daySchedule.dayOfWeek];
      if (!selectedDays[weekKey][day]) {
        selectedDays[weekKey][day] = { all: false, ret: false };
      }

      if (daySchedule.sens === SensTrip.DEPARTURE) {
        selectedDays[weekKey][day].all = true;
      } else if (daySchedule.sens === SensTrip.RETURN) {
        selectedDays[weekKey][day].ret = true;
      }
    });
  });

  return selectedDays;
};

export const convertSelectedDaysToSchedules = (selectedDays: any): TransportSchedule[] => {
  const transportSchedules: TransportSchedule[] = [
    {
      id: '',
      weekType: WeekType.EVEN,
      dayScheduleRepresentative: [] as DaySchedule[],
    },
    {
      id: '',
      weekType: WeekType.ODD,
      dayScheduleRepresentative: [] as DaySchedule[],
    },
  ];

  const dayMap: Record<string, DaysOfWeek> = {
    lundi: DaysOfWeek.MONDAY,
    mardi: DaysOfWeek.TUESDAY,
    mercredi: DaysOfWeek.WEDNESDAY,
    jeudi: DaysOfWeek.THURSDAY,
    vendredi: DaysOfWeek.FRIDAY,
    samedi: DaysOfWeek.SATURDAY,
    dimanche: DaysOfWeek.SUNDAY,
  };

  Object.entries(selectedDays.pair || {}).forEach(([day, value]: [string, any]) => {
    if (dayMap[day]) {
      if (value.all) {
        transportSchedules[0].dayScheduleRepresentative.push({
          id: '',
          dayOfWeek: dayMap[day],
          sens: SensTrip.DEPARTURE,
          checked: true,
        });
      }
      if (value.ret) {
        transportSchedules[0].dayScheduleRepresentative.push({
          id: '',
          dayOfWeek: dayMap[day],
          sens: SensTrip.RETURN,
          checked: true,
        });
      }
    }
  });

  Object.entries(selectedDays.impair || {}).forEach(([day, value]: [string, any]) => {
    if (dayMap[day]) {
      if (value.all) {
        transportSchedules[1].dayScheduleRepresentative.push({
          id: '',
          dayOfWeek: dayMap[day],
          sens: SensTrip.DEPARTURE,
          checked: true,
        });
      }
      if (value.ret) {
        transportSchedules[1].dayScheduleRepresentative.push({
          id: '',
          dayOfWeek: dayMap[day],
          sens: SensTrip.RETURN,
          checked: true,
        });
      }
    }
  });

  return transportSchedules;
};

/**
 * Mappe les données du backend vers la structure du composant EtablissementJoursField
 */
export function mapAmendmentToEstablishmentSchedules(
  amendment: AmendmentPassengerDetails,
  establishmentNames?: Record<number, string>
): EstablishmentSchedule[] {
  if (!amendment.establishmentWeekPassengerMap) {
    return [];
  }

  return amendment.establishmentWeekPassengerMap.map((establishmentData) => ({
    id: establishmentData.establishmentId.toString(),
    idEstablishment: establishmentData.establishmentId,
    establishmentName:
      establishmentNames?.[establishmentData.establishmentId] ||
      `Établissement ${establishmentData.establishmentId}`,
    dayScheduleEstablishments: establishmentData.transportScheduleAmendments.map(
      (scheduleAmendment) => ({
        id: scheduleAmendment.id || '',
        weekType: scheduleAmendment.weekType as any,
        schedules: scheduleAmendment.dayScheduleAmendment
          .filter((amendment) => amendment.isAssignmentDayInWeek === true)
          .map((amendment, index) => ({
            id: `schedule-${index}`,
            dayOfWeek: amendment.dayOfWeek,
            periodOfDay: amendment.periodOfDay,
          })),
      })
    ),
  }));
}

/**
 * Mappe les données du composant vers la structure backend
 */
export function mapEstablishmentSchedulesToAmendment(
  establishmentSchedules: EstablishmentSchedule[],
  originalAmendment: AmendmentPassengerDetails
): AmendmentPassengerDetails {
  const establishmentWeekPassengerMap = establishmentSchedules.map((establishment) => ({
    establishmentId: establishment.idEstablishment,
    transportScheduleAmendments: establishment.dayScheduleEstablishments.map((weekSchedule) => ({
      id: weekSchedule.id || null,
      weekType: weekSchedule.weekType,
      dayScheduleAmendment: weekSchedule.schedules.map((daySchedule) => ({
        dayOfWeek: daySchedule.dayOfWeek,
        periodOfDay: daySchedule.periodOfDay,
        isAssignmentDayInWeek: true,
      })),
    })),
  }));

  return {
    ...originalAmendment,
    establishmentWeekPassengerMap,
  };
}
