import { CostType, Tour } from '@prisma/client';
import { addDays, isSameDay, isWeekend, isWithinInterval } from 'date-fns';
import { toZonedTime } from 'date-fns-tz';
import { generateIntervalForTimeRange } from 'src/utils';
import { INFECTION_TYPES } from './infection-types';
import { PUBLIC_HOLIDAYS_HH } from './public-holidays';

export function calculatePrivatVersicherung(
  tour: Tour,
  costType: CostType,
): number {
  if (
    tour.category?.indexOf('Privatfahrt Rechnung') === -1 &&
    tour.category?.indexOf('Barzahlung') === -1
  ) {
    if (costType.description === 'Hygienemaßnahmen' && tour.hasInfection) {
      return 0;
    }
    return costType.costAmount;
  }
  return 0;
}

export function calculateDesinfektionszuschlag(
  tour: Tour,
  costType: CostType,
): number {
  if (tour.hasInfection && !tour.infectionName) {
    return 0;
  }
  if (
    tour.hasInfection &&
    (tour.infectionName.indexOf(costType.infectionType) > -1 ||
      INFECTION_TYPES[tour.infectionName] === costType.infectionType)
  ) {
    return costType.costAmount;
  }
  return 0;
}

export function calculateTSW(tour: Tour, costType: CostType): number {
  if (costType.description.includes('TS+R') && tour.transportType === 'TS+R') {
    return costType.costAmount;
  } else if (
    (costType.description.includes('TS 1') ||
      costType.description.includes('TSW 1')) &&
    (tour.transportType === 'tsw' || tour.transportType === 'TS1')
  ) {
    return costType.costAmount;
  } else if (
    (costType.description.includes('TS 2') ||
      costType.description.includes('TSW 2')) &&
    (tour.transportType === 'TS+T' || tour.transportType === 'TS2')
  ) {
    return costType.costAmount;
  }
  return 0;
}

export function calculateFeiertagszuschlag(
  tour: Tour,
  costType: CostType,
): number {
  if (
    PUBLIC_HOLIDAYS_HH.some((day) =>
      isSameDay(
        new Date(day),
        new Date(toZonedTime(tour.startDate, 'Europe/Berlin')),
      ),
    )
  ) {
    return costType.costAmount;
  }
  return 0;
}

export function calculateNachtzuschlag(tour: Tour, costType: CostType): number {
  const firstInterval = generateIntervalForTimeRange(
    costType.timeRange,
    'Europe/Berlin',
    addDays(tour.startDate, -1),
  );
  const secondInterval = generateIntervalForTimeRange(
    costType.timeRange,
    'Europe/Berlin',
    tour.startDate,
  );
  if (
    isWithinInterval(tour.startDate, firstInterval) ||
    isWithinInterval(tour.startDate, secondInterval)
  ) {
    return costType.costAmount;
  }
  return 0;
}

export function calculateKilometerzuschlag(
  tour: Tour,
  costType: CostType,
): number {
  const kilometerOverLimit = Math.ceil(tour.occupiedKm - costType.kmInclusive);
  if (kilometerOverLimit <= 0) return 0;
  return costType.costAmount * kilometerOverLimit;
}

export function calculateFahrzeugzuschlag(
  tour: Tour,
  costType: CostType,
): number {
  const isCarNameSupported = !costType.excludeCarNames.includes(tour.carName);
  if (!isCarNameSupported) return 0;
  return costType.costAmount;
}

export function calculateWochenendzuschlag(
  tour: Tour,
  costType: CostType,
): number {
  if (isWeekend(toZonedTime(tour.startDate, 'Europe/Berlin')))
    return costType.costAmount;
  return 0;
}
