import { CheckOutlined } from "@ant-design/icons";
import { App, Image, List, Popconfirm, Spin } from "antd";
import { observer } from "mobx-react";
import { useCallback, useState } from "react";

import { useUpsellModalVisualContentBlocker } from "@devowl-wp/react-cookie-banner-admin";
import { isUrl } from "@devowl-wp/react-utils";

import { useStores } from "../../../store/stores.js";
import { __ } from "../../../utils/i18n.js";
import { request } from "../../../utils/request.js";
import { locationRestMigrationPost } from "../../../wp-api/migration.post.js";
import { useProModalMobileExperience } from "../../customize/controls/mobileSwitcher.js";

import type {
    ParamsRouteMigrationPost,
    RequestRouteMigrationPost,
    ResponseRouteMigrationPost,
} from "../../../wp-api/migration.post.js";
import type { FC } from "react";

type DashboardTileMigration = {
    id: string;
    headline: string;
    description: string;
    actions: Record<
        string,
        {
            id: string;
            title: string;
            description: string;
            performed: false | string;
            linkText?: string;
            linkClasses: string;
            linkDisabled: boolean;
            confirmText?: string;
            callback?: string | [Record<string, unknown>, string] | [string, string] | Record<string, unknown>;
            previewImage?: string;
            performedLabel?: string;
            needsPro: boolean;
            info?: string;
        }
    >;
};

