import * as z from 'zod';

export const BookTimeResponseSchema = z.object({
  Value: z.string(),
  Data: z.null(),
  ErrorCode: z.number(),
  ErrorMessage: z.null(),
});
export type BookTimeResponse = z.infer<typeof BookTimeResponseSchema>;

export enum ConnectedOnlineMethodName {
  SearchLoad = 'Search_Load',
  DefaultLoad = 'Default_Load',
  ConfirmedCancel = 'Confirmed_Cancel',
  GetAvailabilities = 'GetAvailabilities',
  BookTime = 'BookTime',
  ConfirmedLoad = 'Confirmed_Load',
}

export const AvailableAppointmentTBookingSchema = z.object({
  ClinicID: z.number(),
  LocationID: z.number(),
  UserID: z.number(),
  SyncUserID: z.number(),
  ServiceID: z.number(),
  HKServiceID: z.number(),
  StartTime: z.coerce.date(),
  EndTime: z.coerce.date(),
  PayorCode: z.string(),
});
export type AvailableAppointment = z.infer<
  typeof AvailableAppointmentTBookingSchema
>;

export const TDocsASchema = z.object({
  List: z.string(),
});
export type TDocsA = z.infer<typeof TDocsASchema>;

export const TServiceSchema = z.object({
  Code: z.string(),
  Name: z.string(),
  Price: z.number(),
  VATType: z.number(),
  HKServiceID: z.union([z.number(), z.null()]),
  Duration: z.union([z.number(), z.null()]),
  Description: z.union([z.string(), z.null()]),
  OnlinePaymentRequired: z.number(),
  TehikServiceCode: z.union([z.string(), z.null()]),
  OnlineHideDuration: z.number(),
  OnlineHidePrice: z.number(),
  PricePeriods: z.string(),
});
export type TService = z.infer<typeof TServiceSchema>;

export const AvailableAppointmentsDataSchema = z.object({
  T_ScheduleType: z.array(z.any()),
  T_Service: z.array(TServiceSchema),
  T_Booking: z.array(AvailableAppointmentTBookingSchema),
  T_DocsAvailable: z.array(TDocsASchema),
  T_DocsAll: z.array(TDocsASchema),
});
export type AvailableAppointmentsData = z.infer<
  typeof AvailableAppointmentsDataSchema
>;

export const AvailableAppointmentsResponseSchema = z.object({
  Value: z.null(),
  Data: AvailableAppointmentsDataSchema,
  ErrorCode: z.number(),
  ErrorMessage: z.union([z.string(), z.null()]),
});
export type AvailableAppointmentsResponse = z.infer<
  typeof AvailableAppointmentsResponseSchema
>;

export const APaymentRequestSchema = z.object({
  ID: z.number(),
  Ref: z.string(),
  AmountTotal: z.number(),
  AmountVat: z.number(),
  PaidAmount: z.union([z.number(), z.null()]),
  Paid: z.union([z.number(), z.null()]),
  Failed: z.union([z.number(), z.null()]),
  PaidAmount1: z.union([z.number(), z.null()]),
  ScheduleID: z.number(),
  PaymentID: z.union([z.number(), z.null()]),
  Created: z.coerce.date(),
  Nonce: z.string(),
  DiscountPercent: z.number(),
  DiscountCode: z.string(),
});
export type APaymentRequest = z.infer<typeof APaymentRequestSchema>;

export const PClinicSchema = z.object({
  ID: z.number(),
  LicenseID: z.number(),
  Name: z.string(),
  Email: z.string(),
  Address: z.string(),
  Address2: z.string(),
  Phone: z.string(),
  VatNo: z.string(),
  RegistryCode: z.string(),
  OID: z.string(),
  PersonalCodeRequired: z.number(),
  OnlineCommentRequired: z.number(),
  OnlineLoginRequired: z.number(),
  OnlineSenderEmail: z.string(),
  OnlineReplyToEmail: z.string(),
  OnlineCCEmail: z.string(),
  OnlineRedirectkUrl: z.string(), // the typo is on their side
  OnlineAllowQueue: z.number(),
});
export type PClinic = z.infer<typeof PClinicSchema>;

export const PJobTitleTranslationSchema = z.object({
  ID: z.number(),
  SyncID: z.number(),
  TextEN: z.string(),
  TextET: z.string(),
  TextFI: z.string(),
  TextRU: z.string(),
  TextLT: z.string(),
  ClinicID: z.number(),
  Deleted: z.number(),
});
export type PJobTitleTranslation = z.infer<typeof PJobTitleTranslationSchema>;

export const PServiceSchema = z.object({
  ID: z.number(),
  NameET: z.string(),
  NameEN: z.string(),
  NameRU: z.string(),
  NameFI: z.string(),
  DescriptionET: z.string(),
  DescriptionEN: z.string(),
  DescriptionRU: z.string(),
  DescriptionFI: z.string(),
  ExtraEmailTextET: z.string(),
  ExtraEmailTextEN: z.string(),
  ExtraEmailTextRU: z.string(),
  ExtraEmailTextFI: z.string(),
});
export type PService = z.infer<typeof PServiceSchema>;

