import { capitalize, get } from "lodash";

import { orderStatusArrayJson } from "@/src/constants/data/orders";


interface PageData {
    linkType?: string;
    link?: string;
}

export interface Menu {
    menuType?: string;
    linkedMenuItemId?: string;
    customLink?: string;
}

export const generatePageRedirection = (data: PageData): string => {
    if (!data || Object.keys(data).length === 0) {
        return "/";
    }

    const { linkType, link } = data;

    switch (linkType) {
        default:
            return link || "/";
    }
};

export const formatImageUrl = (
    imageUrl?: string,
    returnFallback: boolean = false,
    baseUrl: string = process.env.NEXT_PUBLIC_IMAGE_URL || ''
): string => {
    const fallbackUrl = '/images/no-image.png';
    if (!imageUrl) return returnFallback ? fallbackUrl : '';

    const formattedUrl = imageUrl.startsWith('http')
        ? imageUrl
        : `${baseUrl}${imageUrl.startsWith('/') ? '' : '/'}${imageUrl}`;
    return formattedUrl;
};

export const getCrossOriginAttribute = (url: string) => {
    return url?.startsWith("http") || url?.startsWith("https") ? undefined : "anonymous";
};

export const getDisplayCurrency = (code?: string): string => {
    if (!code) return "AED";
    const clean = code.trim().toUpperCase();
    if (clean === "MYR" || clean === "RM") return "RM";
    if (clean === "$" || clean === "US$") return "USD";
    return clean;
};

export const convertCurrency = (price: number, conversionRate: number): number => {
    return price * (conversionRate || 1);
};

export const formatConvertedPrice = (price: number | undefined, currencyCode: string | undefined, conversionRate: number | undefined, decimal: number = 2): string => {
    const safePrice = price ?? 0;
    const safeCurrency = currencyCode || "AED";
    if (!conversionRate || conversionRate === 1) {
        return amountFormat(safePrice, safeCurrency, decimal);
    }
    const convertedPrice = convertCurrency(safePrice, conversionRate);
    return amountFormat(convertedPrice, safeCurrency, decimal);
};

export const amountFormat = (Amount: number | string, currencyCode?: string, decimal: number = 2, unknownValue: string = "--", zeroValue?: string): string => {
    const num = Number(Amount);
    if (isNaN(num)) {
        return unknownValue;
    }
    if (num === 0 && zeroValue !== undefined) {
        return zeroValue;
    }
    const displayCurrency = getDisplayCurrency(currencyCode);
    const formattedAmount = num.toLocaleString("en-US", {
        minimumFractionDigits: decimal,
        maximumFractionDigits: decimal,
    });
    return `${displayCurrency} ${formattedAmount}`;
};

export const generateMenuPageRedirection = (menu: Menu): string => {
    if (!menu || Object.keys(menu).length === 0) {
        return "/";
    }

    const { menuType, linkedMenuItemId, customLink } = menu;

    switch (menuType) {
        default:
            return customLink || "/";
    }
};

export type DiscountType = "amount" | "percentage" | "percent" | "amount-off";

export const calculateTotalDiscountAmountDifference = (totalAmount: number, discountType: DiscountType, discountVal: number): number => {
    let discountAmount: number;

    if (discountType === "amount" || discountType === "amount-off") {
        discountAmount = discountVal;
    } else if (discountType === "percent" || discountType === "percentage") {
        discountAmount = (discountVal / 100) * totalAmount;
    } else {
        discountAmount = 0;
    }

    return discountAmount;
};

export function calculateDiscountAmount(productVariantData: any, discountType?: string, discountValue?: number | string) {
    if (!productVariantData) {
        return 0;
    }

    const { price: originalPrice, discountPrice: discountedPrice } = productVariantData;
    let newDiscountPrice = discountedPrice > 0 ? discountedPrice : originalPrice;

    if (discountType && discountValue) {
        let newDiscountValue = 0;

        if (discountType === "amount" || discountType === "amount-off") {
            newDiscountValue = Number(discountValue);
        } else if (discountType === "percent" || discountType === "percentage") {
            newDiscountValue = (Number(discountValue) / 100) * newDiscountPrice;
        }
        if (newDiscountValue > 0) {
            newDiscountPrice -= newDiscountValue;
        }
    }

    return newDiscountPrice;
}
interface ProductVariantData {
    price: number;
    discountPrice: number;
}

