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.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.id || "",
                    idEstablishment: establishment.idEstablishment,
                    establishmentName: establishment.establishmentName,
                    weekType: WeekType.EVEN,
                    dayScheduleEstablishments: [],
                },
            ]
        }

        const result = Object.entries(schedulesByWeekType).map(([weekType, daySchedules]) => ({
            id: establishment.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,
  }
}
