import { Col, Divider, Empty, Input, Modal, Popconfirm, Row, Skeleton, Table, Tag, Tooltip } from "antd";
import { useCallback, useMemo, useState } from "react";

import { jsxJoin } from "@devowl-wp/react-utils";

import { ListTcfNetworkSelector } from "./networkSelector.js";
import { useI18n } from "../../../contexts/i18n.js";
import { useListTcfVendor } from "../../../contexts/listTcfVendor.js";
import { useTableBulkAction } from "../../../hooks/useTableBulkAction.js";
import { ListMultilingualLanguages } from "../../common/listMultilingualLanguages.js";

import type { ListTcfVendorRowProps } from "../../../contexts/listTcfVendor.js";
import type { FC, Key } from "react";

const { Column } = Table;

type TableRow = ListTcfVendorRowProps<"vendor-configurations"> | ListTcfVendorRowProps<"vendors">;

const ListTcfVendor: FC = () => {
    const { __, _i } = useI18n();
    const store = useListTcfVendor();
    const { busy, vendorCount, view, rows } = store;
    const [filters, setFilters] = useState<{ vendor: string }>({ vendor: "" });
    const [selectedRowKeys, setSelectedRowKeys] = useState<Key[]>([]);
    const [doBulkAction, progress] = useTableBulkAction();
    const [isAdNetworksModalOpen, setIsAdNetworksModalOpen] = useState(() =>
        view === "vendors" ? !!store.defaultCreateAdNetworkIdentifier : false,
    );
    const adNetworksWithAllVendorIds = useMemo(
        () =>
            store.adNetworks.map((network) => ({
                network,
                vendorIds: network.lists.map(({ vendorIds }) => vendorIds).flat(),
            })),
        [store.adNetworks],
    );

    // We do currently not support asynchronous pagination, so we expect all vendor / vendor configurations
    // for the table. This also allows us to do filtering and sorting directly within this component.
    const useRows = useMemo(
        () =>
            [...rows]
                // We need to manually sort it again cause the `vendor-list.json#vendors` property uses numeric keys and
                // JavaScript does automatically sort it.
                .sort(({ vendor: vendorA }, { vendor: vendorB }) => {
                    if (!vendorA || !vendorB) {
                        // Abanonded vendors should always be on top
                        return -1;
                    }

                    const { name: x } = vendorA;
                    const { name: y } = vendorB;
                    return x < y ? -1 : x > y ? 1 : 0;
                })
                .filter(({ vendor }) => {
                    const { vendor: searchVendor } = filters;
                    if (vendor && searchVendor) {
                        const useTerm = searchVendor.toLowerCase();
                        return vendor.id.toString() === useTerm || vendor.name.toLowerCase().indexOf(useTerm) > -1;
                    }

                    // Always show abandoned vendors
                    return true;
                }),
        [rows, rows.length, filters],
    );

    const pickRowsByRowKeys = useCallback(
        (keys: Key[]) =>
            useRows.filter(
                ({ configuration, vendor }) =>
                    keys.indexOf(typeof configuration === "boolean" ? vendor.id : configuration.id) > -1 &&
                    configuration !== true,
            ),
        [useRows],
    );

    const addText = __("Create TCF vendor configuration");

    return progress ? (
        progress
    ) : vendorCount || view === "vendors" ? (
        <>
            <Row justify="end" gutter={10}>
                {view === "vendors" && (
                    <Col>
                        <Modal
                            open={isAdNetworksModalOpen}
                            title={__("Add vendors from ad networks")}
                            onCancel={() => setIsAdNetworksModalOpen(false)}
                            footer={null}
                            width={800}
                        >
                            <ListTcfNetworkSelector
                                onCreate={async ({ list: { vendorIds } }) => {
                                    setIsAdNetworksModalOpen(false);
                                    const picked = pickRowsByRowKeys(vendorIds).map(({ vendor }) => vendor);
                                    const [handleItemDone, signal, bulkDone] = doBulkAction({
                                        title: __("Creating vendors..."),
                                        total: picked.length,
                                    });

                                    await store.onBulkCreate(picked, handleItemDone, signal, bulkDone);
                                }}
                            />
                        </Modal>
                        <a
                            onClick={() => setIsAdNetworksModalOpen(true)}
                            className="button right"
                            style={{ marginBottom: 10 }}
                        >
                            {_i(__("Add vendors from ad networks (e.g. {{img/}} Google Adsense)"), {
                                img: (
                                    <img
                                        style={{ height: "1em" }}
                                        src="https://assets.devowl.io/in-app/wp-real-cookie-banner/logos/google-a-dsense.svg"
                                    />
                                ),
                            })}
                        </a>
                    </Col>
                )}
                <Col style={{ width: 400 }}>
                    <Input.Search
                        autoFocus
                        style={{ maxWidth: 400 }}
                        placeholder={__("Search vendor by name or ID...")}
                        onChange={(e) => setFilters((filters) => ({ ...filters, vendor: e.target.value }))}
                    />
                </Col>
                {view === "vendor-configurations" && (
                    <Col>
                        <a
                            onClick={store.onSwitchToVendorView}
                            className="button button-primary right"
                            style={{ marginBottom: 10 }}
                        >
                            {addText}
                        </a>
                    </Col>
                )}
            </Row>
            <div style={{ textAlign: "right", marginBottom: 15 }}></div>
            <Table<TableRow>
                pagination={{
                    pageSize: 50,
                    showTotal: (total, range) => `${range[0]}-${range[1]} / ${total}`,
                    showSizeChanger: false,
                }}
                locale={{ emptyText: <Empty description={__("No data")} /> }}
                loading={busy}
                dataSource={useRows}
                rowKey={({ vendor, configuration }) =>
                    typeof configuration === "boolean" ? vendor.id : configuration.id
                }
                size="small"
                bordered
                rowSelection={{
                    type: "checkbox",
                    getCheckboxProps: ({ configuration }) => {
                        return {
                            // Disable already created vendors
                            disabled: view === "vendors" && configuration === true,
                        };
                    },
                    selectedRowKeys,
                    onChange: (newSelectedRowKeys, _, { type }) => {
                        setSelectedRowKeys(
                            type === "all"
                                ? // Deselect all
                                  selectedRowKeys.length > 0
                                    ? []
                                    : useRows
                                          .map(({ configuration, vendor }) => {
                                              return typeof configuration === "boolean"
                                                  ? // Disable already created vendors
                                                    configuration
                                                      ? 0
                                                      : vendor.id
                                                  : configuration.id;
                                          })
                                          .filter(Boolean)
                                : newSelectedRowKeys,
                        );
                    },
                }}
            >
                <Column<TableRow>
                    title={jsxJoin(
                        [
                            ...(selectedRowKeys.length > 0
                                ? [
                                      <span key="bulk">{__("%d selected", selectedRowKeys.length)}</span>,
                                      view === "vendors" && (
                                          <Popconfirm
                                              key="bulk-create"
                                              title={
                                                  <>
                                                      {__(
                                                          "Please note that selecting more vendors than you actually use may lead to ineffective consent. Therefore, only activate the vendors that you actually actively work with!",
                                                      )}
                                                      <br />
                                                      <br />
                                                      {__(
                                                          "After activating the TCF vendors, I will check the information for each activated TCF vendor in the TCF vendor configuration myself and correct any information that does not match my use case.",
                                                      )}
                                                  </>
                                              }
                                              overlayInnerStyle={{ maxWidth: 300 }}
                                              placement="bottomLeft"
                                              onConfirm={() => {
                                                  const [handleItemDone, signal, bulkDone] = doBulkAction({
                                                      title: __("Creating vendors..."),
                                                      total: selectedRowKeys.length,
                                                  });

                                                  store.onBulkCreate(
                                                      pickRowsByRowKeys(selectedRowKeys).map(({ vendor }) => vendor),
                                                      handleItemDone,
                                                      signal,
                                                      bulkDone,
                                                  );

                                                  setSelectedRowKeys([]);
                                              }}
                                              okText={__("Create")}
                                              cancelText={__("Cancel")}
                                          >
                                              <a>{__("Create all selected vendors")}</a>
                                          </Popconfirm>
                                      ),
                                      view === "vendor-configurations" && (
                                          <Popconfirm
                                              key="bulk-delete"
                                              title={__("Are you sure you want to delete this vendors?")}
                                              placement="bottomLeft"
                                              onConfirm={() => {
                                                  const [handleItemDone, signal, bulkDone] = doBulkAction({
                                                      title: __("Deleting vendors..."),
                                                      total: selectedRowKeys.length,
                                                  });

                                                  store.onBulkDelete(
                                                      pickRowsByRowKeys(selectedRowKeys).map(
                                                          ({ configuration }) => configuration as any,
                                                      ),
                                                      handleItemDone,
                                                      signal,
                                                      bulkDone,
                                                  );

                                                  setSelectedRowKeys([]);
                                              }}
                                              okText={__("Delete all")}
                                              cancelText={__("Cancel")}
                                          >
                                              <a>{__("Delete all")}</a>
                                          </Popconfirm>
                                      ),
                                  ]
                                : []),
                            <span key="title">{__("Vendor")}</span>,
                        ],
                        <Divider type="vertical" />,
                    )}
                    dataIndex="vendor"
                    key="vendor"
                    render={(value, _) => {
                        const { vendor, configuration } = _;
                        return (
                            <span>
                                {vendor ? (
                                    <>
                                        {vendor.name} <span style={{ opacity: 0.5 }}>#{vendor.id}</span>{" "}
                                    </>
                                ) : (
                                    typeof configuration !== "boolean" && (
                                        <Tooltip
                                            title={__(
                                                "This vendor is no longer available and/or has been removed from the list of available vendors by the GVL. For this vendor, you can no longer request a consent from your visitors.",
                                            )}
                                        >
                                            <span style={{ opacity: 0.5 }}>#{configuration.vendorId}</span>{" "}
                                            <Tag color="error">{__("Abandoned")}</Tag>
                                        </Tooltip>
                                    )
                                )}
                                {view === "vendors" && configuration === true && (
                                    <>
                                        <Tag>{__("Already created")}</Tag>
                                        {_.blocker !== false && <Tag>{__("Content Blocker")}</Tag>}
                                    </>
                                )}
                            </span>
                        );
                    }}
                />
                <Column<TableRow>
                    title={__("Used in ad networks")}
                    dataIndex="adNetworks"
                    key="adNetworks"
                    render={(value, { vendor }) => {
                        if (!vendor) {
                            return null;
                        }

                        const { id } = vendor;
                        const networks = adNetworksWithAllVendorIds
                            .map(({ network, vendorIds }) => (vendorIds.indexOf(id) > -1 ? network : undefined))
                            .filter(Boolean);

                        return networks.map(({ name, logo }) => (
                            <span key={name} style={{ paddingRight: 10 }}>
                                <img src={logo} style={{ height: "1em" }} /> {name}
                            </span>
                        ));
                    }}
                />
                <Column<TableRow>
                    title={__("Privacy policy")}
                    dataIndex="privacyPolicy"
                    key="privacyPolicy"
                    render={(value, { vendor }) => {
                        if (!vendor?.urls) {
                            return null;
                        }

                        const {
                            urls: [{ privacy }],
                        } = vendor;

                        return (
                            privacy && (
                                <a href={privacy} target="_blank" rel="noreferrer">
                                    {new URL(privacy).origin}
                                </a>
                            )
                        );
                    }}
                />
                <Column<TableRow>
                    title={__("Actions")}
                    dataIndex="actions"
                    key="actions"
                    render={(value, record) => {
                        const { configuration, vendor } = record;

                        return jsxJoin(
                            [
                                view === "vendor-configurations" &&
                                    typeof configuration !== "boolean" &&
                                    record.languages && (
                                        <ListMultilingualLanguages
                                            key="multilingual"
                                            recordId={record.configuration.id}
                                            languages={record.languages}
                                            onClick={record.languageOnClick}
                                            wrapperProps={{ wrapperClassName: "alignleft" }}
                                        />
                                    ),
                                view === "vendors" && configuration !== true && (
                                    <a key="create" onClick={() => store.onCreate(vendor)}>
                                        {__("Create")}
                                    </a>
                                ),
                                view === "vendor-configurations" && typeof configuration !== "boolean" && vendor && (
                                    <a
                                        key="contentBlocker"
                                        onClick={() => store.onCreateOrEditContentBlocker(configuration, vendor)}
                                    >
                                        {configuration.blocker
                                            ? __("Edit Content Blocker")
                                            : __("Create Content Blocker")}
                                    </a>
                                ),
                                view === "vendor-configurations" && typeof configuration !== "boolean" && vendor && (
                                    <a key="edit" onClick={() => store.onEdit(configuration, vendor)}>
                                        {__("Edit")}
                                    </a>
                                ),
                                view === "vendor-configurations" && typeof configuration !== "boolean" && (
                                    <Popconfirm
                                        key="delete"
                                        title={__("Are you sure you want to delete this vendor?")}
                                        placement="bottomRight"
                                        onConfirm={() => store.onDelete(configuration)}
                                        okText={__("Delete")}
                                        cancelText={__("Cancel")}
                                        overlayStyle={{ maxWidth: 350 }}
                                    >
                                        <a>{__("Delete")}</a>
                                    </Popconfirm>
                                ),
                            ],
                            <Divider type="vertical" />,
                        );
                    }}
                />
            </Table>
        </>
    ) : busy ? (
        <Skeleton loading={true} active paragraph={{ rows: 1 }} />
    ) : (
        <Empty description={__("You have not yet created a TCF vendor configuration.")}>
            <a className="button button-primary" onClick={store.onSwitchToVendorView}>
                {addText}
            </a>
        </Empty>
    );
};

export { ListTcfVendor };