export function calculateDiscountPercentage(productVariantData: ProductVariantData, discountType?: DiscountType, discountValue?: number | string): string {
    const originalPrice = productVariantData?.price;
    const finalPrice = calculateDiscountAmount(productVariantData, discountType, discountValue);

    if (originalPrice <= 0) {
        return "0%";
    }

    const difference = originalPrice - finalPrice;
    const percentage = (difference / originalPrice) * 100;
    const roundedPercentage = Math.round(percentage);

    return isNaN(roundedPercentage) ? "0%" : `${roundedPercentage}%`;
}

export const getErrorMessage = (error: any) => {
    if (typeof error === "string") {
        return error;
    } else if (error?.response?.data) {
        if (typeof error.response.data === "string") {
            return error.response.data;
        } else if (typeof error.response.data === "object") {
            return Object.values(error.response.data).join(", ");
        }
    } else if (typeof error === "object") {
        return Object.values(error).join(", ");
    } else if (error.message) {
        return error.message;
    }
    return "An unknown error occurred";
};

export const replaceHyphensAndUnderscoresWithArrow = (slug: string) => {
    if (typeof slug === "string" && slug.trim()) {
        const result = slug.replace(/-/g, " => ").replace(/_/g, " ");
        const capitalizedResult = result
            .split(" ")
            .map((word) => capitalize(word))
            .join(" ");
        return capitalizedResult.trim();
    }
    return "";
};

export const replaceHyphensWithSpace = (slug: string) => {
    return typeof slug === "string" ? slug.split("-").join(" ") : "";
};

export const isDataFresh = (lastFetched: string, hours: number = 20) => {
    if (!lastFetched) return false;

    const lastDate = new Date(lastFetched);
    const currentDate = new Date();
    const diffInMs = currentDate.getTime() - lastDate.getTime();
    const diffInHours = diffInMs / (1000 * 60 * 60);

    return diffInHours <= hours;
};

export const formatPhoneNumber = (phone: number | string | null): string => {
    if (phone) {
        let phoneNumber = phone.toString();

        if (!phoneNumber.startsWith("+971")) {
            phoneNumber = phoneNumber.replace(/^0+/, "");
            phoneNumber = "+971" + phoneNumber;
        }

        if (phoneNumber.length === 13) {
            phoneNumber = `${phoneNumber.slice(0, 4)} ${phoneNumber.slice(4, 6)} ${phoneNumber.slice(6, 9)} ${phoneNumber.slice(9)}`;
        }

        return phoneNumber;
    } else {
        return "--";
    }
};

export const getKeyByValue = (object: any, value: string): string | undefined => {
    return Object.keys(object).find((key) => object[key] === value);
};

export const removePhoneNumberPrefixAndAdd971 = (phone: number | string, countryCode: string = "971") => {
    if (phone) {
        let phoneNumber = phone.toString();
        phoneNumber = phoneNumber.startsWith("0") ? phoneNumber.slice(1) : phoneNumber;
        if (phoneNumber.startsWith("+")) {
            phoneNumber = phoneNumber.slice(1);
        }
        if (!phoneNumber.startsWith(countryCode)) {
            phoneNumber = countryCode + phoneNumber;
        }

        return phoneNumber;
    } else {
        return "Phone is not found";
    }
};

export const getDangerouslySetInnerHtmlClasses = () => {
    return "text-gray-600 leading-relaxed [&_h1]:text-2xl [&_h1]:font-bold [&_h1]:mb-4 [&_h2]:text-xl [&_h2]:font-semibold [&_h2]:mb-2 [&_h2]:mt-3 [&_ul]:list-disc [&_ul]:pl-5 [&_ul]:mb-4 [&_li]:mb-1";
};

