import * as Yup from 'yup';
import { Purchase } from '@/types/api/purchase/purchase';

type PurchaseRequestStaffApprovalFormSchemaType = {
  action: 'APPROVED' | 'REJECTED';
  notes: string | null;
  items: {
    purchase_item_id?: number;
    product_id?: number | null;
    warehouse_id?: number | null;
    product?: {
      value?: number;
      label?: string;
    } | null;
    warehouse?: {
      value?: number;
      label?: string;
    } | null;
    qty: number;
    price: number | string;
    total_price: number | string;
  }[];
};

type PurchaseRequestManagerApprovalFormSchemaType = {
  action: 'APPROVED' | 'REJECTED';
  notes: string | null;
};

type PurchaseRequestAcceptApprovalFormSchemaType = {
  action: 'APPROVED' | 'REJECTED';
  notes: string | null;
  items: {
    purchase_item_id: number;
    received_date: string;
    travel_number: string;
    vehicle_number?: string | null;
    expedition_vendor?: {
      value: number;
      label: string;
    } | null;
    expedition_vendor_id?: number | null;
    received_qty: number | string;
    transport_per_item?: number | string | null;
  }[];
  travel_documents?: (File | null | undefined)[] | null;
};

export type PurchaseStaffApprovalItemSchema = {
  purchase_item_id?: number;
  product_id?: number | null;
  warehouse_id?: number | null;
  product?: {
    value?: number;
    label?: string;
  } | null;
  warehouse?: {
    value?: number;
    label?: string;
  } | null;
  qty: number;
  price: number | string;
  total_price: number | string;
};

export type PurchaseAcceptApprovalItemSchema = {
  purchase_item_id: number;
  received_date: string;
  travel_number: string;
  vehicle_number?: string | null;
  expedition_vendor?: {
    value: number;
    label: string;
  } | null;
  expedition_vendor_id?: number | null;
  received_qty: number | string;
  transport_per_item?: number | string | null;
};

export type PurchaseDeleteItemsSchema = {
  item_ids: number[];
};

const PurchaseStaffApprovalItemObjectSchema: Yup.ObjectSchema<PurchaseStaffApprovalItemSchema> =
  Yup.object({
    purchase_item_id: Yup.number()
      .optional()
      .min(0, 'Purchase item ID tidak valid!')
      .typeError('Purchase item ID harus berupa angka!'),
    product: Yup.object({
      value: Yup.number(),
      label: Yup.string(),
    })
      .nullable()
      .optional(),
    product_id: Yup.number()
      .optional()
      .nullable()
      .typeError('Product ID harus berupa angka!'),
    warehouse: Yup.object({
      value: Yup.number(),
      label: Yup.string(),
    })
      .nullable()
      .optional(),
    warehouse_id: Yup.number()
      .optional()
      .nullable()
      .typeError('Warehouse ID harus berupa angka!'),
    qty: Yup.number()
      .required('Jumlah wajib diisi!')
      .min(1, 'Jumlah harus berupa angka lebih dari 0!')
      .typeError('Jumlah harus berupa angka lebih dari 0!'),
    price: Yup.mixed<number | string>()
      .required('Harga wajib diisi!')
      .test(
        'is-valid-price',
        'Harga harus berupa angka lebih dari atau sama dengan 0!',
        function (value) {
          if (value === '' || value === null || value === undefined)
            return false;
          const numValue =
            typeof value === 'string' ? parseFloat(value) : value;
          return !isNaN(numValue) && numValue >= 0;
        }
      )
      .typeError('Harga harus berupa angka!'),
    total_price: Yup.mixed<number | string>()
      .required('Total harga wajib diisi!')
      .test(
        'is-valid-total-price',
        'Total harga harus berupa angka lebih dari atau sama dengan 0!',
        function (value) {
          if (value === '' || value === null || value === undefined)
            return false;
          const numValue =
            typeof value === 'string' ? parseFloat(value) : value;
          return !isNaN(numValue) && numValue >= 0;
        }
      )
      .typeError('Total harga harus berupa angka!'),
  });

const PurchaseManagerApprovalObjectSchema: Yup.ObjectSchema<PurchaseRequestManagerApprovalFormSchemaType> =
  Yup.object({
    action: Yup.mixed<'APPROVED' | 'REJECTED'>()
      .oneOf(['APPROVED', 'REJECTED'], 'Action harus APPROVED atau REJECTED')
      .required('Action wajib diisi!')
      .default('APPROVED'),
    notes: Yup.string().nullable().default(null),
  });

