import { z } from "zod"
import { i18n } from "@components/utilities/i18n/i18n"
import { optionalFloat, optionalInt } from "@lib/validation"
import { decorateVariantsWithDefaultValues } from "./utils"

export const MediaSchema = z.object({
  id: z.string().optional(),
  url: z.string(),
  isThumbnail: z.boolean(),
  file: z.any().nullable(), // File
})

const ProductCreateVariantSchema = z.object({
  should_create: z.boolean(),
  is_default: z.boolean().optional(),
  title: z.string(),
  upc: z.string().optional(),
  ean: z.string().optional(),
  barcode: z.string().optional(),
  mid_code: z.string().optional(),
  hs_code: z.string().optional(),
  width: optionalInt,
  height: optionalInt,
  length: optionalInt,
  weight: optionalInt,
  material: z.string().optional(),
  origin_country: z.string().optional(),
  sku: z.string().optional(),
  manage_inventory: z.boolean().optional(),
  allow_backorder: z.boolean().optional(),
  inventory_kit: z.boolean().optional(),
  options: z.record(z.string(), z.string()),
  variant_rank: z.number(),
  prices: z.record(z.string(), optionalFloat).optional(),
  inventory: z
    .array(
      z.object({
        inventory_item_id: z.string(),
        required_quantity: optionalInt,
      })
    )
    .optional(),
  media: z.array(MediaSchema).optional(),
})

export type ProductCreateVariantSchema = z.infer<
  typeof ProductCreateVariantSchema
>

export const ProductCreateOptionSchema = z.object({
  title: z.string().min(1, i18n.t("products.fields.attributes.add.title.required")),
  values: z.array(z.string()).min(1, i18n.t("products.fields.attributes.add.values.required")),
  metadata: z.record(z.unknown()).optional(),
  useForVariants: z.boolean().optional(),
  attributeId: z.string().optional(),
})

export type ProductCreateOptionSchemaType = z.infer<
  typeof ProductCreateOptionSchema
>

export const ProductCreateBaseSchema = z.object({
  title: z.string().min(1, i18n.t("products.fields.title.required")),
  subtitle: z.string().optional(),
  handle: z.string().optional(),
  description: z.string().optional(),
  discountable: z.boolean(),
  type_id: z.string().optional(),
  collection_id: z.string().optional(),
  shipping_profile_id: z.string().optional(),
  categories: z.array(z.string()).min(1, i18n.t("products.create.errors.primaryCategoryRequired")),
  secondary_categories: z.array(z.string()).optional(),
  tags: z.array(z.string()).optional(),
  sales_channels: z
    .array(
      z.object({
        id: z.string(),
        name: z.string(),
      })
    )
    .optional(),
  origin_country: z.string().optional(),
  material: z.string().optional(),
  width: z.string().optional(),
  length: z.string().optional(),
  height: z.string().optional(),
  weight: z.string().optional(),
  mid_code: z.string().optional(),
  hs_code: z.string().optional(),
  options: z.array(ProductCreateOptionSchema),
  enable_variants: z.boolean(),
  variants: z.array(ProductCreateVariantSchema).min(1),
  media: z.array(MediaSchema).optional(),
})

export const ProductCreateSchema = ProductCreateBaseSchema
  .superRefine((data, ctx) => {
    if (data.variants.every((v) => !v.should_create)) {
      return ctx.addIssue({
        code: z.ZodIssueCode.custom,
        path: ["variants"],
        message: "invalid_length",
      })
    }

    const skus = new Set<string>()

    data.variants.forEach((v, index) => {
      if (v.sku) {
        if (skus.has(v.sku)) {
          ctx.addIssue({
            code: z.ZodIssueCode.custom,
            path: [`variants.${index}.sku`],
            message: i18n.t("products.create.errors.uniqueSku"),
          })
        }

        skus.add(v.sku)
      }
    })
  })

export const EditProductMediaSchema = z.object({
  media: z.array(MediaSchema),
})

export const PRODUCT_CREATE_FORM_DEFAULTS: Partial<
  z.infer<typeof ProductCreateSchema>
> = {
  discountable: false,
  tags: [],
  sales_channels: [],
  options: [],
  variants: decorateVariantsWithDefaultValues([
    {
      title: i18n.t("products.create.defaults.variantTitle"),
      should_create: true,
      variant_rank: 0,
      options: {
        [i18n.t("products.create.defaults.optionTitle")]: i18n.t(
          "products.create.defaults.optionValue"
        ),
      },
      inventory: [{ inventory_item_id: "", required_quantity: "" }],
      is_default: true,
    },
  ]),
  enable_variants: false,
  media: [],
  categories: [],
  secondary_categories: [],
  collection_id: "",
  shipping_profile_id: "",
  description: "",
  handle: "",
  height: "",
  hs_code: "",
  length: "",
  material: "",
  mid_code: "",
  origin_country: "",
  subtitle: "",
  title: "",
  type_id: "",
  weight: "",
  width: "",
}
