import { createPinia } from 'pinia'
import { __ } from '@wordpress/i18n'
import { ref } from 'vue'
import { applyQuantityStep, getI18n, isMinQuantity as isQuantityAtMin, l10nObj, normalizeQuantity, sanitizeSubtitleHtml } from '@/helper'
import { useCollectionsStore } from '@/api'
import $ from 'jquery'
import {
  notification,
} from 'ant-design-vue'
import { generatePaginationItems } from '@/utils/pagination'
import { filterEligibleCartItems, filterSelectedCartItems, addCartItemsSequentially, finalizeAddToCart } from '@/utils/cartUtils'
import type { CartItem } from '@/utils/cartUtils'
import { attachEscHandler, detachEscHandler } from '../shared/escHandler'
import { refreshWishlistData } from '../shared/wishlistDataMethods'
import { isAllSelected, toggleAllSelection, toggleItemSelection } from '../shared/wishlistSelection'

const pinia = createPinia()

const { getGuestWishlistProducts, getWishlists } = useCollectionsStore(pinia)

const loadedObject = l10nObj()
const wcCurrency = loadedObject.wcCurrency
const isLoggedIn = loadedObject.isLoggedIn
const proDependencies = loadedObject.proDependencies || {}
const activePro = proDependencies?.activePro || false
const disablePublicWishlists = !!proDependencies?.disablePublicWishlists

// Guest wishlist items use item.product.id (the WooCommerce product ID) as the variation key.
const getItemKey = (item: CartItem): number => item.product.id
const publicWishlistsTitle = proDependencies?.publicWishlistsTitle || getI18n('public_wishlists_title', __('Public Wishlists', 'saveto-wishlist-lite-for-woocommerce'))
const publicWishlistsDescription = proDependencies?.publicWishlistsDescription || getI18n('public_wishlists_subtitle', __('Browse publicly shared wishlists from other users.', 'saveto-wishlist-lite-for-woocommerce'))

// Translatable strings.
const searchPlaceholder = getI18n('search_placeholder', __('Search for anything...', 'saveto-wishlist-lite-for-woocommerce'))
const searchLabel = getI18n('search_label', __('Search', 'saveto-wishlist-lite-for-woocommerce'))
const clearSearch = getI18n('clear_search', __('Clear search', 'saveto-wishlist-lite-for-woocommerce'))
const tableInfoString = getI18n('table_info', __('Showing %1$s-%2$s of %3$s items', 'saveto-wishlist-lite-for-woocommerce'))
const emptyTitle = getI18n('empty_product_title', __('No products found', 'saveto-wishlist-lite-for-woocommerce'))
const emptyDescription = getI18n('empty_product_description', __('Add products to your wishlist to get started.', 'saveto-wishlist-lite-for-woocommerce'))
const loginToView = getI18n('login_to_view', __('Login to view your wishlists.', 'saveto-wishlist-lite-for-woocommerce'))
const continueShopping = getI18n('continue_shopping', __('Continue Shopping', 'saveto-wishlist-lite-for-woocommerce'))
const guestWishlist = getI18n('guest_wishlist', __('Guest Wishlist', 'saveto-wishlist-lite-for-woocommerce'))
const guestWishlistDescription = getI18n('guest_wishlist_description', __('Login or create an account to get started.', 'saveto-wishlist-lite-for-woocommerce'))
const loading = getI18n('loading', __('Loading...', 'saveto-wishlist-lite-for-woocommerce'))
const cancel = getI18n('cancel', __('Cancel', 'saveto-wishlist-lite-for-woocommerce'))
const confirmDeleteTitle = getI18n('confirm_delete_title', __('Delete Item', 'saveto-wishlist-lite-for-woocommerce'))
const confirmRemoveItemMessage = getI18n('confirm_remove_item_message', __('Are you sure you want to remove this item from the wishlist?', 'saveto-wishlist-lite-for-woocommerce'))