export const ParamSchema = z.object({
  PersonalCodeRequired: z.number(),
  OnlineCommentRequired: z.number(),
  OnlineLoginRequired: z.number(),
  ClinicName: z.string(),
  ClinicID: z.number(),
  OnlineRedirectkUrl: z.string(),
  OnlineAllowQueue: z.number(),
  Key: z.string(),
});
export type Param = z.infer<typeof ParamSchema>;

export const TBookingSchema = z.object({
  ID: z.number(),
  ClinicID: z.number(),
  FirstName: z.string(),
  LastName: z.string(),
  Email: z.string(),
  Phone: z.string(),
  PersonalCode: z.string(),
  Comments: z.string(),
  ServiceName: z.string(),
  DoctorName: z.string(),
  StartTime: z.coerce.date(),
  EndTime: z.coerce.date(),
  Status: z.number(),
  PaymentRequestID: z.number(),
  MailResponse: z.null(), // was not present in test data, might need to be specified in the future
  BookingCode: z.string(),
  LocationName: z.union([z.string(), z.null()]),
  isDR: z.number(),
  LocationID: z.number(),
  ScheduleID: z.number(),
  ServiceID: z.number(),
  ServiceSyncID: z.number(),
  ServiceCode: z.string(),
  ServiceIsRemote: z.number(),
  IsRegistered: z.number(),
  OfferEarlierTime: z.number(),
  EarlierTimeComment: z.string(),
  PartnerCode: z.union([z.number(), z.null()]),
  PartnerCallBackUrl: z.union([z.string(), z.null()]),
  LocationOfficialName: z.union([z.string(), z.null()]),
  LocationAddress1: z.union([z.string(), z.null()]),
  LocationAddress2: z.union([z.string(), z.null()]),
  LocationPhone: z.union([z.string(), z.null()]),
});
export type TBooking = z.infer<typeof TBookingSchema>;

export const TDoctorSchema = z.object({
  ID: z.number(),
  Name: z.string(),
  Prefix: z.string(),
  Photo: z.string(),
  SpokenLanguages: z.string(),
  JobTitleID: z.union([z.number(), z.null()]),
  ClinicID: z.number(),
  Deleted: z.number(),
});
export type TDoctor = z.infer<typeof TDoctorSchema>;

export const ConfirmedLoadDataSchema = z.object({
  T_Booking: z.array(TBookingSchema),
  P_Location: z.array(z.any()),
  P_Clinic: z.array(PClinicSchema),
  A_PaymentRequest: z.array(APaymentRequestSchema),
  P_Service: z.array(PServiceSchema),
  T_Service: z.array(z.any()),
  T_ServiceHK: z.array(z.any()),
  P_JobTitleTranslations: z.array(PJobTitleTranslationSchema),
  T_Doctor: z.array(TDoctorSchema),
  Params: z.array(ParamSchema),
});
export type ConfirmedLoadData = z.infer<typeof ConfirmedLoadDataSchema>;

export const ConfirmedLoadResponseSchema = z.object({
  Value: z.null(),
  Data: ConfirmedLoadDataSchema,
  ErrorCode: z.number(),
  ErrorMessage: z.union([z.string(), z.null()]),
});
export type ConfirmedLoadResponse = z.infer<typeof ConfirmedLoadResponseSchema>;

export type P_JobTitleTranslation = {
  ID: number;
  SyncID: number;
  TextEN: string;
  TextET: string;
  TextFI: string;
  TextRU: string;
  TextLT: string;
  ClinicID: number;
  Deleted: number;
};

export interface ISearchLoadResponse {
  Value: string;
  Data: {
    T_Lic: {
      ID: number;
      Name: string;
      OnlineCanSelectWorker: boolean;
      Address: string;
      Email: string | null;
      PersonalCodeRequired: boolean;
      Phone: string | null;
      Key: string;
    }[];
    T_Service: {
      ID: number;
      ClinicID: number;
      Code: string;
      Description: string | null;
      Display: string;
      Duration: number;
      HasFreeCodes: boolean;
      Name: string;
      NetoDuration: number;
      OnlineHideDuration: number;
      OnlineHidePrice: number;
      Price: number;
      PricePeriods: string | null;
      RequiresPayment: boolean;
      SyncID: string;
    }[];
    T_Doctor: TDoctor[];
    P_JobTitleTranslations: P_JobTitleTranslation[];
  };
  ErrorCode: number;
  ErrorMessage: string;
}

export enum FailureReason {
  BOOKING_FAILED = 'BOOKING_FAILED',
  TIME_SLOT_UNAVAILABLE = 'TIME_SLOT_UNAVAILABLE',
}
