import { STATUS } from 'src/core/strings/constants/base.constants';
import {
  TransactionPaymentType,
  TransactionType,
} from 'src/modules/transaction/transaction/constants';
import { v4 as uuidv4 } from 'uuid';

export function mappingTransaction(data, refundId?: string) {
  try {
    let payment_type_bank: any = null;
    const season_period = {
      id: data.season_period_id,
      holiday_name: data.season_period_name,
      season_type: {
        id: data.season_period_type_id,
        name: data.season_period_type_name,
      },
    };

    if (data.payment_type_method_id || data.payment_type_method_name) {
      payment_type_bank = {
        id: data.payment_type_method_id,
        issuer_name: data.payment_type_method_name,
        account_number: data.payment_type_method_number,
        qr_image: data.payment_type_method_qr,
      };
    }

    const items = data?.['items']?.map((itemData) => {
      let tenant;
      let refund = itemData.refunds?.find(
        (item) => ![STATUS.CANCEL].includes(item.refund.status),
      );

      if (itemData.item_tenant_id) {
        tenant = {
          id: itemData.item_tenant_id,
          name: itemData.item_tenant_name,
          share_margin: itemData.item_tenant_share_margin,
        };
      }

      if (refundId)
        refund = itemData.refunds?.find((item) => item.refund.id == refundId);

      const timeGroup = itemData?.item?.time_group;

      return {
        item: {
          id: itemData.item_id,
          name: itemData.item_name,
          item_type: itemData.item_type,
          base_price: itemData.item_price,
          hpp: itemData.item_hpp,
          tenant: tenant,
          item_category: {
            id: itemData.item_category_id,
            name: itemData.item_category_name,
          },
          breakdown_bundling: itemData.breakdown_bundling,
          bundling_items: itemData.bundling_items,
          time_group: timeGroup,
        },
        id: itemData.id,
        refund: refund,
        qty: itemData.qty,
        qty_remaining: itemData.qty_remaining,
        total_price_refund: refund?.refund_total ?? 0,
        total_price: itemData.total_price,
      };
    });

    const refund = data.refunds?.find(
      (refund) => ![STATUS.CANCEL].includes(refund.status),
    );

    Object.assign(data, {
      season_period: season_period,
      items: items,
      payment_type_bank: payment_type_bank,
      refund: refund,
    });

    delete data.refunds;

    delete data.season_period_id;
    delete data.season_period_name;
    delete data.season_period_type_id;
    delete data.season_period_type_name;

    delete data.payment_type_method_id;
    delete data.payment_type_method_name;
    delete data.payment_type_method_number;
    delete data.payment_type_method_qr;
  } catch (error) {
    console.log('error mapping transactin', error);
  }
}

