import { create } from 'zustand'
import * as ItemController from '../client/controllers/ItemController'
import { CreateItemQuery } from '../client/queries/CreateItemQuery'
import { SetItemPriceQuery } from '../client/queries/SetItemPriceQuery'
import { ItemHistoryResponse, ItemPriceResponse, OrderFilledResponse, OrderItemPriceResponse } from '../client/response'

export type ItemData = {
	items: ItemPriceResponse[],
	orderItems: OrderItemPriceResponse[]
	itemHistories: ItemHistoryResponse[]
}

export type ItemActions = {
	sync: () => Promise<void>
	createItem: (itemName: string, inSeason: boolean, itemPrice: number) => Promise<ItemPriceResponse>
	setItemPrice: (itemId: number, price: number) => Promise<void>
	getCurrentPrice: (itemId: number) => Promise<ItemPriceResponse>
	addItemToOrder: (itemId: number, orderId: number, quantity: number) => Promise<OrderItemPriceResponse>
	getOrderItems: (orderId: number) => Promise<OrderItemPriceResponse[]>
	setItemMade: (orderId: number, itemId: number, made: number) => Promise<OrderFilledResponse>
	setItemQuantity: (orderId: number, itemId: number, quantity: number) => Promise<OrderFilledResponse>
	deleteOrderItem: (orderId: number, itemId: number) => Promise<void>
	deleteItem: (itemId: number) => Promise<void>
	getItemHistory: (itemId: number) => Promise<ItemHistoryResponse[]>
}

