import { defineStore } from "pinia";
import { computed, ref } from "vue";
import axios from "axios";
import { AxiosError } from "axios";
import {
    TFilters,
    TPagination,
    TParams,
    TProduct,
    TProductAndPagination,
    TResponse,
} from "@/types/Product";
import { TPromotion } from "@/types/Promotion";

export const useProductStore = defineStore("product", () => {
    // State
    const products = ref<TProduct[]>([]);

    // Filters, pcl = product category level
    const filters = ref<TFilters>({
        page: 1,
        search: "",
        pcl1: "",
        pcl2: "",
        pcl3: "",
        brands: [] as string[],
        promotion: "",
        minPrice: null as number | null,
        maxPrice: null as number | null,
    });

    const pagination = ref<TPagination>({
        total: 0,
        current_page: 1,
        last_page: 1,
        per_page: 10,
        first_page_url: null,
        next_page_url: null,
        prev_page_url: null,
        last_page_url: null,
    });
    const loading = ref<boolean>(false);
    const responseStatus = ref<number | null>(null);
    const lastSearchQuery = ref<string>("");

    const transformProduct = (product: TProduct): TProduct => {
        // Extract original price from content
        const originalPrice =
            product?.content?.[0]?.data?.variants?.[0]?.price || 0;
        // Find the promotion with the highest discount
        const maxPromotion = (product.promotions || []).reduce(
            (
                max: { discount: number; valid_until: string },
                promotion: TPromotion
            ) => {
                const discount = promotion.discount || 0;
                if (discount > (max.discount || 0)) {
                    return {
                        discount: discount,
                        valid_until: promotion.valid_until || "",
                    };
                }
                return max;
            },
            { discount: 0, valid_until: "" }
        );

        // Extract maxDiscount and validUntil from the maxPromotion
        const maxDiscount = maxPromotion.discount;
        const validUntil = maxPromotion.valid_until;
        const isValid = new Date(validUntil) >= new Date();

        // Calculate discounted price
        const discountedPrice = originalPrice * (1 - maxDiscount / 100);

        // Return product with new fields
        return {
            ...product,
            originalPrice,
            discountedPrice: Number(discountedPrice.toFixed(2)),
            maxDiscount,
            validUntil,
            isValid,
        };
    };

    // Computed: Products with discount fields added
    const productWithDiscount = computed(() => {
        return products.value.map((product) => {
            // Extract original price from content
            const originalPrice =
                product?.content?.[0]?.data?.variants?.[0]?.price || 0;

            // Get all discounts from promotions
            const discounts = (product.promotions || []).map(
                (promotion: TPromotion) => promotion.discount ?? 0
            );

            // Find the highest discount
            const maxDiscount =
                discounts.length > 0 ? Math.max(...discounts) : 0;

            // Calculate discounted price
            const discountedPrice = originalPrice * (1 - maxDiscount / 100);

            // Return product with new fields added
            return {
                ...product,
                originalPrice,
                discountedPrice: Number(discountedPrice.toFixed(2)),
                maxDiscount,
            };
        });
    });

    // Computed: Products with promotions
    const productsWithPromotions = computed(() => {
        return products.value
            .filter((product) => (product.promotions || []).length > 0)
            .map((product) => product.id);
    });

    // Actions
    const fetchProducts = async (
        pageParam: number = 1,
        searchParam: string,
        pcl1Param: string,
        pcl2Param: string,
        pcl3Param: string,
        brandsParam: string[],
        promotionParam: string,
        minPriceParam: number | null,
        maxPriceParam: number | null
    ): Promise<void> => {
        loading.value = true;

        try {
            const finalSearch = searchParam
                ? searchParam
                : filters.value.search;
            const finalPcl1 = pcl1Param ? pcl1Param : filters.value.pcl1;
            const finalPcl2 = pcl2Param ? pcl2Param : filters.value.pcl2;
            const finalPcl3 = pcl3Param ? pcl3Param : filters.value.pcl3;
            const finalBrands = brandsParam
                ? brandsParam
                : filters.value.brands;
            const finalPromotion = promotionParam
                ? promotionParam
                : filters.value.promotion;
            const finalminPrice = minPriceParam
                ? minPriceParam
                : filters.value.minPrice;
            const finalmaxPrice = maxPriceParam
                ? maxPriceParam
                : filters.value.maxPrice;

            const params: Record<string, string | number | string[] | null> = {
                page: pageParam,
                search: finalSearch,
                pcl1: finalPcl1,
                pcl2: finalPcl2,
                pcl3: finalPcl3,
                brands: finalBrands,
                promotion: finalPromotion,
                minPrice: finalminPrice,
                maxPrice: finalmaxPrice,
            };

            const response = await axios.get<TResponse>("/api/product/search", {
                params,
            });

            console.log("response", response.data);
            console.log("products", response.data.data?.data);

            if (response.status === 200) {
                products.value = response.data.data?.data.map(transformProduct);

                pagination.value = {
                    total: response.data.data?.total ?? 0,
                    current_page: response.data.data?.current_page ?? 1,
                    last_page: response.data.data?.last_page ?? 1,
                    per_page: response.data.data?.per_page ?? 10,
                    first_page_url: response.data.data?.first_page_url ?? null,
                    next_page_url: response.data.data?.next_page_url ?? null,
                    prev_page_url: response.data.data?.prev_page_url ?? null,
                    last_page_url: response.data.data?.last_page_url ?? null,
                };
                responseStatus.value = response.status;
            } else {
                console.warn(
                    `API request failed with status: ${response.data.meta.code}`,
                    response.data
                );
                products.value = [];
                pagination.value = {
                    total: 0,
                    current_page: 1,
                    last_page: 1,
                    per_page: 10,
                    first_page_url: null,
                    next_page_url: null,
                    prev_page_url: null,
                    last_page_url: null,
                };
                responseStatus.value = response.status;
            }

            console.log("products from product store", products.value);
            console.log("filters from product store", filters.value);
        } catch (error: AxiosError | unknown) {
            console.error("Error fetching products:", error);
            products.value = [];
            responseStatus.value = null;
            pagination.value = {
                total: 0,
                current_page: 1,
                last_page: 1,
                per_page: 10,
                first_page_url: null,
                next_page_url: null,
                prev_page_url: null,
                last_page_url: null,
            };
        } finally {
            loading.value = false;
        }
    };

    const setProducts = (rawProducts: TProductAndPagination): void => {
        products.value = rawProducts.data.map(transformProduct);
        pagination.value = rawProducts.pagination;
    };

    const setFilters = ({
        pageParam = 1,
        searchParam,
        pcl1Param,
        pcl2Param,
        pcl3Param,
        brandsParam,
        promotionParam,
        minPriceParam,
        maxPriceParam,
    }: TParams): void => {
        // Check if the current state matches the new parameters before updating
        const isStateMatching =
            products.value?.length > 0 &&
            pagination.value.current_page === pageParam &&
            lastSearchQuery.value === searchParam &&
            filters.value.pcl1 === pcl1Param &&
            filters.value.pcl2 === pcl2Param &&
            filters.value.pcl3 === pcl3Param &&
            filters.value.brands === brandsParam &&
            filters.value.promotion === promotionParam &&
            filters.value.minPrice === minPriceParam &&
            filters.value.maxPrice === maxPriceParam;

        // Only update state and fetch if the state doesn't match
        if (!isStateMatching) {
            filters.value.page = pageParam;
            filters.value.search = searchParam;
            filters.value.pcl1 = pcl1Param;
            filters.value.pcl2 = pcl2Param;
            filters.value.pcl3 = pcl3Param;
            filters.value.brands = brandsParam as string[];
            filters.value.promotion = promotionParam;
            filters.value.minPrice = minPriceParam;
            filters.value.maxPrice = maxPriceParam;
            lastSearchQuery.value = searchParam;

            fetchProducts(
                pageParam,
                searchParam,
                pcl1Param,
                pcl2Param,
                pcl3Param,
                brandsParam,
                promotionParam,
                minPriceParam,
                maxPriceParam
            );
        }
    };

    const setPage = ({
        pageParam,
        searchParam = filters.value.search,
        pcl1Param = filters.value.pcl1,
        pcl2Param = filters.value.pcl2,
        pcl3Param = filters.value.pcl3,
        brandsParam = filters.value.brands as string[],
        promotionParam = filters.value.promotion,
        minPriceParam = filters.value.minPrice,
        maxPriceParam = filters.value.maxPrice,
    }: TParams): void => {
        setFilters({
            pageParam,
            searchParam,
            pcl1Param,
            pcl2Param,
            pcl3Param,
            brandsParam,
            promotionParam,
            minPriceParam,
            maxPriceParam,
        });
    };

    const clearFilters = (): void => {
        filters.value.page = 1;
        filters.value.search = "";
        filters.value.pcl1 = "";
        filters.value.pcl2 = "";
        filters.value.pcl3 = "";
        filters.value.brands = [];
        filters.value.promotion = "";
        filters.value.minPrice = null;
        filters.value.maxPrice = null;
        lastSearchQuery.value = "";

        fetchProducts(1, "", "", "", "", [], "", 0, 0);
    };

    return {
        products,
        filters,
        pagination,
        loading,
        responseStatus,
        lastSearchQuery,
        productWithDiscount,
        productsWithPromotions,
        fetchProducts,
        setProducts,
        setFilters,
        setPage,
        clearFilters,
    };
});