const table = {
  show: getI18n('show', __('Show', 'saveto-wishlist-lite-for-woocommerce')),
  previous: getI18n('previous', __('Previous', 'saveto-wishlist-lite-for-woocommerce')),
  next: getI18n('next', __('Next', 'saveto-wishlist-lite-for-woocommerce')),
  add_to_cart: getI18n('add_to_cart', __('Add to Cart', 'saveto-wishlist-lite-for-woocommerce')),
  delete: getI18n('delete', __('Delete', 'saveto-wishlist-lite-for-woocommerce')),
  name: getI18n('column_name', __('Name', 'saveto-wishlist-lite-for-woocommerce')),
  status: getI18n('column_status', __('Status', 'saveto-wishlist-lite-for-woocommerce')),
  date_added: getI18n('column_date_added', __('Date Added', 'saveto-wishlist-lite-for-woocommerce')),
  actions: getI18n('column_actions', __('Actions', 'saveto-wishlist-lite-for-woocommerce')),
  product_table: {
    image: getI18n('product_table.image', __('Image', 'saveto-wishlist-lite-for-woocommerce')),
    name: getI18n('product_table.name', __('Product Name', 'saveto-wishlist-lite-for-woocommerce')),
    price: getI18n('product_table.price', __('Price', 'saveto-wishlist-lite-for-woocommerce')),
    date_added: getI18n('product_table.date_added', __('Date Added', 'saveto-wishlist-lite-for-woocommerce')),
    stock_status: getI18n('product_table.stock_status', __('Stock Status', 'saveto-wishlist-lite-for-woocommerce')),
    quantity: getI18n('product_table.quantity', __('Quantity', 'saveto-wishlist-lite-for-woocommerce')),
    priority: getI18n('product_table.priority', __('Priority', 'saveto-wishlist-lite-for-woocommerce')),
    subtotal: getI18n('product_table.subtotal', __('Subtotal', 'saveto-wishlist-lite-for-woocommerce')),
    actions: getI18n('product_table.actions', __('Actions', 'saveto-wishlist-lite-for-woocommerce')),
  },
  in_stock: getI18n('in_stock', __('In stock', 'saveto-wishlist-lite-for-woocommerce')),
  allow_backorder: getI18n('allow_backorder', __('Allow backorder', 'saveto-wishlist-lite-for-woocommerce')),
  out_of_stock: getI18n('out_of_stock', __('Out of stock', 'saveto-wishlist-lite-for-woocommerce')),
  adding_item: getI18n('adding_item', __('Adding to cart...', 'saveto-wishlist-lite-for-woocommerce')),
  select_options: getI18n('select_options', __('Select options', 'saveto-wishlist-lite-for-woocommerce')),
  add_all_to_cart: getI18n('add_all_to_cart', __('Add All to Cart', 'saveto-wishlist-lite-for-woocommerce')),
  adding_all_to_cart: getI18n('adding_all_to_cart', __('Adding all to cart...', 'saveto-wishlist-lite-for-woocommerce')),
  add_selected_to_cart: getI18n('add_selected_to_cart', __('Add Selected to Cart', 'saveto-wishlist-lite-for-woocommerce')),
  adding_selected_to_cart: getI18n('adding_selected_to_cart', __('Adding selected to cart...', 'saveto-wishlist-lite-for-woocommerce')),
  decrease_quantity: getI18n('decrease_quantity', __('Decrease quantity', 'saveto-wishlist-lite-for-woocommerce')),
  increase_quantity: getI18n('increase_quantity', __('Increase quantity', 'saveto-wishlist-lite-for-woocommerce')),
}
const publicText = getI18n('public', __('Public', 'saveto-wishlist-lite-for-woocommerce'))

