import ThingsFilter from '@/components/shared/ThingFilterModal';
import { DEFAULT_PAGE_SIZE } from '@/constants';
import {
  apiDeleteUserThingPolicy,
  apiGetThingPolicyByUser,
  apiShareThingToUser,
} from '@/services/master/ThingController';
import { DeleteOutlined, ShareAltOutlined } from '@ant-design/icons';
import {
  ActionType,
  FooterToolbar,
  ProList,
  ProListMetas,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import {
  Button,
  Checkbox,
  GetProp,
  message,
  Popconfirm,
  Tag,
  Typography,
} from 'antd';
import { useRef, useState } from 'react';
const { Paragraph } = Typography;

type PolicyShareDefault = {
  read: boolean;
  write: boolean;
  delete: boolean;
};

type ShareThingProps = {
  user: MasterModel.UserResponse | null;
};
const ShareThing = ({ user }: ShareThingProps) => {
  const listActionRef = useRef<ActionType>();
  const intl = useIntl();
  const [messageApi, contextHolder] = message.useMessage();
  const [selectedRowsState, setSelectedRows] = useState<
    MasterModel.ThingPolicy[]
  >([]);
  const [thingPolicy, setThingPolicy] = useState<MasterModel.ThingPolicy[]>([]);
  const [shareThingModalVisible, setShareThingModalVisible] =
    useState<boolean>(false);
  const [policyShare, setPolicyShare] = useState<PolicyShareDefault>({
    read: true,
    write: true,
    delete: true,
  });
  const getPolicyInfo = (
    policy: MasterModel.Policy,
  ): { color: string; text: string } => {
    switch (policy) {
      case 'read':
        return {
          color: 'blue',
          text: intl.formatMessage({
            id: 'master.users.things.relation.read',
            defaultMessage: 'Read',
          }),
        };
      case 'write':
        return {
          color: 'gold',
          text: intl.formatMessage({
            id: 'master.users.things.relation.write',
            defaultMessage: 'Write',
          }),
        };
      case 'delete':
        return {
          color: 'red',
          text: intl.formatMessage({
            id: 'master.users.things.relation.delete',
            defaultMessage: 'Delete',
          }),
        };
      default:
        return { color: 'default', text: policy };
    }
  };

  const columns: ProListMetas<MasterModel.ThingPolicy> = {
    title: {
      dataIndex: 'name',
      render: (_, record: MasterModel.ThingPolicy) => (
        <Paragraph copyable>{record?.thing_name}</Paragraph>
      ),
    },
    subTitle: {
      dataIndex: 'metadata.external_id',
      render: (_, record: MasterModel.ThingPolicy) => (
        <Paragraph copyable>{record?.external_id}</Paragraph>
      ),
    },
    description: {
      dataIndex: 'policies',
      render: (_, record: MasterModel.ThingPolicy) => {
        return record?.policies?.map((policy) => {
          const info = getPolicyInfo(policy);
          return (
            <Tag key={policy} color={info.color}>
              {info.text}
            </Tag>
          );
        });
      },
    },
  };

  const handleShareThings = async (thingIds: string[]) => {
    const thingsFiltered = thingIds.filter((thingId) => {
      return !thingPolicy.find((thing) => thing.thing_id === thingId);
    });
    if (thingsFiltered.length === 0) return;
    const key = 'share';
    try {
      messageApi.open({
        type: 'loading',
        content: intl.formatMessage({
          id: 'master.users.things.sharing',
          defaultMessage: 'Sharing devices...',
        }),
        key,
      });
      const allShare = thingsFiltered.map(async (thingId) => {
        const resp = await apiShareThingToUser(
          thingId,
          user?.id || '',
          Object.keys(policyShare).filter(
            (key) => policyShare[key as keyof PolicyShareDefault],
          ),
        );
      });

      await Promise.all(allShare);

      messageApi.open({
        type: 'success',
        content: intl.formatMessage({
          id: 'master.users.thing.share.success',
          defaultMessage: 'Share successfully and will refresh soon',
        }),
        key,
      });

      await new Promise((resolve) => {
        setTimeout(resolve, 500);
      });

      if (listActionRef.current) {
        listActionRef.current.reload();
      }
    } catch (error) {
      console.error('Error when share thing: ', error);
      messageApi.open({
        type: 'error',
        content: intl.formatMessage({
          id: 'master.users.thing.share.fail',
          defaultMessage: 'Share failed, please try again!',
        }),
        key,
      });
    }
  };

  const onChange: GetProp<typeof Checkbox.Group, 'onChange'> = (
    checkedValues,
  ) => {
    setPolicyShare({
      read: checkedValues.includes('read'),
      write: checkedValues.includes('write'),
      delete: checkedValues.includes('delete'),
    });
  };
  const handleUnshare = async (selectedRows: MasterModel.ThingPolicy[]) => {
    if (!selectedRows) return true;
    const key = 'unshare';
    try {
      messageApi.open({
        type: 'loading',
        content: intl.formatMessage({
          id: 'master.users.things.unsharing',
          defaultMessage: 'Unsharing devices...',
        }),
        key,
      });

      const allUnshare = selectedRows.map(async (row) => {
        const resp = await apiDeleteUserThingPolicy(
          row?.thing_id || '',
          user?.id || '',
        );
      });

      await Promise.all(allUnshare);

      messageApi.open({
        type: 'success',
        content: intl.formatMessage({
          id: 'master.users.thing.unshare.success',
          defaultMessage: 'Unshare successfully and will refresh soon',
        }),
        key,
      });

      await new Promise((resolve) => {
        setTimeout(resolve, 500);
      });

      return true;
    } catch (error) {
      console.error('Error when unshare thing: ', error);
      messageApi.open({
        type: 'error',
        content: intl.formatMessage({
          id: 'master.users.thing.unshare.fail',
          defaultMessage: 'Unshare failed, please try again!',
        }),
        key,
      });
      return false;
    }
  };
  return (
    <>
      {contextHolder}
      <ThingsFilter
        isOpen={shareThingModalVisible}
        setIsOpen={setShareThingModalVisible}
        thingIds={thingPolicy.map((thing) => thing.thing_id!)}
        disabled
        extra={
          <Checkbox.Group
            options={[
              {
                label: intl.formatMessage({
                  id: 'master.users.things.relation.read',
                  defaultMessage: 'Read',
                }),
                value: 'read',
                disabled: true,
              },
              {
                label: intl.formatMessage({
                  id: 'master.users.things.relation.write',
                  defaultMessage: 'Write',
                }),
                value: 'write',
              },
              {
                label: intl.formatMessage({
                  id: 'master.users.things.relation.delete',
                  defaultMessage: 'Delete',
                }),
                value: 'delete',
              },
            ]}
            value={Object.keys(policyShare).filter(
              (key) => policyShare[key as keyof PolicyShareDefault],
            )}
            onChange={onChange}
          />
        }
        onSubmit={handleShareThings}
      />
      <ProList<MasterModel.ThingPolicy>
        headerTitle={intl.formatMessage({
          id: 'master.users.things.list',
          defaultMessage: 'List things',
        })}
        actionRef={listActionRef}
        toolBarRender={() => [
          <Button
            type="primary"
            key="primary"
            icon={<ShareAltOutlined />}
            onClick={() => {
              setShareThingModalVisible(true);
            }}
          >
            <FormattedMessage
              id="master.users.thing.share.title"
              defaultMessage="Share"
            />
          </Button>,
        ]}
        pagination={{
          pageSize: DEFAULT_PAGE_SIZE,
        }}
        metas={columns}
        request={async (params) => {
          const { current, pageSize } = params;
          const query = {
            type: 'sub',
            id: user?.id || '',
          };
          if (user?.id) {
            const offset = current === 1 ? 0 : (current! - 1) * pageSize!;
            const policyBody: Partial<MasterModel.SearchPaginationBody> = {
              offset: offset,
              limit: pageSize,
            };
            const resp = await apiGetThingPolicyByUser(policyBody, user.id);

            if (resp.things) {
              setThingPolicy(resp.things);
              return Promise.resolve({
                success: true,
                data: resp.things,
                total: resp.total,
              });
            } else {
              return {
                success: false,
                data: [],
                total: 0,
              };
            }
          }
          return Promise.resolve({
            success: false,
            data: [],
            total: 0,
          });
        }}
        rowKey="external_id"
        search={false}
        rowSelection={{
          selectedRowKeys: selectedRowsState
            .map((row) => row.external_id)
            .filter((id): id is string => id !== undefined),
          onChange: (_, selectedRows: MasterModel.ThingPolicy[]) => {
            setSelectedRows(selectedRows);
          },
        }}
      />
      {selectedRowsState?.length > 0 && (
        <FooterToolbar
          extra={
            <div>
              <FormattedMessage
                id="master.footer.chosen"
                defaultMessage="Chosen"
              />{' '}
              <a
                style={{
                  fontWeight: 600,
                }}
              >
                {selectedRowsState.length}
              </a>{' '}
              <FormattedMessage
                id="common.paginations.things"
                defaultMessage="item"
              />
            </div>
          }
        >
          <Popconfirm
            title={intl.formatMessage({
              id: 'master.users.thing.unshare.confirm',
              defaultMessage: 'Are you sure to stop sharing these devices?',
            })}
            okText={intl.formatMessage({
              id: 'common.sure',
              defaultMessage: 'Sure',
            })}
            onConfirm={async () => {
              const success = await handleUnshare(selectedRowsState);
              if (success) {
                setSelectedRows([]);
                if (listActionRef.current) {
                  listActionRef.current.reload();
                }
              }
            }}
          >
            <Button type="primary" danger icon={<DeleteOutlined />}>
              <FormattedMessage
                id="master.users.thing.unshare.title"
                defaultMessage="Sure"
              />
            </Button>
          </Popconfirm>
        </FooterToolbar>
      )}
    </>
  );
};

export default ShareThing;
