import apiRequest from "../api.js";
import { getSdkData } from "./init.js";
import { logger } from "../index.js";
import { getWebSocketInstance } from "../websocket.js";
import { SDKData } from "../types/types.js";

type Position =
  | "Top Left"
  | "Top Right"
  | "Top Middle"
  | "Bottom Left"
  | "Bottom Right"
  | "Bottom Middle";

function urlBase64ToUint8Array(base64String: string): Uint8Array {
    const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
    const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
    const rawData = window.atob(base64);
    const outputArray = new Uint8Array(rawData.length);

    for (let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
    }
    return outputArray;
}
async function subscribeUserMain(swFilePath:string, vapidPublicKey:string, websiteUrl:string) {
    if ('serviceWorker' in navigator && 'PushManager' in window) {
        try {
            const registration : ServiceWorkerRegistration = await navigator.serviceWorker.register(swFilePath);
            await new Promise(resolve => setTimeout(resolve, 1000));
            if (registration.active) {
                // logger.info(`A service worker is active: ${registration.active}`);

                // const vapidPublicKey = publicVapidKey;
                const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);

                const subscription = await registration.pushManager.subscribe({
                    userVisibleOnly: true,
                    applicationServerKey: convertedVapidKey,
                });

                // logger.info("User is subscribed:", subscription);

                const userID = "gaId";
                await fetch("https://qa-ndjs-appwebnotification.erzqa.com/api/subscription/subscribe", {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json",
                    },
                    body: JSON.stringify({ subscription, userID, websiteUrl }),
                });

                return subscription;
            } else {
                throw new Error("Service worker is not active yet.");
            }
        } catch (error) {
            logger.error("Error in subscribing user:", error);
            return null;
        }
    } else {
        return null;
    }
}
async function checkAndSubscribe(currentDomain:string, swFilePath:string, vapidPublicKey:string, sdkData:SDKData) {
    let subNew: PushSubscription | null = null;

    await navigator.serviceWorker.getRegistrations().then(async (registrations) => {
        if (registrations.length === 0) {
            // logger.info("No service workers registered.");
            subNew = await subscribeUserMain(swFilePath, vapidPublicKey, sdkData.website_url);
            return subNew;
        } else {
            let foundSubscription = false;

            for (const reg of registrations) {
                let subscription = await reg.pushManager.getSubscription();

                if (subscription) {
                    // logger.info("Subscription details retrieved:", subscription);
                    const regDomain = new URL(reg.scope).hostname;
                    // const currentDomain = window.location.hostname;
                    const isMatchingDomain = regDomain === currentDomain || regDomain.endsWith(`.${currentDomain}`);

                    if (isMatchingDomain) {
                        subNew = subscription;
                        foundSubscription = true;
                    }
                    // logger.info("Domain Match:", isMatchingDomain, "Scope:", reg.scope);
                }
            }

            if (foundSubscription) {
                // logger.info("Subscription found for service worker...", subNew);
                return subNew;
            } else {
                // logger.info("No subscription found for any service worker. Subscribing...");
                subNew = await subscribeUserMain(swFilePath, vapidPublicKey, sdkData.website_url);
                return subNew;
            }
        }
    });
    return subNew;
}
async function handleNotificationSubscription(sdkData: SDKData, swFilePath: string, triggerSource: string) {
    const gaId = sdkData.userID;
    if (triggerSource === 'Box' || triggerSource === 'Bell') {
        const notificationPopup = document.querySelector('.popup-notification-er') as HTMLElement | null;;
        if (notificationPopup) {
            notificationPopup.style.display = 'none';
        }
    }

    let subscription = null;
    if ('serviceWorker' in navigator && 'PushManager' in window) {
        subscription = await checkAndSubscribe(sdkData.website_url, swFilePath, sdkData.public_vapid_key, sdkData);
    } else {
        // logger.info("Service workers or push notifications are not supported in this browser.");
    }
    let webSocketInstance = getWebSocketInstance(gaId);
    webSocketInstance.send("subscribedNotification", {
        gaId: gaId,
        website_url: sdkData.website_url,
        permission: Notification.permission,
        subscription: subscription ?? null,
        send_web_push: true,
    });
}
async function showPopupNotificationER(sdkData: SDKData, swFilePath: string) {
    const config = sdkData.opt_in_prompt;
    // Define default config if not passed
    const defaultConfig = {
        OptPromptType: "Box",
        ShowOverlyHint: true,
        Message: "Bee the first to know! Join us for instant updates on limited time offers, exclusive styles, and more.",
        Position: "Top Right",
        AllowButtonText: "Stay connected",
        DontAllowButtonText: "I'll do this later",
        BackgroundColor: "#fff",
        TextColor: "#000",
        UserClickDontAllow: "",
        Minutes: "",
        ShowOverlyBox: "true",
        TextOnHover: ""
    };
    // logger.info(config);

    // Merge the provided config with the default one
    const settings = { ...defaultConfig, ...config };

    if (settings.OptPromptType === "Native") {
        handleNotificationSubscription(sdkData, swFilePath, "Native");
        return;
    }
    if (settings.OptPromptType === "Bell") {
        const bellIcon = document.createElement("div") as HTMLElement;
        bellIcon.className = "popup-bell-icon";
        bellIcon.innerHTML = "🔔";
        document.body.appendChild(bellIcon);
    
        const positionStyles: Record<Position, Partial<CSSStyleDeclaration>> = {
            "Top Left": { top: "20px", left: "20px" },
            "Top Right": { top: "20px", right: "20px" },
            "Top Middle": { top: "20px", left: "50%", transform: "translateX(-50%)" },
            "Bottom Left": { bottom: "20px", left: "20px" },
            "Bottom Right": { bottom: "20px", right: "20px" },
            "Bottom Middle": { bottom: "20px", left: "50%", transform: "translateX(-50%)" }
        };
        
        const positionKey = settings.Position as Position;
    
        // Apply position styles
        Object.assign(bellIcon.style, {
            position: "fixed", // Ensure the bell icon is fixed
            BackgroundColor: settings.BackgroundColor,
            color: settings.TextColor || "#fff",
            fontSize: "24px",
            padding: "10px",
            borderRadius: "50%",
            cursor: "pointer",
            boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.2)",
            zIndex: "1000",
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            width: "50px",
            height: "50px",
            ...positionStyles[positionKey]
        });
    
        bellIcon.addEventListener("mouseover", () => {
            bellIcon.style.backgroundColor = settings.TextOnHover;
        });
        bellIcon.addEventListener("mouseout", () => {
            bellIcon.style.backgroundColor = settings.BackgroundColor;
        });
        bellIcon.addEventListener("click", () => {
            handleNotificationSubscription(sdkData, swFilePath, "Bell");
            bellIcon.style.display = "none";
        });
    
        return;
    }
    
    // Create the notification popup
    const notificationPopup = document.createElement("div") as HTMLElement;
    notificationPopup.className = "popup-notification-er";
    notificationPopup.innerHTML = `
        <div class="popup-notification-er-message">${settings.Message}</div>
        <div class="popup-notification-er-div">
            <button class="popup-notification-er-button" id="requestPermissionButton-notification-er-doLaterButton">${settings.DontAllowButtonText}</button>
            <button class="popup-notification-er-button" id="requestPermissionButton-notification-er-allow">${settings.AllowButtonText}</button>
        </div>
    `;

    // Define styles for the popup
    const styleElement = document.createElement("style") as HTMLElement;
    styleElement.innerHTML = `
    .popup-notification-er {
        position: fixed;
        background-color: ${settings.BackgroundColor};
        color: ${settings.TextColor};
        border-radius: 8px;
        box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.2);
        padding: 15px;
        max-width: 300px;
        z-index: 1000;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        min-width: 220px;
        min-height: 80px;
    }

    /* Position Handling */
    .popup-notification-er.top-left {
        top: 20px;
        left: 20px;
    }
    .popup-notification-er.top-right {
        top: 20px;
        right: 20px;
    }
    .popup-notification-er.top-middle {
        top: 20px;
        left: 50%;
        transform: translateX(-50%);
    }
    .popup-notification-er.bottom-left {
        bottom: 20px;
        left: 20px;
    }
    .popup-notification-er.bottom-right {
        bottom: 20px;
        right: 20px;
    }
    .popup-notification-er.bottom-middle {
        bottom: 20px;
        left: 50%;
        transform: translateX(-50%);
    }
    .popup-notification-er-message {
        color: ${settings.TextColor};
        font-size: 14px;
        margin-bottom: 15px;
        text-align: center;
    }

    .popup-notification-er-div {
        display: flex;
        justify-content: space-between;
        gap: 5px;
    }

    .popup-notification-er-button {
        background-color: #ffffff;
        color: teal;
        padding: 10px 15px;
        border: none;
        border-radius: 4px;
        cursor: pointer;
        font-size: 14px;
        flex: 1;
    }

    .popup-notification-er-button:focus {
        outline: none;
    }

    .popup-notification-er-button:hover {
        background-color: ${settings.TextOnHover};
    }
    `;

    document.head.appendChild(styleElement);

    document.body.appendChild(notificationPopup);
    notificationPopup.style.display = 'block';
    notificationPopup.classList.add(settings.Position.toLowerCase().replace(" ", "-"));


    const allowBtn = document.getElementById('requestPermissionButton-notification-er-allow');
    if (allowBtn) {
        allowBtn.addEventListener('click', async function () {
            handleNotificationSubscription(sdkData, swFilePath, "Box");
        });
    }

    const doLaterBtn = document.getElementById('requestPermissionButton-notification-er-doLaterButton');
    if (doLaterBtn) {
        doLaterBtn.addEventListener('click', () => {
            notificationPopup.style.display = 'none';
        });
    }
}