const PurchaseAcceptApprovalItemObjectSchema: Yup.ObjectSchema<PurchaseAcceptApprovalItemSchema> =
  Yup.object({
    purchase_item_id: Yup.number()
      .min(1, 'Purchase item is required!')
      .required('Purchase item is required!')
      .typeError('Purchase item is required!')
      .test(
        'is-valid-purchase-item',
        'Purchase item must be selected!',
        function (value) {
          return Boolean(value && value > 0);
        }
      ),
    received_date: Yup.string()
      .required('Tanggal penerimaan wajib diisi!')
      .typeError('Tanggal penerimaan wajib diisi!'),
    travel_number: Yup.string()
      .required('No. Surat jalan wajib diisi!')
      .typeError('No. Surat jalan wajib diisi!'),
    vehicle_number: Yup.string()
      .nullable()
      .when('expedition_vendor_id', {
        is: (expeditionVendorId?: number | null) => Boolean(expeditionVendorId),
        then: (schema) => schema.required('Nomor kendaraan wajib diisi!'),
        otherwise: (schema) => schema.optional(),
      })
      .typeError('Nomor kendaraan harus berupa plat nomor!'),
    expedition_vendor: Yup.object({
      value: Yup.number().min(1).required(),
      label: Yup.string().required(),
    })
      .default(undefined)
      .nullable()
      .optional(),
    expedition_vendor_id: Yup.number()
      .nullable()
      .optional()
      .typeError('Vendor ekspedisi harus berupa angka!'),
    received_qty: Yup.mixed<string | number>()
      .required('Jumlah diterima wajib diisi!')
      .test(
        'is-valid-received-qty',
        'Harus berupa angka lebih dari 0!',
        function (value) {
          if (value === '' || value === null || value === undefined)
            return false;
          const numValue =
            typeof value === 'string' ? parseFloat(value) : value;
          return !isNaN(numValue) && numValue > 0;
        }
      )
      .typeError('Jumlah diterima harus berupa angka!'),
    transport_per_item: Yup.mixed<string | number>()
      .nullable()
      .when('expedition_vendor_id', {
        is: (expeditionVendorId?: number | null) => Boolean(expeditionVendorId),
        then: (schema) =>
          schema.required('Biaya transport per item wajib diisi!'),
        otherwise: (schema) => schema.optional(),
      })
      .test(
        'is-valid-transport-per-item',
        'Biaya transport per item harus berupa angka lebih dari atau sama dengan 0!',
        function (value) {
          if (value === '' || value === null || value === undefined)
            return true;
          const numValue =
            typeof value === 'string' ? parseFloat(value) : value;
          return !isNaN(numValue) && numValue >= 0;
        }
      )
      .typeError('Biaya transport per item harus berupa angka!'),
  });

export const PurchaseRequestStaffApprovalFormSchema: Yup.ObjectSchema<PurchaseRequestStaffApprovalFormSchemaType> =
  Yup.object({
    action: Yup.mixed<'APPROVED' | 'REJECTED'>()
      .oneOf(['APPROVED', 'REJECTED'], 'Action harus APPROVED atau REJECTED')
      .required('Action wajib diisi!')
      .default('APPROVED'),
    notes: Yup.string().nullable().default(null),
    items: Yup.array()
      .of(PurchaseStaffApprovalItemObjectSchema)
      .min(1, 'Minimal harus ada 1 item pembelian!')
      .required('Item pembelian wajib diisi!')
      .typeError('Item pembelian wajib diisi!')
      .test(
        'items-validation',
        'Setiap item harus valid: existing items hanya butuh purchase_item_id, new items butuh product_id & warehouse_id',
        function (items) {
          if (!items || items.length === 0) return false;

          return items.every((item) => {
            const isExisting =
              item.purchase_item_id && item.purchase_item_id > 0;

            const isNew = !item.purchase_item_id || item.purchase_item_id === 0;

            if (isExisting) {
              return true;
            }

            if (isNew) {
              return Boolean(
                item.product_id &&
                  item.product_id > 0 &&
                  item.warehouse_id &&
                  item.warehouse_id > 0
              );
            }

            return false;
          });
        }
      ),
  });

export const PurchaseDeleteItemsSchema: Yup.ObjectSchema<PurchaseDeleteItemsSchema> =
  Yup.object({
    item_ids: Yup.array()
      .of(
        Yup.number()
          .min(1, 'Item ID tidak valid!')
          .required('Item ID tidak valid!')
          .typeError('Item ID tidak valid!')
      )
      .min(1, 'Minimal harus ada 1 item yang dihapus!')
      .required('Item yang dihapus wajib diisi!')
      .typeError('Item yang dihapus wajib diisi!'),
  });

export const PurchaseRequestStaffApprovalFormInitialValues: PurchaseRequestStaffApprovalFormSchemaType =
  {
    action: 'APPROVED',
    notes: '',
    items: [
      {
        product_id: 0,
        warehouse_id: 0,
        product: null,
        warehouse: null,
        qty: 0,
        price: '',
        total_price: '',
      },
    ],
  };