export const separateWordsAndCapitalize = (str: string): string => {
    return str
        .split(/[\s,]+/)
        .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
        .join(", ");
};

export const sortDataWithShowOrder = (data: any[]) => {
    const sortedData = [...data].sort((a, b) => {
        const aOrder = a.showOrder !== undefined ? a.showOrder : Number.MAX_SAFE_INTEGER;
        const bOrder = b.showOrder !== undefined ? b.showOrder : Number.MAX_SAFE_INTEGER;
        return aOrder - bOrder;
    });

    return sortedData;
};

export const capitalizeWordsFirstLetter = (str: string) => {
    return (str && str?.replace(/_/g, " ").replace(/\b\w/g, (char: string) => char.toUpperCase())) || "";
};

export const isOrderCancellable = (orderDetailsData: any): boolean => {
    if (!orderDetailsData || !orderDetailsData?.products || orderDetailsData?.products?.length === 0) {
        return false;
    }

    return orderDetailsData?.products?.every((product: any) => (product.orderProductStatus) === orderStatusArrayJson.pending);
};

export const isOrderReturnable = (orderDetailsData: any, shipmentSettings: any) => {
    if (!orderDetailsData || !orderDetailsData?.products || orderDetailsData?.products?.length === 0) {
        return false;
    }

    const returnApplicableDays = parseInt(get(shipmentSettings, "returnApplicableDays"));
    const orderDate: any = new Date(orderDetailsData?.deliveredStatusAt);
    const currentDate: any = new Date();
    const timeDifference = currentDate - orderDate;
    const daysDifference = timeDifference / (1000 * 3600 * 24);
    return daysDifference <= returnApplicableDays;
};

type NormalizedHeadType =
    | "meta"
    | "src"
    | "inline"
    | "jsonld"
    | "module"
    | "link";

export const normalizeHeadType = (type?: string): NormalizedHeadType => {
    if (!type) return "inline";

    switch (type) {
        case "meta":
            return "meta";
        case "src":
            return "src";
        case "application/ld+json":
            return "jsonld";
        case "module":
            return "module";
        case "link":
            return "link";
        default:
            return "inline";
    }
};

export function replaceUnderscoreWithSpace(str: any) {
    if (!str) return "";
    return str.replace(/_/g, " ");
}

export function splitByHyphen(str: any) {
    if (typeof str !== "string") return [];
    return str.split("-");
}

export const truncateToTwoDecimals = (value: string | number) => {
    return Math.floor(Number(value) * 100) / 100
}

export const formatDateTimeLocal = (dateString: string) => {
    if (!dateString) return "";
    const date = new Date(dateString);

    const offset = date.getTimezoneOffset();
    const localDate = new Date(date.getTime() - offset * 60000);

    return localDate.toISOString().slice(0, 16); // YYYY-MM-DDTHH:mm
};

export const formatChatDate = (dateString: string) => {
    const date = new Date(dateString);
    const today = new Date();

    const isToday =
        date.toDateString() === today.toDateString();

    if (isToday) {
        return date.toLocaleTimeString([], {
            hour: "2-digit",
            minute: "2-digit",
            hour12: true,
        });
    }

    const yesterday = new Date();
    yesterday.setDate(today.getDate() - 1);

    if (date.toDateString() === yesterday.toDateString()) {
        return "Yesterday";
    }

    if (date.getFullYear() === today.getFullYear()) {
        return date.toLocaleDateString("en-GB", {
            day: "2-digit",
            month: "short",
        });
    }

    return date.toLocaleDateString("en-GB", {
        day: "2-digit",
        month: "short",
        year: "numeric",
    });
};

export const formatDateTime12 = (dateStr: string) => {
    if (!dateStr) return "";

    const date = new Date(dateStr);

    const datePart = date.toLocaleDateString("en-GB"); // 17/06/2026
    const timePart = date.toLocaleTimeString([], {
        hour: "2-digit",
        minute: "2-digit",
        hour12: true,
    });

    return `${datePart} ${timePart}`;
};