import * as Yup from 'yup';
import {
  Recording,
  CreateGrowingRecordingPayload,
  CreateLayingRecordingPayload,
  CreateEggPayload,
  RecordingStock,
} from '@/types/api/production/recording';
import { getProductWarehouseOptionLabel } from '@/lib/product-warehouse';

type RecordingGrowingFormSchemaType = {
  record_date: string;
  location?: {
    value: number;
    label: string;
  } | null;
  location_id: number;
  project_flock?: {
    value: number;
    label: string;
  } | null;
  project_flock_id: number;
  kandang?: {
    value: number;
    label: string;
  } | null;
  kandang_id: number;
  project_flock_kandang: {
    value: number;
    label: string;
  } | null;
  project_flock_kandang_id: number;
  stocks: {
    product_warehouse_id:
      | {
          value: number;
          label: string;
        }
      | undefined;
    qty: number | string;
  }[];
  depletions: {
    product_warehouse_id?: {
      value: number;
      label: string;
    } | null;
    source_product_warehouse_id?: number;
    qty?: number | string;
  }[];
};

type RecordingLayingFormSchemaType = RecordingGrowingFormSchemaType & {
  eggs: {
    product_warehouse_id?: {
      value: number;
      label: string;
    } | null;
    qty?: number | string;
    weight?: number | string;
  }[];
};

export type StockSchema = {
  product_warehouse_id: {
    value: number;
    label: string;
  };
  qty: number | string;
};

export type DepletionSchema = {
  product_warehouse_id?: {
    value: number;
    label: string;
  } | null;
  source_product_warehouse_id?: number;
  qty?: number | string;
};

export type EggSchema = {
  product_warehouse_id?: {
    value: number;
    label: string;
  } | null;
  qty?: number | string;
  weight?: number | string;
};

const StockObjectSchema: Yup.ObjectSchema<StockSchema> = Yup.object({
  product_warehouse_id: Yup.object({
    value: Yup.number().min(1).required(),
    label: Yup.string().required(),
  })
    .required('Produk wajib diisi!')
    .typeError('Produk wajib diisi!'),
  qty: Yup.number()
    .required('Jumlah penggunaan wajib diisi!')
    .moreThan(0, 'Jumlah penggunaan harus lebih dari 0!')
    .typeError('Jumlah penggunaan harus berupa angka!'),
});

const DepletionObjectSchema: Yup.ObjectSchema<DepletionSchema> = Yup.object({
  product_warehouse_id: Yup.object({
    value: Yup.number().min(1).required(),
    label: Yup.string().required(),
  })
    .optional()
    .nullable(),
  source_product_warehouse_id: Yup.number()
    .optional()
    .typeError('Gudang sumber harus berupa angka!'),
  qty: Yup.number()
    .optional()
    .typeError('Jumlah depletions harus berupa angka!'),
});

const EggObjectSchema: Yup.ObjectSchema<EggSchema> = Yup.object({
  product_warehouse_id: Yup.object({
    value: Yup.number().min(1).required(),
    label: Yup.string().required(),
  })
    .optional()
    .nullable(),
  qty: Yup.number().optional().typeError('Jumlah telur harus berupa angka!'),
  weight: Yup.number().optional().typeError('Berat telur harus berupa angka!'),
});

export const RecordingGrowingFormSchema: Yup.ObjectSchema<RecordingGrowingFormSchemaType> =
  Yup.object({
    record_date: Yup.string()
      .required('Tanggal recording wajib diisi!')
      .min(1, 'Tanggal recording wajib diisi!')
      .typeError('Tanggal recording wajib diisi!'),
    location: Yup.object({
      value: Yup.number().min(1).required(),
      label: Yup.string().required(),
    }).nullable(),
    location_id: Yup.number()
      .min(1, 'Lokasi wajib diisi!')
      .required('Lokasi wajib diisi!')
      .typeError('Lokasi wajib diisi!'),
    project_flock: Yup.object({
      value: Yup.number().min(1).required(),
      label: Yup.string().required(),
    }).nullable(),
    project_flock_id: Yup.number()
      .min(1, 'Project flock wajib diisi!')
      .required('Project flock wajib diisi!')
      .typeError('Project flock wajib diisi!'),
    kandang: Yup.object({
      value: Yup.number().min(1).required(),
      label: Yup.string().required(),
    }).nullable(),
    kandang_id: Yup.number()
      .min(1, 'Kandang wajib diisi!')
      .required('Kandang wajib diisi!')
      .typeError('Kandang wajib diisi!'),
    project_flock_kandang: Yup.object({
      value: Yup.number().min(1).required(),
      label: Yup.string().required(),
    }).nullable(),
    project_flock_kandang_id: Yup.number()
      .default(0)
      .typeError('Project Flock Kandang wajib diisi!')
      .test(
        'is-valid-project-flock-kandang',
        'Project Flock Kandang wajib diisi!',
        (value) => value !== undefined && value !== null && value > 0
      )
      .required('Project Flock Kandang wajib diisi!')
      .test(
        'not-already-recorded',
        'Project Flock ini sudah direcord pada tanggal tersebut!',
        function (value) {
          const recordedProjectFlockIds = this.options.context
            ?.recordedProjectFlockIds as Set<number>;
          const formType = this.options.context?.type as
            | 'add'
            | 'edit'
            | 'detail';
          if (formType !== 'add') return true;
          if (value && recordedProjectFlockIds?.has(value)) {
            return false;
          }
          return true;
        }
      ),
    stocks: Yup.array()
      .of(StockObjectSchema)
      .min(1, 'Minimal harus ada 1 data stok!')
      .required('Data stok wajib diisi!'),
    depletions: Yup.array().of(DepletionObjectSchema).default([]),
  });