function showNotification(data: any) {
    const {
        title,
        body,
        icon,
        badge,
        image,
        data: notificationData,
    } = data;

    const notificationOptions: any = {};

    if (title) {
        notificationOptions.title = title;
    }
    if (body) {
        notificationOptions.body = body;
    }
    if (icon) {
        notificationOptions.icon = icon;
    }
    if (badge) {
        notificationOptions.badge = badge;
    }
    if (image) {
        notificationOptions.image = image;
    }
    if (notificationData) {
        notificationOptions.data = notificationData;
    }

    if (Notification.permission === "granted") {
        new Notification(title || '', notificationOptions);
    } else if (Notification.permission !== "denied") {
        Notification.requestPermission().then(function (permission) {
            if (permission === "granted") {
                new Notification(title || '', notificationOptions);
            }
        });
    }
}
async function subscribeUserPush(swFilePath: string, gaId: string) {
    const sdkData = getSdkData();
    sdkData.userID = gaId;

    if (sdkData.show_web_push === "1") {
        logger.info("✅ Web Push is enabled");

        if (Notification.permission === "default") {
            showPopupNotificationER(sdkData, swFilePath);
        } else if (Notification.permission === "granted") {
            let sub: any = null;
            if ("serviceWorker" in navigator && "PushManager" in window) {
                sub = await checkAndSubscribe(sdkData.website_url, swFilePath, sdkData.public_vapid_key, sdkData);
            } else {
                // logger.info("❌ Service workers or push notifications are not supported in this browser.");
            }

            // logger.info("📩 Subscription Data:", sub);
            let webSocketInstance = getWebSocketInstance(gaId);
            webSocketInstance.send("subscribedNotification", {
                gaId: gaId,
                website_url: sdkData.website_url,
                permission: Notification.permission,
                subscription: sub ?? null,
                send_web_push: true,
            });
            if(sub && sub.endpoint){                
                sdkData.pushSubscribed = true;
                sdkData.sub = sub;
            }
        }
    } else {
        logger.info("❌ Web Push is not enabled");
    }
}
async function sendNotification(notificationData: any) {
    const sdkData = getSdkData();
    if (sdkData.pushSubscribed) {
        return apiRequest("sendNotificationToUser", "POST", {
            "subscription": sdkData.sub,
            ...notificationData
        });
    } else{
        return {
            "success": false,
            "data": null,
            "message": "Please Subscribe",
        }
    }
    // return apiRequest("sendNotificationToUser", "POST", { notificationData });
}

// async function unsubscribeUser(gaId: string) {
//     return apiRequest("subscription/unsubscribe", "POST", { gaId });
// }

async function getSubscriptionStatus() {
    const sdkData = getSdkData();
    if (sdkData.pushSubscribed) {
        return {
            "subscribed": true,
            "sub": sdkData.sub,
        }
    } else{
        return {
            "subscribed": false,
            "sub": null,
        }
    }
}

export { subscribeUserPush, sendNotification, 
    // unsubscribeUser,
     getSubscriptionStatus, showNotification };