export function mappingRevertTransaction(data, type) {
  const { status } = data;
  const isCancel = status == STATUS.CANCEL;
  if (type == TransactionType.COUNTER) {
    if (data.booking_id) {
      Object.assign(data, {
        editor_id: data.pos_admin?.id,
        editor_name: data.pos_admin?.name,
        edited_at: new Date(data.created_at),
        payment_code: isCancel ? null : data.code,
        status: isCancel ? STATUS.PENDING : data.status,
      });
    } else {
      Object.assign(data, {
        type: type,
        creator_id: data.pos_admin?.id,
        creator_name: data.pos_admin?.name,
        invoice_code: data.code,
      });
    }

    Object.assign(data, {
      id: data.booking_id ?? data._id ?? data.id,
      creator_counter_no: Number(data.pos_number),
      creator_counter_name: data.pos_name,
      settlement_date: new Date(data.created_at),
      payment_date: isCancel ? null : new Date(data.created_at),
      invoice_date: new Date(data.created_at),
      payment_type: TransactionPaymentType.COUNTER,
      payment_type_counter:
        data.payment_type == 'cc'
          ? TransactionPaymentType.CC
          : data.payment_type,
      payment_card_information: data.card_information,
      payment_code_reference: isCancel ? null : data.payment_code,
      discount_code_id: data.discount_code?.id,
      discount_code: data.discount_code?.code,
      discount_percentage: data.discount_code?.discount,
    });
  } else {
    Object.assign(data, {
      type: type,
    });
  }

  if (isCancel) {
    Object.assign(data, {
      payment_type_method_id: null,
      payment_type_method_number: null,
      payment_type_method_name: null,
      payment_type_method_qr: null,
    });
  } else {
    Object.assign(data, {
      payment_type_method_id:
        data.payment_type_method?.id ?? data.payment_type_bank?.id,
      payment_type_method_number:
        data.payment_type_method?.account_number ??
        data.payment_type_bank?.account_number,
      payment_type_method_name:
        data.payment_type_method?.issuer_name ??
        data.payment_type_bank?.issuer_name,
      payment_type_method_qr:
        data.payment_type_method?.qr_image ?? data.payment_type_bank?.qr_image,
    });
  }

  const { payment_sub_total, discount_value, discount_percentage } = data;
  const discountPercent =
    discount_value && +discount_value > 0
      ? +discount_value / +payment_sub_total
      : (discount_percentage ?? 0) / 100;
  const discountValue = payment_sub_total * discountPercent;

  Object.assign(data, {
    payment_total_net_profit: data.payment_total,
    discount_value: discountValue,
    discount_percentage: discountPercent * 100,
    customer_category_id: data.customer_category?.id ?? null,
    customer_category_name: data.customer_category?.name ?? null,
    season_period_id: data.season_period?.id ?? null,
    season_period_name: data.season_period?.holiday_name ?? null,
    season_period_type_id: data.season_period?.season_type?.id ?? null,
    season_period_type_name: data.season_period?.season_type?.name ?? null,
  });

  data.items?.map((item) => {
    const total_price =
      Number(item.item.price ?? item.item.base_price) * Number(item.qty);
    const discount = discountPercent * total_price;
    const net_price = total_price - discount;
    const share_margin = item.item.tenant?.share_margin ?? 0;
    const total_share_tenant =
      share_margin > 0 ? (Number(share_margin) / 100) * total_price : 0;

    const bundlingTotalPrice =
      (item.item?.bundling_items?.reduce(
        (a, b) => a + Number(b.item_rates || b.base_price),
        0,
      ) ?? 0) * +item.qty;
    const totalAndBundlingRatio = total_price / bundlingTotalPrice;
    item.bundling_items = item.item.bundling_items?.map((bundling) => {
      if (bundling.total_net_price) return bundling;

      const basePrice =
        (bundling.item_rates || bundling.base_price) *
        +item.qty *
        totalAndBundlingRatio;
      const discount = discountPercent * basePrice;
      const total = basePrice - discount;

      return {
        ...bundling,
        item_id: bundling.id,
        item_name: bundling.name,
        total_net_price: basePrice,
        discount_value: discount,
        total_price: total,
        id: uuidv4(),
      };
    });

    Object.assign(item, {
      item_id: item.item.id,
      item_name: item.item.name,
      item_type: item.item.item_type,
      item_price: item.item.base_price,
      item_hpp: item.item.hpp,
      qty_remaining: item.qty,

      item_category_id: item.item.item_category?.id,
      item_category_name: item.item.item_category?.name,
      item_bundlings: item.item.bundling_items?.map(
        (bundling) => bundling.name,
      ),
      breakdown_bundling: item.item.breakdown_bundling,

      item_tenant_id: item.item.tenant?.id ?? null,
      item_tenant_name: item.item.tenant?.id ?? null,
      item_tenant_share_margin: item.item.tenant?.share_margin ?? null,

      total_net_price: net_price,
      discount_value: discount,
      total_price: total_price,
      total_hpp: Number(item.item.hpp) * Number(item.qty),
      total_share_tenant: total_share_tenant,
      total_profit: total_price - Number(total_share_tenant),
    });
  });
}
