import { CheckCircleFilled, ExclamationCircleFilled } from "@ant-design/icons";
import { Result, Tag } from "antd";
import { observer } from "mobx-react";
import { useEffect, useState } from "react";

import type { SettingAccessibilityChangedEvent } from "@devowl-wp/customize";
import { SETTING_ACCESSIBILITY_CHANGED_EVENT, SameSectionAccordion } from "@devowl-wp/customize";

import { __, _i } from "../../utils/i18n.js";

import type { FC } from "react";

function createHierarchy(settings: SettingAccessibilityChangedEvent[], showPassed?: boolean) {
    const root: Record<string, any> = {};
    const removeUnderscoreProperty: any[] = [];

    for (const strKey in settings) {
        const setting = settings[strKey];
        const { breadcrumb, valid } = setting;
        if (valid && !showPassed) {
            continue;
        }

        const parts = breadcrumb.split(" ▸ ").map((part) => part.trim());
        let current = root;

        for (const part of parts) {
            if (!current[part]) {
                current[part] = {
                    __: setting,
                };
                removeUnderscoreProperty.push(current[part]);
            }
            current = current[part];
        }
    }

    for (const remove of removeUnderscoreProperty) {
        const { __, ...rest } = remove;
        if (Object.keys(rest).length > 0) {
            delete remove.__;
        }
    }

    return root;
}

const TreeNode: FC<{ node: ReturnType<typeof createHierarchy> }> = ({ node }) => {
    if (Object.keys(node).length === 0) {
        return null;
    }

    return (
        <ul style={{ listStyle: "disc", paddingLeft: 20 }}>
            {Object.keys(node).map((key) => {
                const { __ } = node[key] as { __?: SettingAccessibilityChangedEvent };

                return (
                    <li key={key} style={__ ? { listStyle: "none", marginLeft: -20 } : undefined}>
                        {__ ? (
                            <>
                                {__.valid ? (
                                    <CheckCircleFilled style={{ color: "green" }} />
                                ) : (
                                    <ExclamationCircleFilled style={{ color: "#df3b3b" }} />
                                )}
                                &nbsp;
                                <a
                                    href="#"
                                    onClick={(e) => {
                                        __.instance.focus();
                                        e.preventDefault();
                                    }}
                                >
                                    {key}
                                </a>
                            </>
                        ) : (
                            <>
                                {key}
                                <TreeNode node={node[key]} />
                            </>
                        )}
                    </li>
                );
            })}
        </ul>
    );
};

const CustomizeA11yScore: FC = observer(() => {
    const [open, setOpen] = useState(false);
    const [settings, setSettings] = useState<
        Record<SettingAccessibilityChangedEvent["setting"], SettingAccessibilityChangedEvent>
    >({});
    const [showPassed, setShowPassed] = useState(false);

    // Also, allow autofocus by a customAutofocus (this is not a standard!)
    useEffect(() => {
        if (window.location.href.indexOf("customAutofocus[rcb-a11y-score]=1") > -1) {
            setOpen(true);
        }
    }, []);

    // Listen to `useA11yDispatcher` and save all "catched" accessibility properties in `settings`
    useEffect(() => {
        document.addEventListener(SETTING_ACCESSIBILITY_CHANGED_EVENT, (({
            detail,
        }: CustomEvent<SettingAccessibilityChangedEvent>) => {
            if (detail.setting.startsWith("rcb-")) {
                setSettings((s) => ({ ...s, [detail.setting]: detail }));
            }
        }) as any);
    }, []);

    const values = Object.values(settings).filter(({ visible }) => visible);
    values.sort(({ breadcrumb: a }, { breadcrumb: b }) => a.localeCompare(b));
    const { score, max: scoreMax } = values.reduce(
        (p, { valid }) => {
            p.max++;
            if (valid) {
                p.score++;
            }
            return p;
        },
        { max: 0, score: 0 } as { score: number; max: number },
    );
    const percent = (score / scoreMax) * 100;
    const scoreColor = percent >= 95 ? "green" : percent >= 50 ? "orange" : "red";

    return (
        <SameSectionAccordion
            state={open}
            onToggle={() => setOpen(!open)}
            title={
                <>
                    {__("Accessibility score")} <Tag color={scoreColor}>{percent.toFixed(0)} %</Tag>
                </>
            }
        >
            <p className="description">
                {_i(
                    __(
                        "Reach 100 points to meet all of Real Cookie Banner's recommendations for making your cookie banner be easily accessible to people with disabilities on the basis of the {{a}}WCAG Standard 2.2{{/a}}. You can find out which sections of your cookie banner need to be changed and which improvements we suggest under the individual options in the customizer.",
                    ),
                    {
                        a: <a href={__("https://www.w3.org/TR/WCAG22/")} target="_blank" rel="noreferrer" />,
                    },
                )}
            </p>
            {percent === 100 ? (
                <Result
                    status="success"
                    subTitle={__(
                        "Congratulations, your Cookie Banner is accessible! Thank you for making your cookie banner easily accessible to people with disabilities.",
                    )}
                />
            ) : (
                <>
                    <p className="description">
                        {__("The following configurations do not comply with the requirements:")}
                    </p>
                    <p style={{ textAlign: "right" }}>
                        <a onClick={() => setShowPassed(!showPassed)}>
                            {showPassed ? __("Hide passed rules") : __("Show passed rules")}
                        </a>
                    </p>
                    <TreeNode node={createHierarchy(values, showPassed)} />
                </>
            )}
        </SameSectionAccordion>
    );
});

export { CustomizeA11yScore };
