<script>
import {ref, watch} from 'vue';
import axios from 'axios';
import {API_URL} from "@/main.js";
import { getScansDepartmentPagination } from "@/components/numberplatescanners/Scans.vue";
import {useRouter} from "vue-router";
import { parseError, clearErrors } from "@/components/request/HandleGlobalError.vue";
import { getNotes, createNote, deleteNote } from "@/components/shop/CustomerNotes.vue";
import { getOrderItems } from "@/components/shop/OrdersItems.vue";
import { getAttributes } from "@/components/shop/CustomerAttributes.vue";
import { SessionUser } from "@/components/session/token/SessionUser.vue";
import { authenticatedRequest } from "@/components/session/authenticatedRequest.vue";
import Swal from "sweetalert2";

/**
 * Display toggleable items
 */
export const hidePricesCatalog = ref(null);
export const hideDiscountsCatalog = ref(null);

// Setters for the hide prices and discounts
export const setHidePricesCatalog = (value) => {
  hidePricesCatalog.value = value;
  localStorage.setItem('hidePricesCatalog', '' + value);
};

export const setHideDiscountsCatalog = (value) => {
  hideDiscountsCatalog.value = value;
  localStorage.setItem('hideDiscountsCatalog', '' + value);
};

// Getters
export const getHidePricesCatalog = () => {
  // If the value is not set, get it from the local storage
  if (hidePricesCatalog.value === null) {
    hidePricesCatalog.value = localStorage.getItem('hidePricesCatalog') === 'true';
  }
  return hidePricesCatalog.value;
};

export const getHideDiscountsCatalog = () => {
  // If the value is not set, get it from the local storage
  if (hideDiscountsCatalog.value === null) {
    hideDiscountsCatalog.value = localStorage.getItem('hideDiscountsCatalog') === 'true';
  }
  return hideDiscountsCatalog.value;
};

/** Define steps for the POS Department Process */
export const step = ref(1);
export const nextStepDelay = ref(0); // 2 seconds delay

/** Define the next step delay function */
export const setNextStepDelay = (delay) => {
  nextStepDelay.value = delay;
  setTimeout(() => {
    nextStepDelay.value = 0;
  }, delay * 1000);
};

/** Define the step functions */
export const nextStep = async () => {
  // Check if the delay has passed since the last step (To prevent double clicks)
  if (nextStepDelay.value > 0) {
    return;
  }
  // Set the delay to 2 seconds
  setNextStepDelay(2);
  // Clear the errors
  clearErrors();
  // If the current step is 1, create the order
  if (step.value === 1) {
    if (await createOrder()) {
      step.value++;
    }
    return;
  }
  if (step.value === 2) {
    // If the current step is 2, set the product category to addons
    setProductsCategory(4);
    // Set the step to 3 in the query parameters
    window.history.pushState({}, '', `?id=${order_id.value}&customer_id=${customer_id.value}&step=3`);
  }
  if (step.value === 3) {
    // Mark the order as completed
    await SessionUser.objects.orders.functions.mark_as_completed(order_id.value).then((response) => {
      // Check if the order contains any material, if not, we can skip the next step
      if (!doesOrderContainMaterial()) {
        // Show a "Success" dialog, that closes after 2 seconds, then redirects to the next page
        Swal.fire({
          title: 'Fuldført',
          text: 'Transaktionen er fuldført, omdirigerer automatisk...',
          icon: 'success',
          showConfirmButton: false,
          timer: 2000
        }).then(() => {
          // Redirect to the next page
          window.location.href = '/admin/' + department_id.value + '/modules/pos';
        });
      }
      // Set the step to 4 in the query parameters
      window.history.pushState({}, '', `?id=${order_id.value}&customer_id=${customer_id.value}&step=4`);
    }).catch((error) => {
      parseError(error, 'stepError');
    })
    return;
  }
  step.value++;
};


export const previousStep = () => {
  step.value--;
};

export const getCurrentStep = () => {
  return step.value;
};

export const setStep = (newStep) => {
  step.value = newStep;
};

