import { PeriodOfDay } from '@/shared/types/ammendment-passenger';
import { SensTrip, TripCircuitDTO } from '@/shared/types/circuit';

export const convertDurationToMinutes = (duration: string): number => {
  if (!duration) return 0;
  const parts = duration.split(':');
  const hours = parseInt(parts[0] || '0', 10);
  const minutes = parseInt(parts[1] || '0', 10);
  return hours * 60 + minutes;
};

export const getTripTimeForPassenger = (trip: TripCircuitDTO, passengerId: number): string => {
  const passengerDay = trip.tripCircuitDays?.find(day =>
    day.passengerInfoTrip?.passengerId === passengerId
  );
  return passengerDay?.passengerInfoTrip?.departureTime || '-';
};

export const separateTripsByDirection = (circuitTripDetails: TripCircuitDTO[]) => {
  if (!circuitTripDetails || circuitTripDetails.length === 0) {
    return { departures: [], returns: [] };
  }

  const departures = circuitTripDetails.filter(trip => trip.sensTrip === 'DEPARTURE');
  const returns = circuitTripDetails.filter(trip => trip.sensTrip === 'RETURN');

  return { departures, returns };
};

export const formatAddress = (address: any): string => {
  if (!address) return 'N/A';

  const parts = [];
  if (address.street) parts.push(address.street);
  if (address.city) parts.push(address.city);
  if (address.zipCode) parts.push(address.zipCode);
  if (address.country) parts.push(address.country);

  return parts.length > 0 ? parts.join(', ') : 'N/A';
};

export const extractUniquePassengers = (circuitTripDetails: TripCircuitDTO[]) => {
  if (!circuitTripDetails || circuitTripDetails.length === 0) {
    return [];
  }

  const passengersMap = new Map<string, {
    id: number;
    name: string;
    establishment: string;
    phone: string;
    address: string;
    latitude?: number;
    longitude?: number;
  }>();

  circuitTripDetails.forEach(trip => {
    trip.passengerInfo?.forEach(passenger => {
      const passengerTripInfo = trip.tripCircuitDays?.find(day =>
        day.passengerInfoTrip?.passengerId === passenger.id
      );

      const establishment = trip.tripCircuitDays?.find(day => day.establishmentInfoTrip)
        ?.establishmentInfoTrip?.establishmentName || 'N/A';

      const phone = passengerTripInfo?.passengerInfoTrip?.representativePhoneNumber || 'N/A';
      const rawAddress = passengerTripInfo?.passengerInfoTrip?.passengerAddress as any;
      const address = rawAddress.additionalAddress ? rawAddress.additionalAddress : formatAddress(rawAddress);

      const latKey = passengerTripInfo?.passengerInfoTrip?.pickupCoordinates?.latitude ?? 'N/A';
      const lonKey = passengerTripInfo?.passengerInfoTrip?.pickupCoordinates?.longitude ?? 'N/A';
      const compositeKey = `${passenger.id}::${latKey}::${lonKey}`;
      if (!passengersMap.has(compositeKey)) {
        passengersMap.set(compositeKey, {
          id: passenger.id,
          name: passenger.name,
          establishment: establishment,
          phone: phone,
          address: address,
          latitude: typeof passengerTripInfo?.passengerInfoTrip?.pickupCoordinates?.latitude === 'number' ? passengerTripInfo?.passengerInfoTrip?.pickupCoordinates?.latitude : undefined,
          longitude: typeof passengerTripInfo?.passengerInfoTrip?.pickupCoordinates?.longitude === 'number' ? passengerTripInfo?.passengerInfoTrip?.pickupCoordinates?.longitude : undefined,
        });
      }
    });
  });

  return Array.from(passengersMap.values());
};

export const extractUniqueEstablishments = (circuitTripDetails: TripCircuitDTO[]) => {
  if (!circuitTripDetails || circuitTripDetails.length === 0) {
    return [];
  }

  const establishmentsMap = new Map<string, {
    name: string;
    phone: string;
    address: string;
    arrivalTime: string;
  }>();

  circuitTripDetails.forEach(trip => {
    trip.tripCircuitDays?.forEach(day => {
      if (day.establishmentInfoTrip) {
        const establishment = day.establishmentInfoTrip;
        const key = establishment.establishmentName;

        if (!establishmentsMap.has(key)) {
          const address = formatAddress(establishment.establishmentAddress);

          establishmentsMap.set(key, {
            name: establishment.establishmentName,
            phone: establishment.establishmentPhoneNumber || 'N/A',
            address: address,
            arrivalTime: establishment.arrivalTime || 'N/A'
          });
        }
      }
    });
  });

  return Array.from(establishmentsMap.values());
};

export const getObservationSchedulesForPassenger = (
  circuitTripDetails: TripCircuitDTO[],
  passengerId: number,
  coords?: { latitude?: number; longitude?: number }
) => {
  const schedules: any[] = [];
  circuitTripDetails.forEach(trip => {
    trip.tripCircuitDays?.forEach(day => {
      const isSamePassenger = day.passengerInfoTrip?.passengerId === passengerId;
      const dayLat = (day.passengerInfoTrip?.pickupCoordinates as any)?.latitude;
      const dayLon = (day.passengerInfoTrip?.pickupCoordinates as any)?.longitude;
      const isSameAddress = coords?.latitude != null && coords?.longitude != null
        ? (dayLat === coords.latitude && dayLon === coords.longitude)
        : true;
      if (isSamePassenger && isSameAddress) {
        day.observationSchedule?.forEach(obs => {
          let existingSchedule = schedules.find(s => s.weekType === obs.weekType);

          if (!existingSchedule) {
            existingSchedule = {
              id: obs.weekType || '',
              weekType: obs.weekType,
              schedules: []
            };
            schedules.push(existingSchedule);
          }

          obs.periods?.forEach(period => {
            period.dayOfWeek?.forEach(dayOfWeek => {

              const exists = existingSchedule.schedules.some((s: any) =>
                s.dayOfWeek === dayOfWeek && s.periodOfDay === period.periodOfDay
              );

              if (!exists) {
                existingSchedule.schedules.push({
                  id: '',
                  dayOfWeek: dayOfWeek,
                  periodOfDay: period.periodOfDay
                });
              }
            });
          });
        });
      }
    });
  });

  return schedules;
};

export const calculateTotalDuration = (circuitTripDetails: TripCircuitDTO[]): number => {
  return circuitTripDetails.reduce((sum, trip) =>
    sum + convertDurationToMinutes(trip.duration || ''), 0
  );
};

export const calculateTotalDistance = (circuitTripDetails: TripCircuitDTO[]): number => {
  return Number(circuitTripDetails.reduce((sum, trip) =>
    sum + (trip.distanceKm || 0), 0
  ).toFixed(3));
};

export const calculateMaxPassengers = (circuitTripDetails: TripCircuitDTO[]): number => {
  return Math.max(...circuitTripDetails.map(trip => trip.passengerCount || 0));
};

export const formatTripId = (tripId: string, length: number = 6): string => {
  return tripId.slice(-length);
};

export const formatDistance = (distance: number): string => {
  return distance.toFixed(3);
};