import { createTariff } from "@root/api/tariff"
import { CustomTariffUserValuesMap, ServiceKeyToPriceMap } from "@root/model/customTariffs"
import { ServiceKeyToPrivilegesMap } from "@root/model/privilege"
import { produce } from "immer"
import { create } from "zustand"
import { devtools, persist } from "zustand/middleware"
import { Discount, PrivilegeWithAmount/* , findCartDiscount */, findDiscountFactor/* , findLoyaltyDiscount *//* , findPrivilegeDiscount *//* , findServiceDiscount  */} from "@frontend/kitui"
import { findNkoDiscount, calcCart } from "@root/utils/calcCart/calcCart"
import { useCartStore } from "./cart"
import { FullTariff } from "@root/model/tariff"


interface CustomTariffsStore {
    privilegeByService: ServiceKeyToPrivilegesMap;
    userValuesMap: CustomTariffUserValuesMap;
    summaryPriceBeforeDiscountsMap: ServiceKeyToPriceMap;
    summaryPriceAfterDiscountsMap: ServiceKeyToPriceMap;
}

const initialState: CustomTariffsStore = {
	privilegeByService: {},
	userValuesMap: {},
	summaryPriceBeforeDiscountsMap: {},
	summaryPriceAfterDiscountsMap: {},
}

function findLoyaltyDiscount(
    purchasesAmount: number,
    discounts: Discount[],
): Discount | null {
    const applicableDiscounts = discounts.filter(discount => {
        return (
            discount.Layer === 4 &&
            discount.Condition.UserType !== "nko" &&
            purchasesAmount >= Number(discount.Condition.PurchasesAmount)
        );
    });

    if (!applicableDiscounts.length) return null;

    const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
        return Number(current.Condition.PurchasesAmount) > Number(prev.Condition.PurchasesAmount) ? current : prev;
    });

    return maxValueDiscount;
}


function findServiceDiscount(
    serviceKey: string,
    currentPrice: number,
    discounts: Discount[],
): Discount | null {
    const applicableDiscounts = discounts.filter(discount => {
        return (
            discount.Layer === 2 &&
            discount.Condition.Group === serviceKey &&
            currentPrice >= Number(discount.Condition.PriceFrom)
        );
    });

    if (!applicableDiscounts.length) return null;

    const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
        return Number(current.Condition.PriceFrom) > Number(prev.Condition.PriceFrom) ? current : prev;
    });

    return maxValueDiscount;
}


export const useCustomTariffsStore = create<CustomTariffsStore>()(
	persist(
		devtools(
			(set, get) => initialState,
			{
				name: "Custom tariffs",
				enabled: process.env.NODE_ENV === "development",
			}),
		{
			name: "customTariffs",
			partialize: state => ({
				userValuesMap: state.userValuesMap,
				summaryPriceBeforeDiscountsMap: state.summaryPriceBeforeDiscountsMap,
				summaryPriceAfterDiscountsMap: state.summaryPriceAfterDiscountsMap,
			}),
			migrate: () => initialState,
		}
	)
)

function findPrivilegeDiscount(
    privilegeId: string,
    privilegePrice: number,
    discounts: Discount[],
): Discount | null {
    const applicableDiscounts = discounts.filter(discount => {
        const conditionMinPrice = parseFloat(discount.Condition.Term);
        if (!isFinite(conditionMinPrice)) throw new Error(`Couldn't parse Discount.Condition.Term: ${discount.Condition.Term}`);

        return (
            discount.Layer === 1 &&
            privilegeId === discount.Condition.Product &&
            privilegePrice >= conditionMinPrice
        );
    });

    if (!applicableDiscounts.length) return null;

    const maxValueDiscount = applicableDiscounts.reduce((prev, current) =>
        parseFloat(current.Condition.Term) > parseFloat(prev.Condition.Term) ? current : prev
    );

    return maxValueDiscount;
}


export const setCustomTariffs = (customTariffs: ServiceKeyToPrivilegesMap) => useCustomTariffsStore.setState({ privilegeByService: customTariffs })
function findCartDiscount(
    cartPurchasesAmount: number,
    discounts: Discount[],
): Discount | null {
    const applicableDiscounts = discounts.filter(discount => {
        return (
            discount.Layer === 3 &&
            cartPurchasesAmount >= discount.Condition.CartPurchasesAmount
        );
    });

    if (!applicableDiscounts.length) return null;

    const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {

        return Number(current.Condition.CartPurchasesAmount) > Number(prev.Condition.CartPurchasesAmount) ? current : prev;
    });

    return maxValueDiscount;
}

