import { Fragment, useCallback, useEffect, useMemo, useState } from "react";

import { findUsedVendorsForDeclaration } from "@devowl-wp/cookie-consent-web-client";
import { jsxJoin, reactNl2Br } from "@devowl-wp/react-utils";
import { extendCommonGroupsStylesheet, extendCommonStylesheet } from "@devowl-wp/web-cookie-banner";

import { useBanner } from "../../../../contexts/banner.js";
import { useBannerStylesheet } from "../../../../hooks/banner/useBannerStylesheet.js";
import { useDurationText } from "../../../../hooks/common/useDurationText.js";
import { generatePluralText } from "../../../../hooks/common/useTeachings.js";
import { Checkbox } from "../../../common/checkbox.js";
import { CookieProperty } from "../../../common/groups/cookieProperty.js";
import { LinkToggle } from "../../../common/linkToggle.js";
import { getTcfDataRetentionTimeForPurpose } from "../vendors/vendor.js";

import type { DataCategory, Declarations, Purpose } from "@iabtechlabtcf/core";
import type { ComponentProps, FC } from "react";

const BannerTcfDeclaration: FC<{
    declaration: keyof Omit<Declarations, "stacks">;
    id: number;
}> = ({ declaration, id }) => {
    const { Link, Cookie } = useBannerStylesheet()
        .extend(...extendCommonStylesheet)
        .extend(...extendCommonGroupsStylesheet);

    const [isOpen, setIsOpen] = useState(false);
    const generateDurationText = useDurationText();
    const {
        tcf: { gvl, model },
        tcfFilterBy,
        group: { descriptionFontSize },
        lazyLoadedDataForSecondView,
        activeAction,
        i18n: {
            purpose,
            showMore,
            hideMore,
            tcf: { example, vendors, vendorsCount, dataRetentionPeriod },
        },
    } = useBanner();
    const {
        [declaration]: { [id.toString()]: declarationObj },
    } = gvl;

    const { name, description, illustrations } = declarationObj as Purpose & DataCategory;

    const isEssentialDeclaration = ["specialPurposes", "features", "dataCategories"].indexOf(declaration) > -1;
    const isDisabled = activeAction === "history" || isEssentialDeclaration;
    const checkedList = isEssentialDeclaration
        ? undefined
        : model[
              declaration === "specialFeatures"
                  ? "specialFeatureOptins"
                  : tcfFilterBy === "legInt"
                    ? "purposeLegitimateInterests"
                    : "purposeConsents"
          ];

    // Save checked in own state cause the model does not trigger a re-render
    const modelIsChecked = isEssentialDeclaration || !!checkedList?.has(id);
    const [isChecked, setIsChecked] = useState(modelIsChecked);

    // Update our checked state depending on the original value (e.g. switch of legInt | consent filter)
    useEffect(() => {
        setIsChecked(modelIsChecked);
    }, [modelIsChecked]);

    const handleCheckbox: ComponentProps<typeof Checkbox>["onToggle"] = useCallback(
        (checked) => {
            try {
                checkedList[checked ? "set" : "unset"](id);
                setIsChecked(checked);
            } catch (e) {
                // Silence is golden.
            }
        },
        [id, checkedList, setIsChecked],
    );

    // Calculate all vendors using this declaration
    const useVendors = useMemo(
        () => findUsedVendorsForDeclaration(gvl, model, id, declaration, tcfFilterBy === "legInt", true),
        [gvl, model, id, declaration, tcfFilterBy],
    );

    return (
        <Cookie>
            <Checkbox
                hideCheckbox={["purposes", "specialFeatures"].indexOf(declaration) === -1}
                isChecked={isChecked}
                isDisabled={isDisabled}
                fontSize={descriptionFontSize}
                onToggle={handleCheckbox}
                after={
                    <LinkToggle
                        onToggle={setIsOpen}
                        showMore={showMore}
                        hideMore={hideMore}
                        groupLabel={name}
                        bullets
                    />
                }
            >
                <strong>{name}</strong> ({generatePluralText(useVendors.length, ...vendorsCount)})
            </Checkbox>
            {isOpen && (
                <Fragment>
                    <CookieProperty label={purpose} value={reactNl2Br(description)}>
                        {illustrations?.length > 0 &&
                            illustrations.map((illustration, i) => (
                                <CookieProperty
                                    key={illustration}
                                    label={`${example} #${i + 1}`}
                                    value={illustration}
                                />
                            ))}
                    </CookieProperty>
                    <CookieProperty
                        label={vendors}
                        value={jsxJoin(
                            useVendors.map(({ id: vendorId, name, urls, dataRetention }) => (
                                <Link
                                    key={vendorId}
                                    href={
                                        lazyLoadedDataForSecondView?.tcf?.vendors[vendorId]?.urls?.[0]?.privacy ||
                                        "about:blank"
                                    }
                                    target="_blank"
                                    rel="noreferrer"
                                >
                                    {name}
                                    {["purposes", "specialPurposes"].indexOf(declaration) > -1 && dataRetention
                                        ? ` (${dataRetentionPeriod}: ${generateDurationText(
                                              getTcfDataRetentionTimeForPurpose(dataRetention, id, false),
                                              "d",
                                          )})`
                                        : ""}
                                </Link>
                            )),
                            ", ",
                        )}
                    />
                </Fragment>
            )}
        </Cookie>
    );
};

export { BannerTcfDeclaration };