/** Define the current order dynamic variables */
export const customer_id = ref('');
export const customer_name = ref('');
export const customer_data = ref([]); // The full customer data object
export const department_id = ref('');
export const reference = ref('');
export const notes = ref([]); // The customer notes
export const order_notes = ref(''); // The order notes
export const reg_1 = ref(''); // Only uppercase letters and numbers without spaces
export const reg_2 = ref(''); // Only uppercase letters and numbers without spaces
export const reg_3 = ref(''); // Only uppercase letters and numbers without spaces
export const order_id = ref(null);
export const order_items = ref([]);
export const customer_attributes = ref([]);
export const user_discounts = ref([]);
const has_user_discounts_loaded = ref(false);
export const scan_data = ref([]);
export const invoiceCollectionId = ref(null);
export const completed_at = ref(null);

/** Whenever the reg_1, reg_2 or reg_3 changes, remove any spaces and make the string uppercase */
watch([reg_1, reg_2, reg_3], () => {
  reg_1.value = reg_1.value.replace(/\s/g, '').toUpperCase();
  reg_2.value = reg_2.value.replace(/\s/g, '').toUpperCase();
  reg_3.value = reg_3.value.replace(/\s/g, '').toUpperCase();
});

/** Get the order details by order id */
export const getOrderDetails = async () => {
  const token = localStorage.getItem('token');
  if (!token || !order_id.value) {
    return null;
  }
  return axios.get(API_URL + '/order?id=' + order_id.value, {
    headers: {
      Authorization: `Bearer ${token}`
    }
  }).then((response) => {
    const order_data = response.data.data;
    // Set the order details
    customer_id.value = order_data.customer_id;
    department_id.value = order_data.department_id;
    reference.value = order_data.reference || '';
    order_notes.value = order_data.notes || '';
    reg_1.value = order_data.reg_1 || '';
    reg_2.value = order_data.reg_2 || '';
    reg_3.value = order_data.reg_3 || '';
    invoiceCollectionId.value = order_data.invoice_collection_id || null;
    completed_at.value = order_data.completed_at || null;
    // Return the order data
    return order_data;
  }).catch((error) => {
    parseError(error, 'stepError');
    return null;
  });
};

export const getOrderReg1 = async (orderId) => {
  const order = await getOrderDetails(orderId);
  console.log(order);
  if (!order) {
    return '';
  }
  return order.reg_1;
};

/** Define the current order functions */
export const createOrder = () => {
  const token = localStorage.getItem('token');
  if (!token) {
    return null;
  }
  return axios.post(API_URL + '/orders', {
    customer_id: customer_id.value,
    department_id: getDepartment(),
    reference: reference.value,
    notes: order_notes.value,
    reg_1: reg_1.value,
    reg_2: reg_2.value,
    reg_3: reg_3.value
  }, {
    headers: {
      Authorization: `Bearer ${token}`
    }
  }).then((response) => {
    // Check if the response is successful
    if (!response.data.success) {
      parseError(response, 'stepError');
      return false;
    }
    order_id.value = parseInt(response.data.data.id);
    // Set the order id in the local storage (To be make F5 safe)
    localStorage.setItem('pos_order_id', order_id.value);
    // Set the query parameters
    window.history.pushState({}, '', `?id=${order_id.value}&customer_id=${customer_id.value}&step=2`);
    return true;
  }).catch((error) => {
    parseError(error, 'stepError');
    return false;
  });
};



export const deleteOrder = () => {
  const token = localStorage.getItem('token');
  if (!token) {
    return null;
  }
  return axios.delete(API_URL + '/orders', {
    params: {
      id: order_id.value
    },
    headers: {
      Authorization: `Bearer ${token}`
    }
  }).then((response) => {
    // Check if the response is successful
    if (!response.data.success) {
      parseError(response, 'stepError');
      return false;
    }
    order_id.value = null;
    return true;
  }).catch((error) => {
    parseError(error, 'stepError');
    return false;
  });
};

export const getOrderId = () => {
  return order_id.value;
};

/** Define the department license plate scans dynamic variables */
export const scans = ref([]);
export const scans_page = ref(1);
export const scans_limit = ref(10);

/** Define the department license plate scans functions */
export const getScans = (forceClearCache = false) => {
  if (forceClearCache) {
    scans.value = [];
  }
  // If the scans are already loaded, return them
  if (scans.value.length > 0) {
    return scans.value;
  }
  // Get the scans from the API
  getScansDepartmentPagination(department_id.value, scans_page.value, scans_limit.value).then((response) => {
    scans.value = response.data.data;
    console.log(scans.value);
  }).catch((error) => {
    console.error(error);
  });
  return scans.value;
};