export const RecordingLayingFormSchema: Yup.ObjectSchema<RecordingLayingFormSchemaType> =
  RecordingGrowingFormSchema.shape({
    eggs: Yup.array().of(EggObjectSchema).default([]),
  });

export const UpdateRecordingGrowingFormSchema =
  RecordingGrowingFormSchema.shape({
    location_id: Yup.number().nullable().optional(),
    project_flock_id: Yup.number().nullable().optional(),
    kandang_id: Yup.number().nullable().optional(),
    project_flock_kandang_id: Yup.number()
      .default(0)
      .typeError('Project Flock Kandang wajib diisi!')
      .test(
        'is-valid-project-flock-kandang',
        'Project Flock Kandang wajib diisi!',
        (value) => value !== undefined && value !== null && value > 0
      )
      .required('Project Flock Kandang wajib diisi!'),
  });

export const UpdateRecordingLayingFormSchema = RecordingLayingFormSchema.shape({
  location_id: Yup.number().nullable().optional(),
  project_flock_id: Yup.number().nullable().optional(),
  kandang_id: Yup.number().nullable().optional(),
  project_flock_kandang_id: Yup.number()
    .default(0)
    .typeError('Project Flock Kandang wajib diisi!')
    .test(
      'is-valid-project-flock-kandang',
      'Project Flock Kandang wajib diisi!',
      (value) => value !== undefined && value !== null && value > 0
    )
    .required('Project Flock Kandang wajib diisi!'),
});

export type RecordingGrowingFormValues = Yup.InferType<
  typeof RecordingGrowingFormSchema
>;

export type RecordingLayingFormValues = Yup.InferType<
  typeof RecordingLayingFormSchema
>;

type RecordingFormData = Partial<Recording> & {
  stocks?: CreateGrowingRecordingPayload['stocks'] | Recording['stocks'];
  depletions?:
    | CreateGrowingRecordingPayload['depletions']
    | Recording['depletions'];
  eggs?: CreateLayingRecordingPayload['eggs'] | Recording['eggs'];
  project_flock_kandang_id?: number;
  project_flock_category?: string;
};

export const getRecordingGrowingFormInitialValues = (
  initialValues?: RecordingFormData
): RecordingGrowingFormValues => ({
  record_date: initialValues?.record_datetime
    ? new Date(initialValues.record_datetime).toISOString().split('T')[0]
    : new Date().toISOString().split('T')[0],
  location: null,
  location_id: 0,
  project_flock: null,
  project_flock_id: 0,
  kandang: null,
  kandang_id: 0,
  project_flock_kandang:
    (initialValues?.project_flock_kandang_id ??
    initialValues?.project_flock?.project_flock_kandang_id)
      ? {
          value:
            initialValues?.project_flock_kandang_id ??
            initialValues?.project_flock?.project_flock_kandang_id ??
            0,
          label: `Project Flock #${
            initialValues?.project_flock_kandang_id ??
            initialValues?.project_flock?.project_flock_kandang_id ??
            0
          }`,
        }
      : null,
  project_flock_kandang_id:
    initialValues?.project_flock_kandang_id ??
    initialValues?.project_flock?.project_flock_kandang_id ??
    0,
  stocks: initialValues?.stocks?.map((stock) => ({
    product_warehouse_id: {
      value: stock.product_warehouse_id,
      label: getProductWarehouseOptionLabel(stock.product_warehouse),
    },
    qty:
      (stock as RecordingStock).qty ||
      ((stock as RecordingStock).usage_amount || 0) +
        ((stock as RecordingStock).pending_qty || 0) ||
      '',
  })) ?? [
    {
      product_warehouse_id: undefined,
      qty: '',
    },
  ],
  depletions: initialValues?.depletions?.map(
    (
      depletion: NonNullable<CreateGrowingRecordingPayload['depletions']>[0]
    ) => ({
      product_warehouse_id: {
        value: Number(depletion.product_warehouse_id ?? 0),
        label: getProductWarehouseOptionLabel(depletion.product_warehouse),
      },
      source_product_warehouse_id: depletion.source_product_warehouse_id,
      qty: depletion.qty,
    })
  ) ?? [
    {
      product_warehouse_id: undefined,
      qty: '',
    },
  ],
});

export const getRecordingLayingFormInitialValues = (
  initialValues?: RecordingFormData
): RecordingLayingFormValues => ({
  ...getRecordingGrowingFormInitialValues(initialValues),

  eggs: initialValues?.eggs?.map((egg: CreateEggPayload) => ({
    product_warehouse_id: {
      value: Number(egg.product_warehouse_id ?? 0),
      label: getProductWarehouseOptionLabel(egg.product_warehouse),
    },
    qty: egg.qty,
    weight: egg.weight,
  })) ?? [
    {
      product_warehouse_id: null,
      qty: '',
      weight: '',
    },
  ],
});
