import { z } from "zod"

import { countriesMap } from "@/components/TempDesignSystem/Form/Country/countries"
import { getMembership } from "@/utils/user"

export const membershipSchema = z.object({
  currentPoints: z.number(),
  expirationDate: z.string(),
  membershipNumber: z.string(),
  membershipLevel: z.string().optional(),
  memberSince: z.string(),
  membershipType: z.string(),
  nextLevel: z.string().optional(),
  nightsToTopTier: z.number().optional(),
  pointsExpiryDate: z.string().optional(),
  pointsRequiredToNextlevel: z.number().optional(),
  pointsToExpire: z.number().optional(),
  tierExpirationDate: z.string().optional(),
})

export const getUserSchema = z
  .object({
    data: z.object({
      attributes: z.object({
        address: z.object({
          city: z.string().optional(),
          country: z.string().optional(),
          countryCode: z.nativeEnum(countriesMap).optional(),
          streetAddress: z.string().optional(),
          zipCode: z.string().optional(),
        }),
        dateOfBirth: z.string().optional().default("1900-01-01"),
        email: z.string().email(),
        firstName: z.string(),
        language: z.string().optional(),
        lastName: z.string(),
        memberships: z.array(membershipSchema),
        phoneNumber: z.string().optional(),
        profileId: z.string(),
      }),
      type: z.string(),
    }),
  })
  .transform((apiResponse) => {
    return {
      ...apiResponse.data.attributes,
      membership: getMembership(apiResponse.data.attributes.memberships),
      name: `${apiResponse.data.attributes.firstName} ${apiResponse.data.attributes.lastName}`,
    }
  })

// Schema is the same for upcoming and previous stays endpoints
export const getStaysSchema = z.object({
  data: z.array(
    z.object({
      attributes: z.object({
        hotelOperaId: z.string(),
        hotelInformation: z.object({
          hotelContent: z.object({
            images: z.object({
              metaData: z.object({
                title: z.string(),
                altText: z.string(),
                altText_En: z.string(),
                copyRight: z.string(),
              }),
              imageSizes: z.object({
                tiny: z.string(),
                small: z.string(),
                medium: z.string(),
                large: z.string(),
              }),
            }),
          }),
          hotelName: z.string(),
          cityName: z.string().nullable(),
        }),
        confirmationNumber: z.string(),
        checkinDate: z.string(),
        checkoutDate: z.string(),
        isWebAppOrigin: z.boolean(),
        bookingUrl: z.string().default(""),
      }),
      relationships: z.object({
        hotel: z.object({
          links: z.object({
            related: z.string().nullable().optional(),
          }),
          data: z.object({
            id: z.string(),
            type: z.string(),
          }),
        }),
      }),
      type: z.string(),
      id: z.string(),
      links: z.object({
        self: z.object({
          href: z.string(),
          meta: z.object({
            method: z.string(),
          }),
        }),
      }),
    })
  ),
  links: z
    .object({
      self: z.string(),
      offset: z.number(),
      limit: z.number(),
      totalCount: z.number(),
    })
    .optional()
    .nullable(),
})

type GetStaysData = z.infer<typeof getStaysSchema>

export type Stay = GetStaysData["data"][number]

export const getFriendTransactionsSchema = z.object({
  data: z.array(
    z.object({
      attributes: z.object({
        awardPoints: z.number().default(0),
        checkinDate: z.string().default(""),
        checkoutDate: z.string().default(""),
        confirmationNumber: z.string().default(""),
        hotelOperaId: z.string().default(""),
        nights: z.number().default(1),
        pointsCalculated: z.boolean().default(true),
        transactionDate: z.string().default(""),
        bookingUrl: z.string().default(""),
        hotelInformation: z
          .object({
            city: z.string().default(""),
            name: z.string().default(""),
            hotelContent: z.object({
              images: z.object({
                metaData: z.object({
                  title: z.string(),
                  altText: z.string(),
                  altText_En: z.string(),
                  copyRight: z.string(),
                }),
                imageSizes: z.object({
                  tiny: z.string(),
                  small: z.string(),
                  medium: z.string(),
                  large: z.string(),
                }),
              }),
            }),
          })
          .optional(),
      }),
      relationships: z.object({
        booking: z.object({
          data: z.object({
            id: z.string().default(""),
            type: z.string().default(""),
          }),
          links: z.object({
            related: z.string().default(""),
          }),
        }),
        hotel: z
          .object({
            data: z.object({
              id: z.string().default(""),
              type: z.string().default(""),
            }),
            links: z.object({
              related: z.string().default(""),
            }),
          })
          .optional(),
      }),
      type: z.string().default(""),
    })
  ),
  links: z
    .object({
      self: z.string(),
    })
    .nullable(),
})

type GetFriendTransactionsData = z.infer<typeof getFriendTransactionsSchema>

export type FriendTransaction = GetFriendTransactionsData["data"][number]

export const creditCardSchema = z
  .object({
    attribute: z.object({
      cardName: z.string().optional(),
      alias: z.string(),
      truncatedNumber: z.string().transform((s) => s.slice(-4)),
      expirationDate: z.string(),
      cardType: z
        .string()
        .transform((s) => s.charAt(0).toLowerCase() + s.slice(1)),
    }),
    id: z.string(),
    type: z.string(),
  })
  .transform((apiResponse) => {
    return {
      id: apiResponse.id,
      type: apiResponse.attribute.cardType,
      truncatedNumber: apiResponse.attribute.truncatedNumber,
      alias: apiResponse.attribute.alias,
      expirationDate: apiResponse.attribute.expirationDate,
      cardType: apiResponse.attribute.cardType,
    }
  })

export const creditCardsSchema = z.object({
  data: z.array(creditCardSchema),
})

export const getMembershipCardsSchema = z.array(
  z.object({
    currentPoints: z.number(),
    expirationDate: z.string(),
    membershipNumber: z.string(),
    memberSince: z.string(),
    membershipType: z.string(),
  })
)

export const initiateSaveCardSchema = z.object({
  data: z.object({
    attribute: z.object({
      transactionId: z.string(),
      link: z.string(),
      mobileToken: z.string().optional(),
    }),
    type: z.string(),
  }),
})

export const subscriberIdSchema = z.object({
  subscriberId: z.string(),
})