const wishlist = ref<any>({
  continueShopping: continueShopping,
  isLoggedIn: isLoggedIn,
  searchPlaceholder: searchPlaceholder,
  searchLabel: searchLabel,
  clearSearch: clearSearch,
  userRole: loadedObject.user_role,
  table: table,
  empty: {
    title: emptyTitle,
    description: emptyDescription,
  },
  loginToView: loginToView,
  pageUrls: loadedObject.pageUrls,
  guestWishlist: guestWishlist,
  guestWishlistDescription: guestWishlistDescription,
  loading: loading,
  activePro: activePro,
  disablePublicWishlists: disablePublicWishlists,
  publicWishlistsTitle: publicWishlistsTitle,
  publicWishlistsDescription: publicWishlistsDescription,
  public: publicText,
  sanitizeSubtitleHtml: sanitizeSubtitleHtml,
  cancel: cancel,
  confirmDeleteTitle: confirmDeleteTitle,
  confirmRemoveItemMessage: confirmRemoveItemMessage,
  pageStyles: loadedObject.pageStyles || {},
})

const getPublicWishlists = async (params: any) => {
  let lists: any[] = []
  let pagination = {
    current: 1,
    pageSize: 10,
    total: 0,
    totalPages: 0,
  }

  await getWishlists({
    page: params.page,
    posts_per_page: params.posts_per_page,
    search: params.search,
    status: '',
    is_public: 1,
    sort_column: params.sort_column,
    sort_order: params.sort_order,
  }).then((response: any) => {

    // Pagination
    pagination = {
      ...pagination,
      total: response.total,
      totalPages: Math.ceil(response.total / params.posts_per_page),
    }

    // Table data
    lists = response.data.map((item: any) => ({
      ...item,
      status: item.status,
    }))

  }).catch((e: any) => {
    if (e.error?.message) {
      notification.error({
        message: getI18n('error', __('Error', 'saveto-wishlist-lite-for-woocommerce')),
        description: e.error?.message,
        class: 'wishlist-lists-error-notification',
      })
    }
  })

  return {
    lists,
    pagination,
  }
}