/** Define the department setters */
export const setDepartment = (id = null) => {
  // Set the department id to the departmentId from the route, or the id passed in
  if (id) {
    department_id.value = id;
  } else {
    const router = useRouter();
    department_id.value = router.currentRoute.value.params.departmentId;
  }
};

/** Define the department getters */
export const getDepartment = () => {
  return department_id.value;
};

/** Define the product category dynamic variables */
export const products_category = ref(null);

/** Define the product category functions */
export const setProductsCategory = (category) => {
  products_category.value = category;
};

export const getProductsCategory = () => {
  return products_category.value;
};


export const getUserGlobalDiscount = () => {
  // Check if the user discounts are loaded
  if (user_discounts.value === undefined) {
    getUserDiscounts();
  }

  // Find the specific discount for the category
  let discount = 0;
  try {
    discount = parseInt(user_discounts.value.find(
        (discount) =>
            discount.id === '999999'
    ).percentage) || null;
  } catch (e) {
  }
  // If there is no discount, return 0
  if (!discount) {
    return 0;
  }
  // Return the discount
  return discount;
}

/** Check if the customer is barred */
export const isCustomerBarred = (customer) => {
  // Check if the customer.barred field exists, otherwise return false
  return customer.barred ? customer.barred : false;
};

/** Select a customer */
export const selectCustomer = (customer) => {
  function reset() {
    customer_id.value = '';
    customer_name.value = '';
    customer_data.value = [];
    customer_attributes.value = [];
    notes.value = [];
    user_discounts.value = [];
  }
  reset();
  // If the customer is null, clear the customer data
  if (!customer) {
    return;
  }
  // Check if the customer is barred
  if (isCustomerBarred(customer)) {
    /**
    Swal.fire({
      title: 'Kunden er spærret',
      text: 'Denne kunde er spærret og kan ikke bruges',
      icon: 'error',
      confirmButtonText: 'Ok'
    }); */
    // Select the 999 customer
    searchAndSelectCustomer(999);
    return;
  }
  customer_id.value = customer.customerNumber;
  customer_name.value = customer.name;
  customer_data.value = customer;
  console.log(customer);
  // Get the customer's notes
  fetchCustomerNotes();
  // Get the customer's attributes
  loadCustomerAttributes();
};

/** Is customer selected */
export const isCustomerSelected = () => {
  return customer_name.value !== '';
};

export const doesOrderContainMaterial = () => {
  let ids = [
      53,
      54
  ]
  let result = false;
  // Loop through the ids, and check if the order contains any of the ids
  ids.forEach((id) => {
    if (order_items.value.some((item) => item.product.id === id)) {
      result = true;
    }
  });
  return result;
};

/** Fetch the customer's notes */
export const fetchCustomerNotes = () => {
  getNotes(customer_id.value).then((response) => {
    notes.value = response.data.data;
  }).catch((error) => {
    console.error(error);
  });
};

/** Create a customer note */
export const addCustomerNote = (note) => {
  createNote(customer_id.value, note).then((response) => {
    fetchCustomerNotes();
  }).catch((error) => {
    console.error(error);
  });
};

/** Delete a customer note */
export const removeCustomerNote = (id) => {
  deleteNote(id).then((response) => {
    fetchCustomerNotes();
  }).catch((error) => {
    console.error(error);
  });
};

/** Show confirmation delete note dialog */
export const showDeleteNoteDialog = (noteId) => {
  Swal.fire({
    title: 'Are you sure?',
    text: `You are about to delete the note: ${noteId}`,
    icon: 'warning',
    showCancelButton: true,
    confirmButtonText: 'Yes, delete it!',
    cancelButtonText: 'No, keep it'
  }).then((result) => {
    if (result.isConfirmed) {
      removeCustomerNote(noteId);
    }
  });
};


/** Select a scan */
export const selectScan = (scan) => {
  showSelectedScanDialog(scan);
  console.log(scan);
  // Check which registration number is empty
  //if (!Object.keys(reg_1.value).length > 0 || !reg_1.value) {
    // Set the registration number 1
    //reg_1.value = scan.plate;
    //return;
  //}
  // Set the registration number 1
  reg_1.value = scan.plate;
};