const DashboardMigrationCardContent: FC = observer(() => {
    const { message } = App.useApp();
    const [busy, setBusy] = useState(false);
    const {
        optionStore: {
            dashboardMigration: { id: migrationId, description, actions },
            others: { isPro },
        },
    } = useStores();
    const [overrideActions, setOverrideActions] = useState<
        Record<string, Partial<DashboardTileMigration["actions"][""]>>
    >({});
    const [performedActions, setPerformedActions] = useState<string[]>([]);

    const proModalMobileExperience = useProModalMobileExperience();
    const proModalVisualContentBlocker = useUpsellModalVisualContentBlocker();

    // We do not have this currently in a store / model as it should be only made through this dashboard tile
    const handleClick = useCallback(async ({ id, callback }: (typeof actions)[0]) => {
        if (typeof callback === "string" && isUrl(callback)) {
            // Directly redirect to this page as there is no server callback
            window.location.href = callback;
        } else {
            setBusy(true);
            try {
                const {
                    success,
                    redirect,
                    message: actionSuccessMessage,
                    overrideAction,
                } = await request<RequestRouteMigrationPost, ParamsRouteMigrationPost, ResponseRouteMigrationPost>({
                    location: locationRestMigrationPost,
                    params: {
                        migration: migrationId,
                        action: id,
                    },
                });

                if (success) {
                    if (redirect) {
                        window.location.href = redirect;
                    } else {
                        message.success(actionSuccessMessage || __("Successfully saved changes!"));

                        if (overrideAction) {
                            setOverrideActions((state) => ({
                                ...state,
                                [id]: overrideAction,
                            }));
                            setPerformedActions((v) => [...v, id]);
                        }
                    }
                }
            } catch (e) {
                // Silence is golden. Currently - we do ignore errors
            } finally {
                setBusy(false);
            }
        }
    }, []);

    return (
        <Spin spinning={busy}>
            <p className="description" dangerouslySetInnerHTML={{ __html: description }} />
            <List
                itemLayout="vertical"
                size="small"
                dataSource={Object.values(actions)}
                renderItem={(action) => {
                    const {
                        id,
                        title,
                        description,
                        linkText,
                        linkClasses,
                        linkDisabled,
                        confirmText,
                        previewImage,
                        performed,
                        performedLabel,
                        needsPro,
                        info,
                    } = {
                        ...action,
                        ...(overrideActions[action.id] || {}),
                        ...(performedActions.indexOf(action.id) > -1 ? { performed: true } : {}),
                    };

                    const btn = (
                        <button
                            key="apply-link"
                            className={linkClasses}
                            onClick={() => !confirmText && handleClick(action)}
                            disabled={linkDisabled}
                        >
                            {linkText}
                        </button>
                    );

                    return (
                        <List.Item
                            key={id}
                            actions={[
                                linkText &&
                                    (confirmText ? (
                                        <Popconfirm
                                            title={<span dangerouslySetInnerHTML={{ __html: confirmText }} />}
                                            placement="bottomLeft"
                                            onConfirm={() => handleClick(action)}
                                            cancelText={__("Cancel")}
                                            okText={linkText}
                                            overlayStyle={{ maxWidth: 450 }}
                                            // zoom-in effect does not work correctly within a Card component
                                            transitionName={null}
                                        >
                                            {btn}
                                        </Popconfirm>
                                    ) : (
                                        btn
                                    )),
                                performed && (needsPro ? isPro : true) && (
                                    <span style={{ verticalAlign: "middle" }}>
                                        {<CheckOutlined />} {performedLabel || __("Already applied")}
                                    </span>
                                ),
                                needsPro &&
                                    !isPro &&
                                    (() => {
                                        // TODO: could this be done more generic? currently it's totally ok for this amount of cases
                                        let modal: JSX.Element;
                                        let tag: JSX.Element;
                                        switch (id) {
                                            case "visual-content-blocker":
                                                ({ modal, tag } = proModalVisualContentBlocker);
                                                break;
                                            case "mobile-experience":
                                                ({ modal, tag } = proModalMobileExperience);
                                                break;
                                            default:
                                                return null;
                                        }

                                        return (
                                            <>
                                                {modal}
                                                &nbsp;
                                                <span style={{ position: "absolute", top: 3 }}>{tag}</span>
                                            </>
                                        );
                                    })(),
                            ].filter(Boolean)}
                        >
                            <List.Item.Meta
                                title={title}
                                description={
                                    <>
                                        {previewImage ? (
                                            /* Antd does currently not support webm videos as image source so we create a dummy object which will
                                                    be only used as "click" handler to open the preview. */
                                            previewImage.endsWith(".webm") ? (
                                                <>
                                                    <video
                                                        autoPlay
                                                        muted
                                                        loop
                                                        src={previewImage}
                                                        style={{
                                                            marginLeft: 15,
                                                            width: 272,
                                                            height: "auto",
                                                            float: "right",
                                                            cursor: "pointer",
                                                        }}
                                                        onClick={(e) =>
                                                            (
                                                                (e.target as HTMLVideoElement)
                                                                    .nextElementSibling as HTMLDivElement
                                                            ).click()
                                                        }
                                                    >
                                                        <source src={previewImage} type="video/webm" />
                                                    </video>
                                                    <Image
                                                        width={272}
                                                        wrapperStyle={{ display: "none" }}
                                                        preview={{
                                                            imageRender: () => (
                                                                <video autoPlay muted loop src={previewImage}>
                                                                    <source src={previewImage} type="video/webm" />
                                                                </video>
                                                            ),
                                                        }}
                                                    />
                                                </>
                                            ) : (
                                                <Image
                                                    width={272}
                                                    src={previewImage}
                                                    wrapperStyle={{ marginLeft: 15, float: "right" }}
                                                />
                                            )
                                        ) : null}
                                        <p className="description" dangerouslySetInnerHTML={{ __html: description }} />
                                        {!!info && (
                                            <div
                                                className="notice notice-info below-h2 notice-alt"
                                                style={{ marginTop: 10 }}
                                            >
                                                <p className="description" dangerouslySetInnerHTML={{ __html: info }} />
                                            </div>
                                        )}
                                    </>
                                }
                            />
                        </List.Item>
                    );
                }}
            />
        </Spin>
    );
});

export { DashboardMigrationCardContent, type DashboardTileMigration };