export const useItemStore = create<ItemData & ItemActions>((set, get) => ({
	items: [],
	orderItems: [],
	itemHistories: [],
	sync: async (): Promise<void> => {
		const itemPrices = await ItemController.GetItems()
		set((state) => ({
			...state,
			items: itemPrices
		}))
	},
	createItem: async (itemName: string, inSeason: boolean, itemPrice: number): Promise<ItemPriceResponse> => {
		const itemQuery: CreateItemQuery = {
			item_name: itemName,
			in_season: inSeason ? "1" : "0",
			item_price: itemPrice.toString()
		}

		const itemResponse = await ItemController.CreateItem(itemQuery)
		set((state) => ({
			...state,
			items: [...state.items, itemResponse]
		}))
		return itemResponse
	},
	setItemPrice: async (itemId: number, price: number): Promise<void> => {
		const itemPriceQuery: SetItemPriceQuery = {
			item_id: itemId.toString(),
			item_price: price.toString()
		}

		const itemPrice = await ItemController.SetItemPrice(itemPriceQuery)

		set((state) => {
			const item = state.items.filter((i) => i.ItemId === itemId)[0]
			let itemsWithoutItem = state.items.filter((i) => i.ItemId !== itemId)
			item.ItemPrice = price
			if(!Array.isArray(itemsWithoutItem))
				itemsWithoutItem = [itemsWithoutItem]
			return {
				...state,
				items: [...itemsWithoutItem, item].sort((a,b) => {
					if(a.InSeason && !b.InSeason)
						return 1
					if(!a.InSeason && b.InSeason)
						return -1
					return a.ItemId - b.ItemId
				}),
				itemHistories: [...state.itemHistories, {
					ItemId: itemPrice.ItemId.toString(),
					ItemName: itemPrice.ItemName,
					ItemPrice: (Math.trunc(itemPrice.ItemPrice * 100) / 100).toString(),
					ValidFrom: new Date().toLocaleDateString(),
					ValidTo: new Date().toLocaleDateString()
				} as ItemHistoryResponse]
			}
		})
	},
	getCurrentPrice: async (itemId: number): Promise<ItemPriceResponse> => {
		const store = get()

		const priceObjectArray = store.items.filter((i: ItemPriceResponse) => i.ItemId === itemId)

		if(priceObjectArray.length > 0) {
			return priceObjectArray[0]
		}
		
		const resp = await ItemController.GetCurrentPrice({item_id: itemId.toString()})

		set((state) => ({
			...state,
			items: [...state.items, resp]
		}))
		return resp
	},
	addItemToOrder: async (itemId: number, orderId: number, quantity: number): Promise<OrderItemPriceResponse> => {
		const resp = await ItemController.AddItemToOrder({item_id: itemId.toString(), order_id: orderId.toString(), quantity: quantity.toString()})

		set((state) => ({
			...state,
			orderItems: [...state.orderItems, resp]
		}))

		return resp
	},
	getOrderItems: async (orderId: number): Promise<OrderItemPriceResponse[]> => {
		const state = get()
		
		const fetchedOrderItems = state.orderItems
		
		const orderOrderItems = fetchedOrderItems.filter((i) => i.OrderId === orderId)

		if(orderOrderItems.length > 0) {
			return orderOrderItems
		}
		
		const resp = await ItemController.GetOrderItems({order_id: orderId.toString()})
		
		set((state) => ({
			orderItems: [...state.orderItems, ...resp]
		}))

		return resp
	},
	setItemMade: async (orderId: number, itemId: number, made: number): Promise<OrderFilledResponse> => {
		const order_filled: OrderFilledResponse = await ItemController.SetItemMade({
			order_id: orderId,
			item_id: itemId,
			made: made
		})

		set((state) => {
			// TODO: Update order filled once order store is made
			const orderItem = state.orderItems.filter((oi) => oi.ItemId === itemId && oi.OrderId === orderId)[0]
			const orderItemsWithoutOrderItem = state.orderItems.filter((oi) => oi.ItemId !== itemId || oi.OrderId !== orderId)
			orderItem.Made = made

			return {
				...state,
				orderItems: [...orderItemsWithoutOrderItem, orderItem]
			}
		})

		return order_filled
	},
	setItemQuantity: async (orderId: number, itemId: number, quantity: number): Promise<OrderFilledResponse> => {
		const order_filled: OrderFilledResponse = await ItemController.SetItemQuantity({
			order_id: orderId,
			item_id: itemId,
			quantity: quantity
		})

		set((state) => {
			// TODO: Update order filled once order store is made
			const orderItem = state.orderItems.filter((oi) => oi.ItemId === itemId && oi.OrderId === orderId)[0]
			const orderItemsWithoutOrderItem = state.orderItems.filter((oi) => oi.ItemId !== itemId || oi.OrderId !== orderId)
			
			orderItem.Quantity= quantity

			return {
				...state,
				orderItems: [...orderItemsWithoutOrderItem, orderItem]
			}
		})

		return order_filled

	},
	deleteOrderItem: async (orderId: number, itemId: number): Promise<void> => {
		await ItemController.DeleteOrderItem({order_id: orderId, item_id: itemId})

		set((state) => ({
			...state,
			orderItems: [...(state.orderItems.filter((i) => i.OrderId !== orderId || i.ItemId !== itemId))]
		}))
	},
	deleteItem: async (itemId: number): Promise<void> => {
		await ItemController.DeleteItem(itemId)

		set((state) => {
			const itemsWithoutItem = state.items.filter((i) => i.ItemId !== itemId)
			const orderItemsWithoutItem = state.orderItems.filter((i) => i.ItemId !== itemId)

			return {
				...state,
				items: itemsWithoutItem,
				orderItems: orderItemsWithoutItem
			}
		})
	},
	getItemHistory: async (itemId: number): Promise<ItemHistoryResponse[]> => {
		const currHist = get().itemHistories.filter((ih) => parseInt(ih.ItemId) === itemId)
		if(currHist.length > 0)
			return currHist
		const itemHistory = await ItemController.GetItemHistory(itemId)

		set((state) => ({
			...state,
			itemHistories: [...state.itemHistories, ...itemHistory]
		}))

		return itemHistory
	}
}))
