import type { CreatePureScopedStylesheetCallbackArgs, PureScopedStyleSheetRules } from "@devowl-wp/web-scoped-css";
import { createRenderedDimensionVariables, cssRgba, mapStringToBoolean } from "@devowl-wp/web-scoped-css";

import type { MainStyleSheetReturn } from "../main.js";

type BannerStyleSheetReturn = MainStyleSheetReturn & ReturnType<(typeof extendBannerStylesheet)[1]>;

const extendBannerStylesheet = [
    Symbol("extendBannerStylesheet"),
    (
        {
            computed,
            rule,
            boolIf,
            boolNot,
            boolSwitch,
            jsx,
            variable,
            className,
            vars,
            varName,
            plugin,
        }: CreatePureScopedStylesheetCallbackArgs,
        {
            unsetDialogStyles,
            customize: { activeAction: activeActionValue, pageRequestUuid4 },
            boolLargeOrMobile,
            isMobile,
            layout: {
                dialogPosition,
                dialogMaxWidth,
                dialogMargin,
                dialogBorderRadius,
                bannerPosition,
                overlay,
                overlayBg,
                overlayBgAlpha,
                overlayBlur,
            },
            design: {
                boxShadowEnabled,
                boxShadowColor,
                boxShadowOffsetX,
                boxShadowOffsetY,
                boxShadowBlurRadius,
                boxShadowSpreadRadius,
                boxShadowColorAlpha,
                fontSize,
                borderWidth,
                borderColor,
                textAlign,
                fontInheritFamily,
                fontFamily,
                fontWeight,
                fontColor,
            },
            mobile,
            layout,
            individualLayout,
        }: MainStyleSheetReturn,
    ) => {
        // Generate unique IDs for accessibility
        const a11yIds = {
            headline: className(),
            description: className(),
            firstButton: className(),
        };

        // Banner-specific variables
        const dimsOverlay = createRenderedDimensionVariables(varName, vars);
        const dimsContent = createRenderedDimensionVariables(varName, vars);
        const dimsHeader = createRenderedDimensionVariables(varName, vars);
        const dimsFooter = createRenderedDimensionVariables(varName, vars);
        const dimsRightSidebar = createRenderedDimensionVariables(varName, vars);
        const activeAction = variable(activeActionValue, mapStringToBoolean(activeActionValue, ["history"]));
        const individualPrivacyOpen = variable(false as boolean, undefined, "individual");

        // Force banner on mobile view
        const { isDialog, isBanner } = computed([isMobile, layout.type], ([isMobile, layout]) => {
            const use = isMobile ? "banner" : layout;
            return { type: use, isDialog: use === "dialog", isBanner: use === "banner" };
        });

        const alignCpt = computed(
            [dialogPosition],
            ([dialogPosition]) => [
                dialogPosition.startsWith("top")
                    ? "flex-start"
                    : dialogPosition.startsWith("bottom")
                      ? "flex-end"
                      : "center",
                dialogPosition.endsWith("Center")
                    ? "center"
                    : dialogPosition.endsWith("Left")
                      ? "flex-start"
                      : "flex-end",
            ],
            "dialogAlign",
        );

        let backdropFilter = "none";
        if (process.env.PLUGIN_CTX === "pro") {
            /* onlypro:start */
            backdropFilter = boolIf(overlay, `blur(${overlayBlur()})`);
            /* onlypro:end */
        }

        const [Overlay] = jsx("div", {
            classNames: "bann3r",
            position: "fixed",
            top: 0,
            left: 0,
            right: 0,
            bottom: 0,
            zIndex: 999999,
            filter: "none",
            maxWidth: "100vw",
            maxHeight: "100vh",
            fontSize: fontSize("l"),
            background: boolIf(overlay, cssRgba(overlayBg, overlayBgAlpha)),
            pointerEvents: boolIf(overlay, "all", "none"),
            backdropFilter,
            transform: "translateZ(0)",
        });

        const [Dialog] = jsx(
            "dialog",
            {
                classNames: ["align", unsetDialogStyles],
                display: "flex",
                width: "100%",
                height: "100%",
                alignItems: boolIf(isDialog, alignCpt(0)),
                justifyContent: boolIf(isDialog, alignCpt(1)),
            },
            {
                tabIndex: 0,
                "aria-labelledby": a11yIds.headline,
                "aria-describedby": a11yIds.description,
                "aria-modal": "true",
                autofocus: "true",
            },
        );

        // Inner container
        const width = boolIf({
            when: isDialog,
            then: {
                when: [individualPrivacyOpen, boolNot(individualLayout.inheritDialogMaxWidth)],
                then: individualLayout.dialogMaxWidth(),
                or: dialogMaxWidth(),
            },
            or: "100%",
        });
        const { alignment } = mobile;
        const border = `${boolLargeOrMobile(borderWidth, boolIf)} solid ${borderColor()}`;
        const useDialogBorderRadius = boolIf(isDialog, dialogBorderRadius());
        const [, inner] = rule({
            classNames: "inner",
            pointerEvents: "all",
            transition: "width 500ms, max-width 500ms",
            overflow: "hidden",
            maxWidth: width,
            width,
            textAlign: textAlign("val"),
            fontFamily: boolIf(fontInheritFamily, "inherit", fontFamily()),
            fontWeight: fontWeight(),
            color: fontColor("hex"),
            margin: boolIf({
                when: [isDialog, boolNot(dialogPosition["is-middlecenter"])],
                then: dialogMargin(),
                or: boolIf(isDialog, "10px"),
            }),
            borderRadius: useDialogBorderRadius,
            boxShadow: boolIf(
                boxShadowEnabled,
                `${boxShadowOffsetX()} ${boxShadowOffsetY()} ${boxShadowBlurRadius()} ${boxShadowSpreadRadius()} rgba(${boxShadowColor(
                    "r",
                )} ${boxShadowColor("g")} ${boxShadowColor("b")} / ${boxShadowColorAlpha()})`,
            ),
            alignSelf: boolIf({
                when: isMobile,
                then: boolSwitch([
                    [alignment("is-bottom"), "flex-end"],
                    [alignment("is-top"), "flex-start"],
                    [alignment("is-center"), "center"],
                ]),
                or: {
                    when: isBanner,
                    then: boolSwitch([
                        [bannerPosition("is-top"), "flex-start"],
                        [bannerPosition("is-bottom"), "flex-end"],
                    ]),
                },
            }),
            borderTop: boolIf({
                when: [isBanner, bannerPosition("is-bottom")],
                then: border,
            }),
            borderBottom: boolIf({
                when: [isBanner, bannerPosition("is-top")],
                then: border,
            }),
        });

        const forceResetRules: PureScopedStyleSheetRules = {
            boxSizing: "border-box",
            backfaceVisibility: "initial",
            textTransform: "initial",
            // See https://stackoverflow.com/a/2711132/5506547
            "-webkit-text-size-adjust": "100%",
        };

        rule({
            forceSelector: `#${pageRequestUuid4}, #${pageRequestUuid4} *`,
            ...forceResetRules,
        });

        plugin("modifyRule", (props) => {
            if (props.all === "unset") {
                for (const property in forceResetRules) {
                    if (!Object.prototype.hasOwnProperty.call(props, property)) {
                        props[property] = forceResetRules[property];
                    }
                }
            }
        });

        // Apply an additional border radius to the header, body and footer depending on visibility of each component
        // as a border radius applied to the whole component which compose all three elements could lead to pixel issues.
        const footerHeaderBorderStyle = `${boolIf(isDialog, borderWidth("l"), "0px")} solid ${borderColor()}`;
        const footerBorderStyle: PureScopedStyleSheetRules = {
            borderBottomLeftRadius: useDialogBorderRadius,
            borderBottomRightRadius: useDialogBorderRadius,
            borderLeft: footerHeaderBorderStyle,
            borderRight: footerHeaderBorderStyle,
            borderBottom: footerHeaderBorderStyle,
        };
        const headerBorderStyle: PureScopedStyleSheetRules = {
            borderTopLeftRadius: useDialogBorderRadius,
            borderTopRightRadius: useDialogBorderRadius,
            borderLeft: footerHeaderBorderStyle,
            borderRight: footerHeaderBorderStyle,
            borderTop: footerHeaderBorderStyle,
        };

        return {
            a11yIds,
            isDialog,
            isBanner,
            activeAction,
            dimsOverlay,
            dimsContent,
            dimsHeader,
            dimsFooter,
            dimsRightSidebar,
            individualPrivacyOpen,
            Dialog,
            Overlay,
            inner,
            footerBorderStyle,
            headerBorderStyle,
        };
    },
] as const;

export { type BannerStyleSheetReturn, extendBannerStylesheet };