const wishlistGuestMounted = () => {
  return {
    wishlist,
    lists: [] as any[],
    fetchingItems: false,
    search: '',
    status: '',
    deletingItem: false,
    deletingItemId: 0,
    deleteConfirmPopup: false,
    deleteConfirmId: 0 as number,
    _escHandler: null as null | ((e: KeyboardEvent) => void),
    addingItem: false,
    addingAllItems: false,
    addingSelectedItems: false,
    addingItemId: 0,
    selectedItems: [] as number[],
    selectedDefaultVariation: [] as any[],
    selectedVariation: [] as any[],
    sortColumn: 'id',
    sortOrder: 'DESC',
    pagination: {
      current: 1,
      pageSize: 10,
      total: 0,
      totalPages: 0,
    },
    tableInfo: '',
    publicLists: [] as any[],
    fetchingPublicItems: false,
    publicSearch: '',
    publicSortColumn: 'id',
    publicSortOrder: 'DESC',
    publicPagination: {
      current: 1,
      pageSize: 10,
      total: 0,
      totalPages: 0,
    },
    publicTableInfo: '',
    user_id: 0,
    get wishlistData() {
      // Get all wishlists from local storage.
      const wishlists = localStorage.getItem('stw_wishlist')
      if (wishlists) {
        this.fetchingItems = true

        const guestWishlists = JSON.parse(wishlists)

        // Get all products.
        getGuestWishlistProducts(guestWishlists).then((response: any) => {
          const filtered = this.search
            ? response.filter((item: any) => item.product?.name?.toLowerCase().includes(this.search.toLowerCase()))
            : response
          this.lists = this.handleGetWishlistData(filtered)
          this.pagination.total = filtered.length
          this.pagination.totalPages = Math.ceil(filtered.length / this.pagination.pageSize)
          this.fetchingItems = false
          this.updatePagination()
          this.assignDefaultVariation()
        })
      }

      return {
        lists: this.lists,
        pagination: this.pagination,
      }
    },
    handleGetWishlistData(lists: any[]) {
      const startIndex = (this.pagination.current - 1) * this.pagination.pageSize
      const endIndex = startIndex + this.pagination.pageSize
      const paginatedLists = lists.slice(startIndex, endIndex)

      return paginatedLists
    },
    handleGetTotalItems() {
      const wishlists = localStorage.getItem('stw_wishlist')
      if (wishlists) {
        const guestWishlists = JSON.parse(wishlists)
        return Object.keys(guestWishlists).length
      }

      return 0
    },
    handleGetTotalPages() {
      const wishlists = localStorage.getItem('stw_wishlist')
      if (wishlists) {
        const guestWishlists = JSON.parse(wishlists)
        return Math.ceil(Object.keys(guestWishlists).length / this.pagination.pageSize)
      }

      return 0
    },
    get allSelected(): boolean {
      return isAllSelected(this, getItemKey)
    },
    toggleSelectAll() {
      toggleAllSelection(this, getItemKey)
    },
    toggleSelectItem(productId: number) {
      toggleItemSelection(this, productId)
    },
    onSearch() {
      this.pagination.current = 1
      this.wishlistData
    },
    clearSearch() {
      this.search = ''
      this.pagination.current = 1
      this.wishlistData
    },
    handleSort(column: string) {
      this.sortColumn = column
      this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc'
      this.wishlistData
    },
    updateTableInfo() {
      const startIndex = (this.pagination.current - 1) * this.pagination.pageSize + 1
      const endIndex = Math.min(this.pagination.current * this.pagination.pageSize, this.pagination.total)

      this.tableInfo = tableInfoString.replace('%1$s', startIndex.toString()).replace('%2$s', endIndex.toString()).replace('%3$s', this.pagination.total.toString())
    },
    handleItemsPerPageChange(event: any) {
      this.pagination.pageSize = parseInt(event.target.value)
      this.selectedItems = []
      this.wishlistData
    },
    handlePagination(direction: string) {
      if (direction === 'prev' && this.pagination.current > 1) {
        this.pagination.current--
      } else if (direction === 'next' && this.pagination.current < this.pagination.total) {
        this.pagination.current++
      }

      this.selectedItems = []
      this.wishlistData
    },
    handlePaginationNumber(page: number) {
      this.pagination.current = page
      this.selectedItems = []
      this.wishlistData
    },
    updatePagination() {
      this.updateTableInfo()
    },
    handleDeleteItem(productId: number) {
      this.deleteConfirmId = productId
      this.deleteConfirmPopup = true
      this._escHandler = attachEscHandler(() => this.handleDeleteItemCancel())
    },
    handleDeleteItemConfirm() {
      const productId = this.deleteConfirmId
      this.deleteConfirmPopup = false
      this.deleteConfirmId = 0
      this._escHandler = detachEscHandler(this._escHandler)
      this.deletingItem = true
      this.deletingItemId = productId

      // Remove item from wishlist.
      const wishlists = localStorage.getItem('stw_wishlist')
      if (wishlists) {
        const guestWishlists = JSON.parse(wishlists)
        const productIdStr = String(productId)

        delete guestWishlists[productIdStr]

        localStorage.setItem('stw_wishlist', JSON.stringify(guestWishlists))

        this.deletingItem = false
        this.deletingItemId = 0
      }

      this.wishlistData
    },
    handleDeleteItemCancel() {
      this.deleteConfirmPopup = false
      this.deleteConfirmId = 0
      this._escHandler = detachEscHandler(this._escHandler)
    },
    handleQuantityChange(productId: number, event: any) {
      // Update item quantity.
      const wishlists = localStorage.getItem('stw_wishlist')
      if (wishlists) {
        const guestWishlists = JSON.parse(wishlists)
        const productIdStr = String(productId)

        const quantity = normalizeQuantity(event.target.value)
        event.target.value = quantity

        guestWishlists[productIdStr].quantity = quantity

        localStorage.setItem('stw_wishlist', JSON.stringify(guestWishlists))
      }
    },
    handleQuantityStep(item: { quantity: number | string; product: { id: number } }, delta: number) {
      const next = applyQuantityStep(item, delta)
      if (next === null) return
      item.quantity = next

      const wishlists = localStorage.getItem('stw_wishlist')
      if (wishlists) {
        const guestWishlists = JSON.parse(wishlists)
        const productIdStr = String(item.product.id)
        if (guestWishlists[productIdStr]) {
          guestWishlists[productIdStr].quantity = next
          localStorage.setItem('stw_wishlist', JSON.stringify(guestWishlists))
        }
      }
    },
    isMinQuantity(item: { quantity: number | string }): boolean {
      return isQuantityAtMin(item)
    },
    hasNoPrice(item: any): boolean {
      return item.product.price === '' || item.product.price === null
    },
    calculateSubtotal(product: any, quantity: number) {
      if (product.price === '' || product.price === null) {
        return '&mdash;'
      }
      const qty = normalizeQuantity(quantity)
      if (product.type === 'variable') {
        const price = (product.variations.variations.find((variation: any) => variation.variation_id === this.selectedVariation[product.id])?.price * qty) || 0
        return wcCurrency.currency_symbol + parseFloat(price.toString()).toFixed(wcCurrency.decimals ?? 2)
      } else {
        const price = (product.price * qty) || 0
        return wcCurrency.currency_symbol + parseFloat(price.toString()).toFixed(wcCurrency.decimals ?? 2)
      }
    },
    handleAddToCart(productType: string, collectionId: string, productId: number, quantity: number) {
      const self = this
      const data = {
        action: 'stwlite_add_to_cart',
        nonce: loadedObject.ajax.nonce,
        collection_id: collectionId,
        product_id: productId,
        quantity: quantity,
        product_type: productType,
        variation_id: this.selectedVariation[productId] || 0,
      }

      this.addingItemId = productId
      this.addingItem = true

      $.ajax({
        type: 'POST',
        url: loadedObject.ajax.url,
        data: data,
        success: function (res) {
          if (res.status === 'error') {
            notification.error({
              message: getI18n('error', __('Error', 'saveto-wishlist-lite-for-woocommerce')),
              description: res.message,
              class: 'wishlist-lists-error-notification',
            })
          } else {
            notification.success({
              message: res.message,
              class: 'wishlist-lists-success-notification',
            })

            self.addingItem = false
            self.addingItemId = 0

            // Refresh WooCommerce cart fragments.
            document.body.dispatchEvent(new CustomEvent('wc_fragment_refresh'));

            // Remove item from wishlist.
            if (loadedObject.wishlistOptions.autoRemoveProductFromWishlist === 'yes') {
              self.handleDeleteItem(productId)
            }

            // Refresh wishlist items.
            self.wishlistData
          }
        }
      })
    },
    async handleAddAllToCart() {
      if (this.addingAllItems) return

      const itemsToAdd = filterEligibleCartItems(this.lists, this.selectedVariation, getItemKey)

      if (itemsToAdd.length === 0) {
        notification.warning({
          message: getI18n('no_items_to_add', __('No eligible items to add to cart.', 'saveto-wishlist-lite-for-woocommerce')),
          class: 'wishlist-lists-warning-notification',
        })
        return
      }

      this.addingAllItems = true

      const result = await addCartItemsSequentially(itemsToAdd, this.selectedVariation, getItemKey)

      this.addingAllItems = false

      finalizeAddToCart(result, () => refreshWishlistData(this))
    },
    async handleAddSelectedToCart() {
      if (this.addingSelectedItems || this.selectedItems.length === 0) return

      const itemsToAdd = filterSelectedCartItems(this.lists, this.selectedItems, this.selectedVariation, getItemKey)

      if (itemsToAdd.length === 0) {
        notification.warning({
          message: getI18n('no_items_to_add', __('No eligible items to add to cart.', 'saveto-wishlist-lite-for-woocommerce')),
          class: 'wishlist-lists-warning-notification',
        })
        return
      }

      this.addingSelectedItems = true

      const result = await addCartItemsSequentially(itemsToAdd, this.selectedVariation, getItemKey)

      this.addingSelectedItems = false
      this.selectedItems = []

      finalizeAddToCart(result, () => refreshWishlistData(this))
    },
    assignDefaultVariation() {
      this.lists.forEach((item: any) => {
        if (
          item.product.type === 'variable' &&
          item.product.variations?.attributes &&
          Object.keys(item.product.variations?.attributes).length > 0
        ) {
          const attributes = item.product.variations.attributes
          if (!this.selectedDefaultVariation[item.product.id]) {
            this.selectedDefaultVariation[item.product.id] = {}
          }
          Object.keys(attributes).forEach((attribute) => {
            this.selectedDefaultVariation[item.product.id][attribute] =
              attributes[attribute][0]?.name || ''
          })

          this.handleVariationChange(item.product)
          this.calculateSubtotal(item.product, item.quantity)
        }
      })
    },
    handleVariationChange(product: any) {
      const productId = product.id
      const variations = product.variations.variations

      // Get the selected attributes for this product
      const selectedAttributes = this.selectedDefaultVariation[productId] || {} as any;

      // Find the variation that matches all selected attributes
      let variation = variations.find((item: any) => {
        return Object.keys(selectedAttributes).every(attr => {
          return item.attributes[attr] === selectedAttributes[attr]
        })
      })

      const variationId = variation?.variation_id
      this.selectedVariation[productId] = variationId

      // Change the product status and image in the list.
      this.lists.forEach((item: any) => {
        if (item.product.id === productId) {
          item.product.stock = variation?.stock
          if (variation?.image_url) {
            item.product.image_url = variation.image_url
          }
        }
      })
    },
    get publicWishlistData() {

      if (!wishlist.value.activePro || (wishlist.value.activePro && wishlist.value.disablePublicWishlists)) {
        return {
          lists: [],
          pagination: {
            current: 1,
            pageSize: 10,
          },
        }
      }

      const params = {
        page: this.publicPagination.current,
        posts_per_page: this.publicPagination.pageSize,
        search: this.publicSearch,
        status: '',
        sort_column: this.publicSortColumn,
        sort_order: this.publicSortOrder,
      }

      this.fetchingPublicItems = true

      getPublicWishlists(params).then((res: any) => {
        this.publicLists = res.lists
        this.publicPagination.total = res.pagination.total
        this.publicPagination.totalPages = res.pagination.totalPages
        this.fetchingPublicItems = false
        this.updatePublicPagination()
      })

      return {
        lists: this.publicLists,
        pagination: this.publicPagination,
      }
    },
    onPublicSearch() {
      this.publicWishlistData
    },
    clearPublicSearch() {
      this.publicSearch = ''
      this.publicWishlistData
    },
    handlePublicSort(column: string) {
      this.publicSortColumn = column
      this.publicSortOrder = this.publicSortOrder === 'asc' ? 'desc' : 'asc'
      this.publicWishlistData
    },
    updatePublicTableInfo() {
      const startIndex = (this.publicPagination.current - 1) * this.publicPagination.pageSize + 1
      const endIndex = Math.min(this.publicPagination.current * this.publicPagination.pageSize, this.publicPagination.total)

      this.publicTableInfo = tableInfoString.replace('%1$s', startIndex.toString()).replace('%2$s', endIndex.toString()).replace('%3$s', this.publicPagination.total.toString())
    },
    handlePublicItemsPerPageChange(event: any) {
      this.publicPagination.pageSize = parseInt(event.target.value)
      this.publicWishlistData
    },
    handlePublicPagination(direction: string) {
      if (direction === 'prev' && this.publicPagination.current > 1) {
        this.publicPagination.current--
      } else if (direction === 'next' && this.publicPagination.current < this.publicPagination.totalPages) {
        this.publicPagination.current++
      }

      this.publicWishlistData
    },
    handlePublicPaginationNumber(page: number) {
      this.publicPagination.current = page
      this.publicWishlistData
    },
    updatePublicPagination() {
      this.updatePublicTableInfo()
    },
    get publicPaginationItems() {
      const current = this.publicPagination.current
      const totalPages = this.publicPagination.totalPages

      return generatePaginationItems(current, totalPages)
    },
    getUserName(id: string) {
      // Guests don't have access to user data
      return ''
    },
  }
}

export default wishlistGuestMounted