import * as Yup from 'yup';
import { Movement, MovementDocument } from '@/types/api/inventory/movement';

type MovementFormSchemaType = {
  transfer_reason: string;
  transfer_date: string;
  source_warehouse?: {
    value: number;
    label: string;
    area?: string;
    location?: string;
  } | null;
  source_warehouse_id: number;
  destination_warehouse?: {
    value: number;
    label: string;
    area?: string;
    location?: string;
  } | null;
  destination_warehouse_id: number;
  products: {
    product?: {
      value: number;
      label: string;
    } | null;
    product_id: number;
    product_qty: number | string;
  }[];
  deliveries: {
    delivery_cost?: number | string | null;
    delivery_cost_per_item?: number | string | null;
    document?: File | MovementDocument | null;
    document_path?: string | null;
    driver_name?: string | null;
    vehicle_plate?: string | null;
    supplier?: {
      value: number;
      label: string;
    } | null;
    supplier_id?: number | null;
    products: {
      product?: {
        value: number;
        label: string;
      } | null;
      product_id: number;
      product_qty: number | string;
    }[];
  }[];
};

export type ProductSchema = {
  product?: {
    value: number;
    label: string;
  } | null;
  product_id: number;
  product_qty: number | string;
};

export type DeliverySchema = {
  delivery_cost?: number | string | null;
  delivery_cost_per_item?: number | string | null;
  document?: File | MovementDocument | null;
  document_path?: string | null;
  driver_name?: string | null;
  vehicle_plate?: string | null;
  supplier?: {
    value: number;
    label: string;
  } | null;
  supplier_id?: number | null;
  products: {
    product?: {
      value: number;
      label: string;
    } | null;
    product_id: number;
    product_qty: number | string;
  }[];
};

const ProductObjectSchema: Yup.ObjectSchema<ProductSchema> = Yup.object({
  product: Yup.object({
    value: Yup.number().min(1).required(),
    label: Yup.string().required(),
  }).nullable(),
  product_id: Yup.number()
    .required('Produk wajib diisi!')
    .min(1, 'Produk wajib diisi!')
    .typeError('Produk wajib diisi!'),
  product_qty: Yup.number()
    .required('Qty wajib diisi!')
    .min(1, 'Qty minimal 1!')
    .typeError('Qty harus berupa angka!'),
});

const DeliveryProductObjectSchema = Yup.object({
  product: Yup.object({
    value: Yup.number().min(1).required(),
    label: Yup.string().required(),
  }).nullable(),
  product_id: Yup.number()
    .required('Produk wajib diisi!')
    .min(1, 'Produk wajib diisi!')
    .typeError('Produk wajib diisi!'),
  product_qty: Yup.number()
    .required('Qty wajib diisi!')
    .min(1, 'Qty minimal 1!')
    .typeError('Qty harus berupa angka!'),
});

const DeliveryDocumentSchema = Yup.mixed<File | MovementDocument>()
  .nullable()
  .test('fileSize', 'Ukuran dokumen maksimal 5 MB', (value): boolean => {
    if (!value) return true;
    if (value instanceof File) return value.size <= 5 * 1024 * 1024;
    return true;
  });

const DeliveryObjectSchema: Yup.ObjectSchema<DeliverySchema> = Yup.object({
  delivery_cost: Yup.number()
    .transform((value) =>
      isNaN(value) || value === '' || value === null ? undefined : value
    )
    .when('supplier_id', {
      is: (supplier_id: number | null | undefined) =>
        supplier_id !== null && supplier_id !== undefined && supplier_id > 0,
      then: (schema) =>
        schema
          .required('Biaya pengiriman wajib diisi!')
          .min(1, 'Biaya minimal 1!')
          .typeError('Biaya harus berupa angka!'),
      otherwise: (schema) =>
        schema
          .optional()
          .nullable()
          .min(1, 'Biaya minimal 1!')
          .typeError('Biaya harus berupa angka!'),
    }),
  delivery_cost_per_item: Yup.number()
    .transform((value) =>
      isNaN(value) || value === '' || value === null ? undefined : value
    )
    .when('supplier_id', {
      is: (supplier_id: number | null | undefined) =>
        supplier_id !== null && supplier_id !== undefined && supplier_id > 0,
      then: (schema) =>
        schema
          .required('Biaya per item wajib diisi!')
          .min(1, 'Biaya per item minimal 1!')
          .typeError('Biaya per item harus berupa angka!'),
      otherwise: (schema) =>
        schema
          .optional()
          .nullable()
          .min(1, 'Biaya per item minimal 1!')
          .typeError('Biaya per item harus berupa angka!'),
    }),
  document_path: Yup.string().nullable().optional(),
  document_index: Yup.number().optional(),
  document: DeliveryDocumentSchema,
  driver_name: Yup.string().when('supplier_id', {
    is: (supplier_id: number | null | undefined) =>
      supplier_id !== null && supplier_id !== undefined && supplier_id > 0,
    then: (schema) =>
      schema
        .required('Nama sopir wajib diisi!')
        .min(1, 'Nama sopir wajib diisi!'),
    otherwise: (schema) => schema.optional().nullable(),
  }),
  vehicle_plate: Yup.string().when('supplier_id', {
    is: (supplier_id: number | null | undefined) =>
      supplier_id !== null && supplier_id !== undefined && supplier_id > 0,
    then: (schema) =>
      schema
        .required('Plat nomor wajib diisi!')
        .min(1, 'Plat nomor wajib diisi!'),
    otherwise: (schema) => schema.optional().nullable(),
  }),
  supplier: Yup.object({
    value: Yup.number().min(1).required(),
    label: Yup.string().required(),
  }).nullable(),
  supplier_id: Yup.number()
    .optional()
    .nullable()
    .typeError('Supplier harus berupa angka!'),
  products: Yup.array()
    .of(DeliveryProductObjectSchema)
    .min(1, 'Minimal harus ada 1 produk!')
    .required('Produk wajib diisi!'),
});