export const setCustomTariffsUserValue = (
	serviceKey: string,
	privilegeId: string,
	value: number,
	discounts: Discount[],
	currentCartTotal: number,
	purchasesAmount: number,
	isUserNko: boolean,
) => useCustomTariffsStore.setState(
	produce<CustomTariffsStore>(state => {
		state.userValuesMap[serviceKey] ??= {}
		state.userValuesMap[serviceKey][privilegeId] = value
  

		const privilegeWithoutAmount = state.privilegeByService[serviceKey].find(p => p._id === privilegeId)
		if (!privilegeWithoutAmount) throw new Error(`Privilege not found: ${privilegeId}`)
		let priceWithoutDiscounts = 0
		let priceAfterDiscounts = 0
    const privileges = new Array<PrivilegeWithAmount>()

    Object.keys(state.userValuesMap[serviceKey]).forEach(e => {
      const pwa = state.privilegeByService[serviceKey].find(p => p._id === e)
      if (!pwa) return
      if (state.userValuesMap[serviceKey][e] > 0)
      privileges.push({
        ...pwa, 
          amount: state.userValuesMap[serviceKey][e]
      })
    })

    let tariff: FullTariff = {
      _id: "",
      name: "",
      price: 0,
      description: "",
      isCustom: true,
      isDeleted: false,
      privileges: privileges,
    }
	const cart = calcCart([...Object.values(useCartStore.getState().cartTariffMap as Record<string, FullTariff>), tariff], discounts, purchasesAmount, isUserNko)

		const nkoDiscount = findNkoDiscount(discounts)

		if (isUserNko && nkoDiscount) {
			state.privilegeByService[serviceKey].forEach(privilege => {
				const amount = state.userValuesMap[serviceKey]?.[privilege._id] ?? 0
				priceWithoutDiscounts += privilege.price * amount
			})

			priceAfterDiscounts = priceWithoutDiscounts * findDiscountFactor(nkoDiscount)
		} else {
			state.privilegeByService[serviceKey].forEach(privilege => {
				const amount = state.userValuesMap[serviceKey]?.[privilege._id] ?? 0
        console.log(amount, serviceKey, privilege._id)
				priceWithoutDiscounts += privilege.price * amount

        const discount = cart.allAppliedDiscounts?.find(e => e.Condition.Product === privilege.privilegeId)
        console.log(discount, privilege.price*amount, findDiscountFactor(discount))
				//const discount = findPrivilegeDiscount(privilege.privilegeId, amount, discounts)
				priceAfterDiscounts += privilege.price * amount * findDiscountFactor(discount)
			})
      console.log(priceAfterDiscounts)

			const serviceDiscount = cart.allAppliedDiscounts?.find(e => e.Condition.Group === serviceKey)
			priceAfterDiscounts *= findDiscountFactor(serviceDiscount)
      console.log(serviceDiscount, serviceKey, priceAfterDiscounts, discounts)

			const cartDiscount = findCartDiscount(currentCartTotal+priceAfterDiscounts, discounts)
			priceAfterDiscounts *= findDiscountFactor(cartDiscount)

			const loyaltyDiscount = findLoyaltyDiscount(purchasesAmount, discounts)
			priceAfterDiscounts *= findDiscountFactor(loyaltyDiscount)
		}
    console.log('cTC', cart)

		state.summaryPriceBeforeDiscountsMap[serviceKey] = priceWithoutDiscounts
		state.summaryPriceAfterDiscountsMap[serviceKey] = priceAfterDiscounts
	})
)

export const createAndSendTariff = (serviceKey: string) => {
	const state = useCustomTariffsStore.getState()

	const privileges: PrivilegeWithAmount[] = []

	Object.entries(state.userValuesMap[serviceKey]).forEach(([privilegeId, userValue]) => {
		if (userValue === 0) return

		const privilegeWithoutAmount = state.privilegeByService[serviceKey].find(p => p._id === privilegeId)
		if (!privilegeWithoutAmount) throw new Error(`Privilege not found: ${privilegeId}`)

		const privilege: PrivilegeWithAmount = {
			...privilegeWithoutAmount,
			privilegeId: privilegeWithoutAmount.privilegeId,
			amount: userValue,
		}

		privileges.push(privilege)
	})

	const name = [...privileges.map(p => p.name), new Date().toISOString()].join(", ")

	const tariff = {
		name,
		isCustom: true,
		privileges,
	}

	return createTariff(tariff)
}

export const clearCustomTariffs = () => useCustomTariffsStore.setState({ ...initialState })