const cached_customer_names = [];

/** Get the customer's name */
export const getCustomerName = async (customerNumber) => {
  if (!customerNumber) {
    return '';
  }
  // Check if the customer name is already cached
  if (cached_customer_names[customerNumber]) {
    return cached_customer_names[customerNumber];
  }
  // Get the customer data
  await authenticatedRequest(
      `/users/customer?customer_number=${customerNumber}`,
      'GET').then((response) => {
    console.log(response);
    // Cache the customer name
    cached_customer_names[customerNumber] = response.data.data.customer_name;
    return cached_customer_names[customerNumber];
  }).catch((error) => {
    // If the customer is not found, return an empty string
    cached_customer_names[customerNumber] = '';
    console.error(error);
  });
  return '';
};

/** Search, then select customer by customer number */
export const searchAndSelectCustomer = async (customerNumber) => {
  // Get the customer data
  await authenticatedRequest(
      `/users/customer?customer_number=${customerNumber}`,
      'GET').then((response) => {
    console.log(response);
    selectCustomer(response.data.data.economic_customer);
  }).catch((error) => {
    console.error(error);
  });
};

/** Show selected scan dialog */
export const showSelectedScanDialog = (scan) => {
  return;
  // Show a loading swal
  Swal.fire({
    title: 'Henter nummerplade',
    text: 'Vent venligst...',
    icon: 'info',
    showConfirmButton: false,
    allowOutsideClick: false,
    allowEscapeKey: false,
  })
  // Get the number plate data
  SessionUser.adminUser.plates.get_order_history(scan.plate).then((response) => {
    // noinspection JSValidateTypes - This is a Vue ref
    scan_data.value = response;
    // For each order, show the order data
    let html = '';
    let orderCount = 0;
    let customerOrders = [];
    response.forEach((order) => {
      orderCount++;
      // Check if the customer is already in the list
      let customerOrder = customerOrders.find((customerOrder) => customerOrder.customer_id === order.customer_id);
      if (customerOrder) {
        customerOrder.order_count++;
      } else {
        customerOrders.push({
          customer_id: order.customer_id,
          order_count: 1
        });
      }

    });
    console.log(customerOrders);
    html += '<div class="columns">';
    html += '<div class="column is-12">';
    html += `<p>Denne nummerplade er set ${orderCount} gang(e), faktureret til:</p>`;
    html += '</div>';
    html += '</div>';
    // List of customers this plate is registered to
    html += '<div class="buttons">';
    customerOrders.forEach((customerOrder) => {
      // Get the customer name
      html += `<button class="button is-fullwidth is-dark">${customerOrder.customer_id} - ${customerOrder.order_count} gang(e)</button>`;
    });
    html += '</div>';
    // Show the swal (IF there's any orders)
    if (orderCount !== 0) {
      Swal.fire({
        title: 'Genkendt nummerplade',
        html: html,
        icon: 'info',
        showConfirmButton: false,
        showCancelButton: true,
        allowOutsideClick: true,
        allowEscapeKey: true,
        cancelButtonText: 'Luk'
      });
    } else {
      Swal.close();
    }
  }).catch((error) => {
    console.error(error);
  });
};

/** Get order items */
export const loadOrderItems = async () => {
  const response = await getOrderItems(order_id.value);
  order_items.value = response.data.data;
};

/** Get customer attributes */
export const loadCustomerAttributes = async () => {
  const response = await getAttributes(customer_id.value);
  try {
    if (!response.data.success) {
      return;
    }
  } catch (e) {
    return;
  }
  customer_attributes.value = response.data.data;
};

/** Check if an attribute is set in the customer attributes */
const hasAttribute = (attrib) => {
  // Check if the customer has been loaded
  if (!customer_attributes.value) {
    return false;
  }
  return customer_attributes.value.some(attribute => attribute.attribute === attrib);
};

