import * as Yup from 'yup';
import {
  CustodyCategory,
  ParticularityTransport,
  SchoolClass,
  State,
  RelationType,
  WeekType,
  DaysOfWeek,
  SensTrip,
} from '@/shared/types/passenger';
import { Civility } from '@/shared/types/common';
import { AddressType } from '@/shared/types/establishment';

export const representativeSchema = Yup.object().shape({
  id: Yup.string(),
  firstName: Yup.string().required('Le prénom est requis'),
  lastName: Yup.string().required('Le nom est requis'),
  email: Yup.string().email('Format email invalide').nullable(),
  civility: Yup.string().oneOf(Object.values(Civility), 'Civilité invalide'),
  type: Yup.string().oneOf(Object.values(RelationType), 'Type de relation invalide').nullable(),
  parentalAuthorization: Yup.boolean(),
  arrivalNotification: Yup.boolean(),
  circuitId: Yup.string().nullable(),
  circuitCode: Yup.string().nullable(),
  contacts: Yup.array().of(
    Yup.object().shape({
      landlinePhoneNumbers: Yup.array()
        .of(
          Yup.string().matches(
            /^\+?[0-9]{10,}$/,
            'Le numéro de téléphone doit contenir au moins 10 chiffres et peut commencer par +'
          )
        )
        .nullable()
        .notRequired(),

      mobilePhoneNumbers: Yup.array()
        .of(
          Yup.string().matches(
            /^\+?[0-9]{10,}$/,
            'Le numéro de téléphone doit contenir au moins 10 chiffres et peut commencer par +'
          )
        )
        .nullable()
        .notRequired(),

      assignedPersonNames: Yup.array().of(Yup.string()).nullable().notRequired(),
    })
  ),
  addresses: Yup.array()
    .of(
      Yup.object().shape({
        additionalAddress: Yup.string().required("L'adresse est requise"),
        latitude: Yup.number().required('La latitude est requise'),
        longitude: Yup.number().required('La longitude est requise'),
        addressType: Yup.string().required("Le type d'adresse est requis"),
      })
    )
    .test('has-representative-address', "L'adresse est requise", function (value) {
      return value && value.some((addr) => addr.addressType === AddressType.REPRESENTATIVE);
    }),
  transportSchedulesRepresentative: Yup.array().of(
    Yup.object().shape({
      weekType: Yup.string()
        .oneOf(Object.values(WeekType), 'Type de semaine invalide')
        .required('Le type de semaine est requis'),
      dayScheduleRepresentative: Yup.array().of(
        Yup.object().shape({
          dayOfWeek: Yup.string()
            .oneOf(Object.values(DaysOfWeek), 'Jour de la semaine invalide')
            .required('Le jour de la semaine est requis'),
          sens: Yup.string()
            .oneOf(Object.values(SensTrip), 'Sens de trajet invalide')
            .required('Le sens de trajet est requis'),
          checked: Yup.boolean(),
        })
      ),
    })
  ),
});

export const otherInterlocutorsSchema = Yup.object().shape({
  civility: Yup.string().oneOf(Object.values(Civility), 'Civilité invalide').nullable(),
  firstName: Yup.string().required('Le nom est requis'),
  lastName: Yup.string().required('Le prénom est requis'),
  mobilePhone: Yup.string()
    .matches(
      /^\+?[0-9]{10,}$/,
      'Le numéro de téléphone doit contenir au moins 10 chiffres et peut commencer par +'
    )
    .nullable(),
  email: Yup.string().email('Email invalide').nullable(),
  type: Yup.string().oneOf(Object.values(RelationType), 'Type de relation invalide').nullable(),
  observation: Yup.string(),
});

export const usagerSchema = Yup.object().shape({
  firstName: Yup.string().required('Le prénom est requis'),
  lastName: Yup.string().required('Le nom est requis'),
  email: Yup.string().email('Format email invalide').required('Email est requis'),
  birthDate: Yup.date()
    .nullable()
    .required('La date de naissance est requise')
    .test(
      'birth-date-in-the-past',
      'La date de naissance est invalide : elle doit être une date dans le passé.',
      function (value) {
        if (!value) return false;
        return value < new Date();
      }
    ),
  birthPlace: Yup.string().required('Le lieu de naissance est requis'),
  state: Yup.string().oneOf(Object.values(State), 'État invalide'),

  idDepartment: Yup.number()
    .test(
      'is-greater-than-zero',
      'Le département est requis',
      (value) => value !== undefined && value > 0
    )
    .required('Le département est requis'),
  establishmentTransportSchedules: Yup.array()
    .of(
      Yup.object().shape({
        idEstablishment: Yup.number()
          .required("L'établissement est requis")
          .test(
            'is-greater-than-zero',
            "L'établissement doit être valide",
            (value) => value !== undefined && value > 0
          ),
        establishmentName: Yup.string(),
      })
    )
    .min(1, 'Au moins un établissement doit être sélectionné')
    .required('Les établissements de transport sont requis')
    .test(
      'no-duplicate-establishments',
      'Vous ne pouvez pas sélectionner le même établissement plusieurs fois',
      function (value) {
        if (!value || !Array.isArray(value)) return true;
        const establishmentIds = value.map((item) => item.idEstablishment).filter((id) => id > 0);
        const uniqueIds = new Set(establishmentIds);
        return establishmentIds.length === uniqueIds.size;
      }
    ),
  particularityTransport: Yup.string()
    .oneOf(Object.values(ParticularityTransport), 'Particularité de transport invalide')
    .nullable(),
  custodyCategory: Yup.string().oneOf(
    Object.values(CustodyCategory),
    'Catégorie de garde invalide'
  ),
  schoolClass: Yup.string()
    .oneOf(Object.values(SchoolClass), 'Classe scolaire invalide')
    .nullable(),
  startTransport: Yup.string().required('La date de début du transport est requise'),
  openingDays: Yup.string().nullable(),
  specificity: Yup.string(),
  referentTeacherName: Yup.string(),
  observations: Yup.string(),

  representatives: Yup.array().of(representativeSchema),
  interlocutor: otherInterlocutorsSchema.nullable(),
});

export const avenantUsagerSchema = Yup.object().shape({
  startDate: Yup.string().required("La date d'application est requise"),
  subject: Yup.string().required("L'objet de l'avenant est requis"),
  specificity: Yup.string(),
  amendmentType: Yup.string().nullable(),
  observation: Yup.string(),
  actionType: Yup.string().nullable(),
  endDate: Yup.string().required('La date de fin est requise'),
  establishmentWeekPassengerMap: Yup.array()
    .of(
      Yup.object().shape({
        establishmentId: Yup.number()
          .required("L'établissement est requis")
          .test(
            'is-greater-than-zero',
            "L'établissement doit être valide",
            (value) => value !== undefined && value > 0
          ),
      })
    )
    .min(1, 'Au moins un établissement doit être sélectionné')
    .required('Les établissements de transport sont requis')
    .test(
      'no-duplicate-establishments',
      'Vous ne pouvez pas sélectionner le même établissement plusieurs fois',
      function (value) {
        if (!value || !Array.isArray(value)) return true;
        const establishmentIds = value.map((item) => item.establishmentId).filter((id) => id > 0);
        const uniqueIds = new Set(establishmentIds);
        return establishmentIds.length === uniqueIds.size;
      }
    ),
});