export const MovementFormSchema: Yup.ObjectSchema<MovementFormSchemaType> =
  Yup.object({
    transfer_reason: Yup.string().required('Alasan transfer wajib diisi!'),
    transfer_date: Yup.string().required('Tanggal transfer wajib diisi!'),
    source_warehouse: Yup.object({
      value: Yup.number().min(1).required(),
      label: Yup.string().required(),
      area: Yup.string().optional(),
      location: Yup.string().optional(),
    }).nullable(),
    source_warehouse_id: Yup.number()
      .required('Gudang asal wajib diisi!')
      .min(1, 'Gudang asal wajib diisi!')
      .typeError('Gudang asal wajib diisi!'),
    destination_warehouse: Yup.object({
      value: Yup.number().min(1).required(),
      label: Yup.string().required(),
      area: Yup.string().optional(),
      location: Yup.string().optional(),
    }).nullable(),
    destination_warehouse_id: Yup.number()
      .required('Gudang tujuan wajib diisi!')
      .min(1, 'Gudang tujuan wajib diisi!')
      .typeError('Gudang tujuan wajib diisi!')
      .test(
        'different-warehouse',
        'Gudang tujuan tidak boleh sama dengan gudang asal!',
        function (value) {
          const { source_warehouse_id } = this.parent;
          return (
            !value || !source_warehouse_id || value !== source_warehouse_id
          );
        }
      ),
    products: Yup.array()
      .of(ProductObjectSchema)
      .min(1, 'Minimal harus ada 1 produk!')
      .required('Produk wajib diisi!'),
    deliveries: Yup.array()
      .of(DeliveryObjectSchema)
      .min(1, 'Minimal harus ada 1 pengiriman!')
      .required('Pengiriman wajib diisi!'),
  });

export type MovementFormValues = Yup.InferType<typeof MovementFormSchema>;

export const getMovementFormInitialValues = (
  initialValues?: Movement
): MovementFormValues => {
  const detailIdToProductId = new Map<number, { id: number; name: string }>();
  initialValues?.details?.forEach((detail) => {
    detailIdToProductId.set(detail.id, {
      id: detail.product.id,
      name: detail.product.name,
    });
  });

  return {
    transfer_reason: initialValues?.transfer_reason ?? '',
    transfer_date: initialValues?.transfer_date ?? '',
    source_warehouse: initialValues?.source_warehouse
      ? {
          value: initialValues.source_warehouse.id,
          label: initialValues.source_warehouse.name,
          area: initialValues.source_warehouse.area?.name ?? undefined,
          location: initialValues.source_warehouse.location?.name ?? undefined,
        }
      : null,
    source_warehouse_id: initialValues?.source_warehouse?.id ?? 0,
    destination_warehouse: initialValues?.destination_warehouse
      ? {
          value: initialValues.destination_warehouse.id,
          label: initialValues.destination_warehouse.name,
          area: initialValues.destination_warehouse.area?.name ?? undefined,
          location:
            initialValues.destination_warehouse.location?.name ?? undefined,
        }
      : null,
    destination_warehouse_id: initialValues?.destination_warehouse?.id ?? 0,
    products: initialValues?.details?.map((detail) => ({
      product: {
        value: detail.product.id,
        label: detail.product.name,
      },
      product_id: detail.product.id,
      product_qty: detail.quantity,
    })) ?? [
      {
        product: null,
        product_id: 0,
        product_qty: '',
      },
    ],
    deliveries: initialValues?.deliveries?.map((d) => ({
      delivery_cost: d.shipping_cost_total ?? undefined,
      delivery_cost_per_item: d.shipping_cost_item ?? undefined,
      document: d.document ?? null,
      document_path: d.document_path ?? null,
      driver_name: d.driver_name ?? '',
      vehicle_plate: d.vehicle_plate ?? '',
      supplier: d.supplier
        ? { value: d.supplier.id, label: d.supplier.name }
        : null,
      supplier_id: d.supplier?.id ?? 0,
      products:
        d.items?.map((item) => {
          const productData = detailIdToProductId.get(
            item.stock_transfer_detail_id
          );
          return {
            product: productData
              ? { value: productData.id, label: productData.name }
              : null,
            product_id: productData?.id ?? 0,
            product_qty: item.quantity,
          };
        }) ?? [],
    })) ?? [
      {
        delivery_cost: null,
        delivery_cost_per_item: null,
        document: null,
        document_path: null,
        driver_name: null,
        vehicle_plate: null,
        supplier: null,
        supplier_id: 0,
        products: [
          {
            product: null,
            product_id: 0,
            product_qty: '',
          },
        ],
      },
    ],
  };
};
