import { MinusSquareOutlined, PlusSquareOutlined, QuestionCircleOutlined } from "@ant-design/icons";
import { App, Divider, Empty, Popconfirm, Select, Table, Tag, Tooltip } from "antd";
import { observer } from "mobx-react";
import { useCallback, useEffect, useState } from "react";

import { Notices, useTableColumnFilterSimpleInput } from "@devowl-wp/react-cookie-banner-admin";
import { jsxJoin } from "@devowl-wp/react-utils";
import { fetchStatus, useProgress } from "@devowl-wp/real-queue";

import { ConsentRecordBanner } from "./banner.js";
import { ConsentTableRecordExpand } from "./expand.js";
import { useAvailableDateRangesForFilter } from "../../../../hooks/useAvailableDateRangesForFilter.js";
import { useConfigHintText } from "../../../../hooks/useConfigHintText.js";
import { useStores } from "../../../../store/stores.js";
import { DATABASE_CONSENT_MIGRATION_QUEUE_JOB } from "../../../../types/queue.js";
import { __, _i } from "../../../../utils/i18n.js";
import { DateRangePicker } from "../../../dateRangePicker.js";
import { calculatePercentForDatabaseConsentMigrationV2QueueJob } from "../dbConsentMigrationV2Badge.js";
import { ConsentRefererSelect } from "../refererSelect.js";

import type { Consent } from "../../../../models/consent.js";
import type { DatabaseConsentMigrationV2QueueJobData } from "../../../../types/queue.js";
import type { FC } from "react";

const { Column } = Table;

