import { z } from 'zod';
import { UpdateShoppingCartItem } from '../models';
import { EntityContainerSchema, PriceSchema } from '@isa/common/data-access';
import { AvailabilitySchema } from './availability.schema';
import { CampaignSchema } from './campaign.schema';
import { DestinationSchema } from './destination.schema';
import { LoyaltySchema } from './loyalty.schema';
import { PromotionSchema } from './promotion.schema';

const UpdateShoppingCartItemParamsValueDefaultSchema = z.object({
  availability: AvailabilitySchema.describe(
    'Availability information',
  ).optional(),
  buyerComment: z.string().describe('Buyer comment text').optional(),
  campaign: CampaignSchema.describe('Campaign information').optional(),
  destination: EntityContainerSchema(DestinationSchema)
    .optional()
    .describe('Destination information'),
  loyalty: LoyaltySchema.describe('Loyalty information').optional(),
  promotion: PromotionSchema.describe('Promotion information').optional(),
  quantity: z.number().int().positive().describe('Item quantity').optional(),
  retailPrice: PriceSchema.describe('Retail price').optional(),
  specialComment: z.string().describe('Special comment text').optional(),
});

// When loyalty points are used the price value must be 0 and promotion is not allowed
// and availability must not contain a price
// and loyalty must be present
const UpdateShoppingCartItemParamsValueWithRedemptionPointsSchema =
  UpdateShoppingCartItemParamsValueDefaultSchema.omit({
    availability: true,
    promotion: true,
  }).extend({
    availability: AvailabilitySchema.omit({ price: true })
      .extend({
        price: PriceSchema.omit({ value: true })
          .extend({
            value: z
              .object({
                value: z
                  .literal(0)
                  .describe('Price value must be 0 for loyalty redemption'),
                currency: z.string().describe('Currency code'),
              })
              .describe('Price value object'),
          })
          .describe('Price information for loyalty redemption'),
      })
      .describe('Availability information for loyalty redemption'),
    loyalty: LoyaltySchema.describe(
      'Loyalty information for points redemption',
    ),
  });

const UpdateShoppingCartItemParamsValueSchema = z
  .union([
    UpdateShoppingCartItemParamsValueDefaultSchema,
    UpdateShoppingCartItemParamsValueWithRedemptionPointsSchema,
  ])
  .describe('Update shopping cart item params value');

export const UpdateShoppingCartItemParamsSchema = z.object({
  shoppingCartId: z
    .number()
    .int()
    .positive()
    .describe('Shopping cart identifier'),
  shoppingCartItemId: z
    .number()
    .int()
    .positive()
    .describe('Shopping cart item identifier'),
  values: UpdateShoppingCartItemParamsValueSchema.describe(
    'Updated values for the cart item',
  ),
});

export type UpdateShoppingCartItemParams = {
  shoppingCartId: number;
  shoppingCartItemId: number;
  values: UpdateShoppingCartItem;
};
