import type { CreatePureScopedStylesheetCallbackArgs } from "@devowl-wp/web-scoped-css";
import { mapIsSet, mapStringArrayToBoolean, mapStringToBoolean, mapValueSuffixPx } from "@devowl-wp/web-scoped-css";

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

type BlockerStyleSheetReturn = MainStyleSheetReturn &
    ReturnType<ReturnType<typeof extendIndividualBlockerStylesheet>[1]> &
    ReturnType<(typeof extendBlockerStylesheet)[1]>;

/**
 * Only make variables which are different per visual content blocker available with this extension
 * as it is an detached style extension.
 */
const extendIndividualBlockerStylesheet = (
    reactRootSymbol: symbol,
    {
        presetId,
        isVisualDarkMode,
        visualBlur,
        visualContentType,
        visualType,
        visualThumbnail: visualThumbnailValue,
    }: CustomizeBlocker,
) =>
    [
        reactRootSymbol,
        ({
            className,
            vars,
            variable,
            meta: { id: individualBlockerClassName },
        }: CreatePureScopedStylesheetCallbackArgs) => {
            // Generate unique IDs for accessibility
            const a11yIds = {
                firstButton: className(),
            };

            const [blocker] = vars(
                {
                    isVisualDarkMode,
                    visualBlur,
                    visualContentType,
                    visualType,
                    presetId,
                },
                {
                    visualType: mapStringToBoolean(visualType, ["wrapped"]),
                    visualContentType: mapStringToBoolean(visualContentType, ["audio-player", "video-player"]),
                    visualBlur: mapValueSuffixPx,
                    // Special cases for known presets (e.g. Youtube Play button)
                    presetId: mapStringToBoolean(presetId, ["youtube", "vimeo"]),
                },
            );

            const useVisualThumbnailValue = visualThumbnailValue || ({} as typeof visualThumbnailValue);
            const { forceRatio, hide, titleType, width, height } = useVisualThumbnailValue;

            const [visualThumbnail] = vars(
                {
                    hide: hide || [],
                    forceRatio: forceRatio || 0,
                    titleType: titleType || "top",
                    width,
                    height,
                },
                {
                    // Keep unitless as we work with `aspect-ratio` CSS property
                    //forceRatio: mapValueSuffix("%"),
                    //width: mapValueSuffixPx,
                    //height: mapValueSuffixPx,
                    titleType: mapStringToBoolean(visualThumbnailValue?.titleType, ["center", "top"]),
                    hide: mapStringArrayToBoolean(visualThumbnailValue?.hide, ["overlay", "title"]),
                },
            );

            const forceRatioIsset = variable(forceRatio, mapIsSet);

            return {
                a11yIds,
                blocker,
                visualThumbnail: { ...visualThumbnail, forceRatioIsset },
                individualBlockerClassName,
            };
        },
    ] as const;

const extendBlockerStylesheet = [
    Symbol("extendBlockerStylesheet"),
    (
        { jsx, boolIf, computed, className }: CreatePureScopedStylesheetCallbackArgs,
        {
            layout: { dialogBorderRadius, type },
            design: { textAlign, fontFamily, fontInheritFamily, fontColor, borderWidth, borderColor },
            headerDesign: { borderWidth: headerDesignBorderWidth, borderColor: headerDesignBorderColor },
            footerDesign: { borderWidth: footerDesignBorderWidth, borderColor: footerDesignBorderColor },
            blocker,
            isMobile,
        }: MainStyleSheetReturn & ReturnType<ReturnType<typeof extendIndividualBlockerStylesheet>[1]>,
    ) => {
        const { isDialog, isBanner } = computed([type], ([type]) => {
            return { type, isDialog: type === "dialog", isBanner: type === "banner" };
        });

        const hasBg = blocker.visualType("is-wrapped");
        const fixedDialog = className();

        // Calculate a border color for the complete box as the standard box does not have one configured
        const blockerOverwrites = computed(
            [
                borderWidth,
                borderColor,
                headerDesignBorderWidth,
                headerDesignBorderColor,
                footerDesignBorderWidth,
                footerDesignBorderColor,
                fontColor,
            ],
            ([
                borderWidth,
                borderColor,
                headerDesignBorderWidth,
                headerDesignBorderColor,
                footerDesignBorderWidth,
                footerDesignBorderColor,
                fontColor,
            ]) => ({
                borderWidth: mapValueSuffixPx(borderWidth || 1),
                borderColor:
                    borderWidth === 0
                        ? headerDesignBorderWidth > 0
                            ? headerDesignBorderColor
                            : footerDesignBorderWidth > 0
                              ? footerDesignBorderColor
                              : fontColor
                        : borderColor,
            }),
        );

        const [Inner] = jsx("div", {
            classNames: "inner",
            textAlign: textAlign("val"),
            fontFamily: boolIf(fontInheritFamily, "inherit", fontFamily()),
            color: fontColor("hex"),
            borderRadius: boolIf(isDialog, dialogBorderRadius()),
            border: `${blockerOverwrites.borderWidth()} solid ${blockerOverwrites.borderColor()}`,
            position: "relative",
            padding: boolIf({ when: hasBg, then: { when: isMobile, then: "20px 30px", or: "30px 50px" } }),
            overflow: boolIf(hasBg, "hidden"),
        });

        const [Content] = jsx("div", {
            classNames: "content",
            boxShadow: boolIf(hasBg, "#0000004d 0px 0px 100px 30px, 0px 2px 5px 2px #0000001c"),
            borderRadius: boolIf({
                when: hasBg,
                then: {
                    when: isDialog,
                    then: dialogBorderRadius(),
                },
            }),
            position: "relative",
        });

        const [InnerBackground] = jsx(
            "img",
            {
                classNames: "inner-bg",
                objectFit: "cover",
                position: "absolute",
                top: 0,
                left: 0,
                width: "100%",
                height: "100%",
                filter: `blur(${blocker.visualBlur()})`,
            },
            {
                loading: "lazy",
            },
        );

        return { isDialog, isBanner, Inner, Content, InnerBackground, blockerOverwrites, fixedDialog };
    },
] as const;

export { extendIndividualBlockerStylesheet, extendBlockerStylesheet, type BlockerStyleSheetReturn };
