import * as Yup from 'yup';
import { Expense } from '@/types/api/expense';
import { formatDate } from '@/lib/helper';
import { S3_PUBLIC_BASE_URL } from '@/config/constant';

type ExpenseFormSchemaType = {
  category?: {
    value: 'BOP' | 'NON-BOP';
    label: 'BOP' | 'NON-BOP';
  } | null;
  location?: {
    value: number;
    label: string;
  } | null;
  location_id: number;
  transaction_date?: string;
  kandangs?: { id?: number; name?: string }[];
  supplier?: {
    value: number;
    label: string;
  } | null;
  supplier_id: number;
  existing_documents?: { id: number; name: string; url: string }[];
  deleted_documents?: number[];
  documents?: File[];
  expense_nonstocks: {
    kandang_id?: number;
    cost_items: {
      nonstock?: {
        value: number;
        label: string;
      } | null;
      nonstock_id?: number;
      quantity?: number;
      price?: number;
      notes?: string;
    }[];
  }[];
};

export const ExpenseRequestFormSchema: Yup.ObjectSchema<ExpenseFormSchemaType> =
  Yup.object({
    category: Yup.object({
      value: Yup.string()
        .oneOf(['BOP', 'NON-BOP'])
        .required('Kategori wajib diisi!'),
      label: Yup.string()
        .oneOf(['BOP', 'NON-BOP'])
        .required('Kategori wajib diisi!'),
    })
      .nullable()
      .required('Kategori wajib diisi!')
      .typeError('Kategori 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!'),

    transaction_date: Yup.string().required('Tanggal transaksi wajib diisi!'),

    kandangs: Yup.array()
      .of(
        Yup.object({
          id: Yup.number().optional(),
          name: Yup.string().optional(),
        })
      )
      .optional(),

    supplier: Yup.object({
      value: Yup.number().min(1).required(),
      label: Yup.string().required(),
    }).nullable(),

    supplier_id: Yup.number()
      .required('Vendor wajib diisi!')
      .min(1, 'Vendor wajib diisi!')
      .typeError('Vendor wajib diisi!'),

    existing_documents: Yup.array()
      .of(
        Yup.object({
          id: Yup.number().required(),
          name: Yup.string().required(),
          url: Yup.string().required(),
        })
      )
      .optional(),

    deleted_documents: Yup.array().of(Yup.number().required()).optional(),

    documents: Yup.array().of(Yup.mixed<File>().required()).optional(),

    expense_nonstocks: Yup.array()
      .of(
        Yup.object({
          kandang_id: Yup.number().min(1, 'Wajib memilih kandang!').optional(),
          cost_items: Yup.array()
            .of(
              Yup.object({
                nonstock: Yup.object({
                  value: Yup.number().min(1).required('Nonstock wajib diisi!'),
                  label: Yup.string().required('Nonstock wajib diisi!'),
                })
                  .nullable()
                  .required('Nonstock wajib diisi!')
                  .typeError('Nonstock wajib diisi!'),
                nonstock_id: Yup.number()
                  .required('Nonstock wajib diisi!')
                  .min(1, 'Nonstock wajib diisi!')
                  .typeError('Nonstock wajib diisi!'),
                quantity: Yup.number()
                  .required('Total kuantitas wajib diisi!')
                  .typeError('Total kuantitas wajib diisi!'),
                price: Yup.number()
                  .required('Harga satuan wajib diisi!')
                  .typeError('Harga satuan wajib diisi!'),
                notes: Yup.string(),
              })
            )
            .min(1, 'Kandang harus memiliki setidaknya 1 biaya!')
            .required('Biaya kandang wajib diisi!'),
        })
      )
      .min(1, 'Biaya kandang wajib diisi!')
      .required('Biaya kandang wajib diisi!'),
  });

export const UpdateExpenseRequestFormSchema = ExpenseRequestFormSchema;

export const UploadRequestDocumentsFormSchema = Yup.object({
  documents: Yup.array()
    .of(
      Yup.mixed<File>()
        .required()
        .test('fileSize', 'Ukuran dokumen maksimal 5 MB', (value) => {
          if (!value || !(value instanceof File)) return true;
          return value.size <= 5 * 1024 * 1024;
        })
    )
    .required(),
});

export type ExpenseRequestFormValues = Yup.InferType<
  typeof ExpenseRequestFormSchema
>;

export type UploadRequestDocumentsFormValues = Yup.InferType<
  typeof UploadRequestDocumentsFormSchema
>;

export const getExpenseFormInitialValues = (
  initialValues?: Expense
): ExpenseRequestFormValues => {
  return {
    category: initialValues?.category
      ? {
          value: initialValues.category,
          label: initialValues.category,
        }
      : null,
    location: initialValues?.location
      ? {
          value: initialValues.location.id,
          label: initialValues.location.name,
        }
      : null,
    location_id: Number(initialValues?.location.id || 0),
    transaction_date: initialValues?.transaction_date
      ? formatDate(initialValues.transaction_date, 'YYYY-MM-DD')
      : undefined,
    kandangs: initialValues?.kandangs.map((kandang) => ({
      id: kandang.kandang_id,
      name: kandang.name,
    })),
    supplier: initialValues?.supplier
      ? {
          value: initialValues.supplier.id,
          label: initialValues.supplier.name,
        }
      : null,
    supplier_id: initialValues?.supplier?.id ?? 0,
    existing_documents: initialValues?.documents?.map((doc) => {
      const path = doc.path.startsWith('/') ? doc.path.slice(1) : doc.path;
      return {
        id: doc.id,
        name: doc.path,
        url: `${S3_PUBLIC_BASE_URL}/${path}`,
      };
    }),
    deleted_documents: [],
    documents: [],
    expense_nonstocks: initialValues?.kandangs
      ? initialValues.kandangs.map((kandangExpense) => ({
          kandang_id: kandangExpense.kandang_id,
          cost_items: kandangExpense.pengajuans
            ? kandangExpense.pengajuans.map((expenseItem) => ({
                nonstock: {
                  value: expenseItem.nonstock.id,
                  label: expenseItem.nonstock.name,
                },
                nonstock_id: expenseItem.nonstock.id,
                quantity: expenseItem.qty,
                price: expenseItem.price,
                notes: expenseItem.notes,
              }))
            : [],
        }))
      : [
          {
            cost_items: [
              {
                nonstock: null,
                nonstock_id: 0,
                quantity: undefined,
                price: undefined,
                notes: '',
              },
            ],
          },
        ],
  };
};