const ConsentTable: FC = observer(() => {
    const { message } = App.useApp();
    const {
        consentStore,
        optionStore: { contexts },
    } = useStores();
    const {
        busyConsent,
        pageCollection,
        perPage,
        count,
        truncatedIpsCount,
        filters: {
            page: currentPage,
            referer: currentReferer,
            context: currentContext,
            dates: currentDates,
            ip: currentIp,
        },
    } = consentStore;

    const [bannerRecord, setBannerRecord] = useState<Consent>();
    const [replayBannerRecord, setReplayBannerRecord] = useState(false);
    const [migrationNeeded, setMigrationNeeded] = useState(false);
    const [bannerVisible, setBannerVisible] = useState(true);
    const contextKeys = Object.keys(contexts);

    const {
        percent: percentMigration,
        currentJob: currentJobMigration,
        remaining: remainingMigration,
        errors: errorMigration,
    } = useProgress<
        DatabaseConsentMigrationV2QueueJobData,
        { [DATABASE_CONSENT_MIGRATION_QUEUE_JOB]: { migrationNeeded: boolean } }
    >({
        type: DATABASE_CONSENT_MIGRATION_QUEUE_JOB,
        fetchAdditionalData: DATABASE_CONSENT_MIGRATION_QUEUE_JOB,
        onAdditionalData: ({ [DATABASE_CONSENT_MIGRATION_QUEUE_JOB]: data }) => {
            if (data.migrationNeeded !== migrationNeeded) {
                setMigrationNeeded(data.migrationNeeded);
            }
        },
    });

    // Provide predefined ranges to the user
    const availableRanges = useAvailableDateRangesForFilter();

    const fetchAll = useCallback(async () => {
        try {
            await consentStore.fetchAll();
        } catch (e) {
            message.error(e.responseJSON.message);
        }
    }, []);

    // Initially fetch first page
    useEffect(() => {
        fetchAll();
        fetchStatus(true);
    }, []);

    const hintText = useConfigHintText("list-of-consents");
    const hintTextDeleted = useConfigHintText("consents-deleted");

    const getColumnSearchProps = useTableColumnFilterSimpleInput();

    return (
        <>
            {bannerRecord && (
                <ConsentRecordBanner
                    record={bannerRecord}
                    visible={bannerVisible}
                    replayBannerRecord={replayBannerRecord}
                    onClose={() => {
                        setBannerVisible(false);
                        setReplayBannerRecord(false);
                        setBannerRecord(undefined);
                    }}
                />
            )}
            <div style={{ textAlign: "right", marginBottom: 15 }}>
                {contextKeys.length > 1 && (
                    <>
                        <label>
                            <Select
                                style={{ width: 200, textAlign: "left" }}
                                value={currentContext}
                                onSelect={(value) => {
                                    consentStore.applyPage(1);
                                    consentStore.applyContext(value);
                                    fetchAll();
                                }}
                            >
                                {contextKeys.map((context) => (
                                    <Select.Option value={context} key={context}>
                                        {contexts[context]}
                                    </Select.Option>
                                ))}
                            </Select>
                        </label>
                        <Divider type="vertical" />
                    </>
                )}
                <label>
                    {__("Period")}:{" "}
                    <DateRangePicker
                        value={
                            /* Ant design relies on moment 2.27 and typings are currently incompatible with other moment typings */ currentDates as any
                        }
                        ranges={availableRanges as any}
                        onChange={(dates) => {
                            consentStore.applyPage(1);
                            consentStore.applyDates(dates || [undefined, undefined]);
                            fetchAll();
                        }}
                    />
                </label>
                <Divider type="vertical" />
                <label style={{ textAlign: "left" }}>
                    <ConsentRefererSelect
                        value={currentReferer}
                        onChange={(referer) => {
                            consentStore.applyPage(1);
                            consentStore.applyReferer(referer);
                            fetchAll();
                        }}
                    />
                </label>
            </div>
            <Notices
                notices={[
                    truncatedIpsCount > 0 &&
                        !!currentIp && {
                            message: __(
                                "For data protection reasons, IP addresses, depending on the configuration of the cookie banner, were only shortened by the last octet and stored hashed. In this case, you can only assign consents to individual IP addresses with a high probability, but not with absolute certainty. Therefore, also match the time of consent to narrow down your search for the proper consent!",
                            ),
                            severity: "warning",
                        },
                    remainingMigration > 0 && percentMigration > 0 && currentJobMigration
                        ? {
                              message: __(
                                  "Real Cookie Banner v5.0 introduces an optimized database schema that allows consent documents to be stored in less storage space. Previously stored consent data is currently being automatically migrated in the background (%s %%). Please have a little patience!",
                                  calculatePercentForDatabaseConsentMigrationV2QueueJob(currentJobMigration.data),
                              ),
                              severity: "info",
                          }
                        : migrationNeeded && !errorMigration
                          ? {
                                message: _i(
                                    __(
                                        "Real Cookie Banner v5.0 introduces an optimized database schema that allows consent documents to be stored in less storage space. There are still consents left to migrate. {{a}}Click here to start the migration.{{/a}}",
                                    ),
                                    {
                                        a: (
                                            <a
                                                onClick={() => {
                                                    setMigrationNeeded(false);
                                                    consentStore
                                                        .fetchAll({
                                                            migration: DATABASE_CONSENT_MIGRATION_QUEUE_JOB,
                                                        })
                                                        .then(() => fetchStatus(true));
                                                }}
                                            >
                                                {__("Start migration")}
                                            </a>
                                        ),
                                    },
                                ),
                                severity: "info",
                            }
                          : undefined,
                ]}
            />
            <Table<Consent>
                pagination={{
                    current: currentPage,
                    pageSize: perPage,
                    total: count,
                    showTotal: (total, range) => `${range[0]}-${range[1]} / ${total}`,
                    showSizeChanger: false,
                }}
                style={{ marginTop: 5 }}
                locale={{ emptyText: <Empty description={__("No data")} /> }}
                loading={busyConsent}
                dataSource={Array.from(pageCollection.values())}
                rowKey="id"
                size="small"
                bordered
                expandable={{
                    expandedRowRender: (record) => (
                        <div style={{ background: "white", padding: 10 }}>
                            <ConsentTableRecordExpand
                                record={record}
                                onPreview={(r, replay) => {
                                    setBannerRecord(r);
                                    setReplayBannerRecord(replay);
                                    setBannerVisible(true);
                                }}
                            />
                        </div>
                    ),
                    rowExpandable: () => true,
                    expandIcon: ({ expanded, onExpand, record }) => (
                        <Tag
                            style={{ cursor: "pointer" }}
                            onClick={(e) => onExpand(record, e)}
                            icon={expanded ? <MinusSquareOutlined /> : <PlusSquareOutlined />}
                        >
                            {expanded ? __("Less") : __("More")}
                        </Tag>
                    ),
                }}
                onChange={({ current }, filters) => {
                    const uuid = (filters.uuid?.[0] as string) || "";
                    const ip = (filters.ip?.[0] as string) || "";
                    consentStore.applyPage(current);
                    consentStore.applyUuid(uuid);
                    consentStore.applyIp(ip);
                    fetchAll();
                }}
                footer={() => (
                    <Popconfirm
                        overlayStyle={{ maxWidth: 300 }}
                        arrow={{ pointAtCenter: true }}
                        title={_i(
                            __(
                                "Are you sure you want to delete all consents? You should only do this if it is absolutely necessary. In case you want to continue, make sure you have {{a}}exported{{/a}} all consents beforehand (for legal reasons).",
                            ),
                            {
                                a: <a href="#/import" />,
                            },
                        )}
                        okText={__("I am sure!")}
                        cancelText={__("Cancel")}
                        placement="topRight"
                        onConfirm={() =>
                            window.confirm(__("Just to be sure: Do you really want to delete all consents?")) &&
                            consentStore.deleteAll()
                        }
                    >
                        <button className="button-link">{__("Delete all consents")}</button>
                    </Popconfirm>
                )}
            >
                <Column<Consent>
                    title={__("Time of consent documentation")}
                    dataIndex="created"
                    key="created"
                    render={(value, record) => {
                        const { created } = record;

                        return (
                            <>
                                {new Date(created).toLocaleString(document.documentElement.lang)}{" "}
                                {record.dnt && (
                                    <Tooltip
                                        title={__(
                                            "This consent was given automatically because the browser sent a 'Do Not Track' header. Accordingly, only essential services have been consented to.",
                                        )}
                                    >
                                        <Tag color="magenta">{__("Do Not Track")}</Tag>
                                    </Tooltip>
                                )}
                                {record.blocker > 0 && (
                                    <Tooltip title={__("This consent has been given in a content blocker.")}>
                                        <Tag color="cyan">{__("Content Blocker")}</Tag>
                                    </Tooltip>
                                )}
                                {record.forwarded > 0 && (
                                    <Tooltip title={__("This consent was implicitly given by Consent Forwarding.")}>
                                        <Tag color="green">
                                            {record.forwarded_blocker
                                                ? __("Forwarded through Content Blocker")
                                                : __("Forwarded")}
                                        </Tag>
                                    </Tooltip>
                                )}
                                {record.custom_bypass && (
                                    <Tooltip title={__("This consent was implicitly given by a configured bypass.")}>
                                        <Tag color="magenta">{record.custom_bypass_readable}</Tag>
                                    </Tooltip>
                                )}
                            </>
                        );
                    }}
                />
                <Column<Consent>
                    title={
                        <Tooltip title={__("Unique name of the consent given")}>
                            <span>
                                {__("UUID")} <QuestionCircleOutlined style={{ color: "#9a9a9a" }} />
                            </span>
                        </Tooltip>
                    }
                    dataIndex="uuid"
                    key="uuid"
                    render={(value, record) => <code>{record.uuid}</code>}
                    {...(getColumnSearchProps() as any)}
                />
                <Column<Consent>
                    title={
                        <Tooltip
                            title={__(
                                "If you have allowed to log IP addresses, you can view them here. Otherwise you will see a salted hash of the IP address (truncated).",
                            )}
                        >
                            <span>
                                {__("IP")} <QuestionCircleOutlined style={{ color: "#9a9a9a" }} />
                            </span>
                        </Tooltip>
                    }
                    dataIndex="ip"
                    key="ip"
                    render={(value, record) =>
                        record.ipv4 ? (
                            <>
                                <code>{record.ipv4}</code>
                                {!!currentIp && record.ipv4 === currentIp && (
                                    <Tag style={{ marginLeft: 5 }} color="blue">
                                        {__("Exact match")}
                                    </Tag>
                                )}
                            </>
                        ) : record.ipv6 ? (
                            <>
                                <code>{record.ipv6}</code>
                                {!!currentIp && record.ipv6 === currentIp && (
                                    <Tag style={{ marginLeft: 5 }} color="blue">
                                        {__("Exact match")}
                                    </Tag>
                                )}
                            </>
                        ) : record.ipv4_hash ? (
                            <Tooltip title={record.ipv4_hash}>
                                <code>{record.ipv4_hash.slice(0, 8)}</code>
                            </Tooltip>
                        ) : (
                            <Tooltip title={record.ipv6_hash}>
                                <code>{record.ipv6_hash.slice(0, 8)}</code>
                            </Tooltip>
                        )
                    }
                    {...(getColumnSearchProps() as any)}
                />
                <Column<Consent>
                    title={__("Accepted services")}
                    dataIndex="decision"
                    key="decision"
                    render={(value, record) => record.decision_labels.map((label) => <Tag key={label}>{label}</Tag>)}
                />
                <Column<Consent>
                    title={__("Actions")}
                    dataIndex="actions"
                    key="actions"
                    render={(value, record) => {
                        return jsxJoin(
                            [
                                <Popconfirm
                                    key="delete"
                                    title={__("Are you sure you want to delete this entry?")}
                                    placement="bottomLeft"
                                    onConfirm={() => record.delete()}
                                    okText={__("Delete")}
                                    cancelText={__("Cancel")}
                                    overlayStyle={{ maxWidth: 350 }}
                                >
                                    <a>{__("Delete")}</a>
                                </Popconfirm>,
                            ],
                            <Divider type="vertical" />,
                        );
                    }}
                />
            </Table>
            <p className="description" style={{ maxWidth: 800, margin: "30px auto 0", textAlign: "center" }}>
                {hintText}
            </p>
            <p className="description" style={{ maxWidth: 800, margin: "30px auto 0", textAlign: "center" }}>
                {hintTextDeleted}
            </p>
        </>
    );
});

export { ConsentTable };