/** Check if the product category is allowed */
export const productCategoryAllowed = (category) => {
  // Check if the product category is the addons category
  if (category === 'addons') {
   // Check if the customer has the attribute restrictAdditionalServices
    return !hasAttribute('restrictAdditionalServices');
  }
  if (category === 'spot_free') {
    // Check if the customer has the attribute restrictSpotFree
    return !hasAttribute('restrictSpotFree');
  }
  if (category === 'interior_cleaning') {
    // Check if the customer has the attribute restrictInteriorCleaning
    return !hasAttribute('restrictInteriorCleaning');
  }
  if (category === 'tank_cleaning') {
    // Check if the customer has the attribute restrictTankCleaning
    return !hasAttribute('restrictTankCleaning');
  }
  return true;
};

/** Check if the customer should be billed per order, or per billing period */
export const invoiceAllOrdersIndividually = () => {
  // Check if the customer has the attribute invoiceAllOrdersIndividually
  return hasAttribute('invoiceAllOrdersIndividually');
};

/** Check if the customer should be billed using Stripe */
export const invoiceUsingStripe = () => {
  // Check if the customer has the attribute invoiceWithStripe
  return hasAttribute('invoiceWithStripe');
};

/** Check if the customer is allowed to buy spot free products */
export const canBuySpotFree = () => {
  // Check if the customer has the attribute restrictSpotFree
  return !hasAttribute('restrictSpotFree');
};

/** Check if the customer is allowed to buy interior cleaning products */
export const canBuyInteriorCleaning = () => {
  // Check if the customer has the attribute restrictInteriorCleaning
  return !hasAttribute('restrictInteriorCleaning');
};

/** Check if the customer is allowed to buy tank cleaning products */
export const canBuyTankCleaning = () => {
  // Check if the customer has the attribute restrictTankCleaning
  return !hasAttribute('restrictTankCleaning');
};

function loadOrderDetails() {
  getOrderDetails().then((response) => {
    console.log(response);
  });
}

/** Set the order id */
export const setOrderId = (id) => {
  order_id.value = id;
  // Load the order details
  loadOrderDetails();
  // Load the order items
  loadOrderItems();
};

/** Delete everything button */
export const deleteEverything = async () => {
  // If the order is created, delete it
  if (order_id.value) {
    await deleteOrder()
        .catch((error) => {
          parseError(error, 'stepError');
        });
  }
  // Clear the cache
  clearCache();
  location.reload();
};

/** Delete everything button dialog */
export const showDeleteEverythingDialog = () => {
  Swal.fire({
    title: 'Er du sikker?',
    text: 'Du er ved at slette alt i denne ordre. Dette kan ikke fortrydes.',
    icon: 'warning',
    showCancelButton: true,
    confirmButtonText: 'Ja, slet alt',
    cancelButtonText: 'Nej, fortryd',
    allowEscapeKey: false,
    allowOutsideClick: false,
    showLoaderOnConfirm: true,
  }).then((result) => {
    if (result.isConfirmed) {
      deleteEverything().then(() => {
        Swal.fire('Slettet', 'Ordren er slettet', 'success');
      });
    }
  });
};

/** Clear cache */
export const clearCache = () => {
  // Reset the query parameters
  window.history.pushState({}, '', `?step=1`);
  // Clear the customer data
  clearCustomerSelection();
  // Clear the order data
  order_id.value = null;
  order_items.value = [];
  // Clear the registration numbers
  reg_1.value = '';
  reg_2.value = '';
  reg_3.value = '';
  // Clear the scans
  scans.value = [];
};

export const clearCustomerSelection = () => {
  // Clear the customer data
  customer_id.value = '';
  customer_name.value = '';
  customer_data.value = [];
  // Clear the notes
  notes.value = [];
  order_notes.value = '';
  // Clear the attributes
  customer_attributes.value = [];
};

/** Show delete order dialog */
export const showDeleteOrderDialog = () => {
  // Require the user to confirm the deletion by writing the order number in the dialog
  Swal.fire({
    title: 'Are you sure?',
    text: 'You are about to delete the order. Please write the order number in the field below to confirm.',
    input: 'number',
    inputAttributes: {
      autocapitalize: 'off'
    },
    showCancelButton: true,
    confirmButtonText: 'Delete',
    showLoaderOnConfirm: true,
    preConfirm: (orderNumber) => {
      if (orderNumber !== order_id.value) {
        Swal.showValidationMessage('The order number does not match');
      }
    },
    allowOutsideClick: () => !Swal.isLoading()
  }).then((result) => {
    if (result.isConfirmed) {
      deleteOrder().then((response) => {
        if (response) {
          clearCache();
          location.reload();
        }
      });
    }
  });
};