export const PurchaseRequestStaffApprovalFormDefaultValues = (
  purchase?: Purchase,
  type?: 'add' | 'edit'
): PurchaseRequestStaffApprovalFormSchemaType => {
  return {
    action: 'APPROVED',
    notes: purchase?.notes ?? null,
    items: purchase?.items
      ? purchase.items.map((item) => ({
          purchase_item_id: item.id,
          product_id: item.product_id || 0,
          warehouse_id: item.warehouse?.id || 0,
          product: {
            value: item.product_id || 0,
            label: item.product?.name || '',
          },
          warehouse: {
            value: item.warehouse?.id || 0,
            label: item.warehouse?.name || '',
          },
          qty: item.sub_qty || item.qty || 0,
          price:
            type === 'add'
              ? 'ProductPrice' in item.product
                ? item.product.ProductPrice || item.price || ''
                : item.price
              : item.price,
          total_price:
            type === 'add'
              ? ('ProductPrice' in item.product
                  ? item.product.ProductPrice || item.price || 0
                  : item.price) * (item.sub_qty || item.qty || 0)
              : item.total_price,
        }))
      : [
          {
            product_id: 0,
            warehouse_id: 0,
            product: null,
            warehouse: null,
            qty: 0,
            price: '',
            total_price: '',
          },
        ],
  };
};

export type PurchaseRequestStaffApprovalFormValues = Yup.InferType<
  typeof PurchaseRequestStaffApprovalFormSchema
>;

export const PurchaseRequestManagerApprovalFormSchema: Yup.ObjectSchema<PurchaseRequestManagerApprovalFormSchemaType> =
  PurchaseManagerApprovalObjectSchema;

export const PurchaseRequestManagerApprovalFormDefaultValues = (
  purchase?: Purchase
): PurchaseRequestManagerApprovalFormSchemaType => {
  return {
    action: 'APPROVED',
    notes: purchase?.notes ?? null,
  };
};

export type PurchaseRequestManagerApprovalFormValues = Yup.InferType<
  typeof PurchaseRequestManagerApprovalFormSchema
>;

export const PurchaseRequestAcceptApprovalFormSchema: Yup.ObjectSchema<PurchaseRequestAcceptApprovalFormSchemaType> =
  Yup.object({
    action: Yup.mixed<'APPROVED' | 'REJECTED'>()
      .oneOf(['APPROVED', 'REJECTED'], 'Action harus APPROVED atau REJECTED')
      .required('Action wajib diisi!')
      .default('APPROVED'),
    notes: Yup.string().nullable().default(null),
    items: Yup.array()
      .of(PurchaseAcceptApprovalItemObjectSchema)
      .min(1, 'Minimal harus ada 1 item pembelian!')
      .required('Item pembelian wajib diisi!')
      .typeError('Item pembelian wajib diisi!'),
    travel_documents: Yup.array()
      .of(
        Yup.mixed<File>()
          .nullable()
          .optional()
          .test('fileSize', 'Ukuran dokumen maksimal 5 MB', (value) => {
            if (!value) return true;
            if (value instanceof File) return value.size <= 5 * 1024 * 1024;
            return true;
          })
      )
      .nullable()
      .optional()
      .typeError('Dokumen surat jalan harus berupa array!'),
  });

export const PurchaseRequestAcceptApprovalFormInitialValues: PurchaseRequestAcceptApprovalFormSchemaType =
  {
    action: 'APPROVED',
    notes: '',
    items: [
      {
        purchase_item_id: 0,
        received_date: '',
        travel_number: '',
        vehicle_number: '',
        expedition_vendor_id: 0,
        received_qty: '',
        transport_per_item: '',
      },
    ],
    travel_documents: [],
  };

export const PurchaseRequestAcceptApprovalFormDefaultValues = (
  purchase?: Purchase
): PurchaseRequestAcceptApprovalFormSchemaType => {
  return {
    action: 'APPROVED',
    notes: purchase?.notes ?? null,
    items: purchase?.items
      ? purchase.items.map((item) => ({
          purchase_item_id: item.id,
          received_date: '',
          travel_number: '',
          vehicle_number: '',
          expedition_vendor_id: 0,
          received_qty: '',
          transport_per_item: '',
        }))
      : [
          {
            purchase_item_id: 0,
            received_date: '',
            travel_number: '',
            vehicle_number: '',
            expedition_vendor_id: 0,
            received_qty: '',
            transport_per_item: '',
          },
        ],
    travel_documents: [],
  };
};

export type PurchaseRequestAcceptApprovalFormValues = Yup.InferType<
  typeof PurchaseRequestAcceptApprovalFormSchema
>;

export const PurchaseDeleteItemsInitialValues: PurchaseDeleteItemsSchema = {
  item_ids: [],
};

export type PurchaseDeleteItemsFormValues = Yup.InferType<
  typeof PurchaseDeleteItemsSchema
>;