/** Get users discounts */
export const getUserDiscounts = async () => {
  const token = localStorage.getItem('token');
  if (!token) {
    return null;
  }
  return axios.get(API_URL + '/superuser/user/discounts', {
    headers: {
      Authorization: `Bearer ${token}`
    },
    params: {
      customer_number: customer_id.value
    }
  }).then((response) => {
    user_discounts.value = response.data.data;
    //console.log(user_discounts.value);
    return user_discounts.value;
  }).catch((error) => {
    console.error(error);
  });
};

/** Get user product discount */
export const getUserProductDiscount = (product, allowCategory = null, onlyCategory = null) => {
  // Check if the user discounts are loaded
  if (!has_user_discounts_loaded.value) {
    has_user_discounts_loaded.value = true;
    getUserDiscounts().then(() => {});
  }

  // Get the product's id
  const productId = product.id;

  // Get the product's category
  const category = getProductsCategory(productId);

  // Find the specific discount for the product
  let discount = 0;
  let allowCategoryDiscount = null;
  let categoryDiscount = 0;
  let globalDiscount = 0;
  let productDiscount = 0;
  let allowProductDiscount = null;
  let appliedDiscount = 0;

  // Check if we should allow the category discount
  if (allowCategory || allowCategory === null) {
    // If the allowCategory is null, check if the category discount is allowed by the product
    if (allowCategory === null) {
      allowCategoryDiscount = parseInt(product.apply_category_discount) === 1;
    } else if (allowCategory) {
      allowCategoryDiscount = true;
    }
    //console.log('Allow category discount', allowCategoryDiscount);
    //console.log(product);
  }

  // Check if we should allow the product discount
  if (allowCategory === null) {
    allowProductDiscount = true;
  } else {
    allowProductDiscount = allowCategory;
  }


  // Check if we should only allow the category discount
  if (onlyCategory) {
    allowProductDiscount = false;
    //console.log('Only category discount');
  }

  // Get the global discount
  try {
    globalDiscount = parseInt(user_discounts.value.find(
        (discount) =>
            discount.id == '999999'
    ).percentage) || null;
  } catch (e) {}
  //console.log('Global discount', globalDiscount);

  try {
    productDiscount = parseInt(user_discounts.value.find(
        (discount) =>
            discount.product_or_category_id == productId && discount.is_category == '0'
    ).percentage) || null;
  } catch (e) {}
  //console.log('Product discount', productDiscount);

  try {
    categoryDiscount = parseInt(user_discounts.value.find(
        (discount) =>
            discount.product_or_category_id == category && discount.is_category == '1'
    ).percentage) || null;
  } catch (e) {}
  //console.log('Category discount', categoryDiscount);

  // If we should allow the product discount, apply it
  if (allowProductDiscount && !onlyCategory && productDiscount) {
    appliedDiscount = productDiscount;
  }

  // If the category has a discount, apply it (If the category discount is allowed, and has a higher percentage than the product discount)
  if (categoryDiscount && allowCategoryDiscount && categoryDiscount > appliedDiscount) {
    appliedDiscount = categoryDiscount;
  }

  // If the global discount is higher than the applied discount, apply it
  if (globalDiscount && globalDiscount > appliedDiscount && allowCategoryDiscount) {
    appliedDiscount = globalDiscount;
  }

  // If there's a global discount, and category discounts are allowed, apply the global discount (If it's higher than the applied discount)
  if (globalDiscount && globalDiscount > appliedDiscount && allowCategoryDiscount) {
    appliedDiscount = globalDiscount;
  }

  // If there is no discount, return 0
  if (!appliedDiscount) {
    return 0;
  }

  // Return the applied discount
  //console.log('Applied discount', appliedDiscount);
  return appliedDiscount;
};

export const showFakeCreateOrderItem = (product, quantity, price) => {
  order_items.value.push({
    id: Math.floor(Math.random() * 1000),
    product: product,
    quantity: quantity,
    price: price,
    notes: '',
    reference: ''
  });
  console.log('Fake create order item', product, quantity);
};



</script>