import { t } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import {
  Button,
  Card,
  Col,
  Modal,
  notification,
  Row,
  Spin,
  Tooltip,
  Tree,
} from 'antd';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { ImageAnnotator } from '../../components/annotator';
import {
  AnnotatorProvider,
  useStoreInstance,
} from '../../components/annotator/store-context';
import {
  extractShapesFromTemplateData,
  shapesToStringData,
  shapesToTemplateData,
} from '../../utils/shape-convert';
import {
  isTemplateChanged,
  validateTemplate,
} from '../../utils/template-validation';

import { testingUser } from '../../constants/variable';
import { ApiCode } from '../../models';
import {
  useDeleteTemplate,
  useTemplates,
  useUpdateTemplate,
  useUser,
} from '../../queries';

import {
  DeleteOutlined,
  PlusOutlined,
  SaveOutlined,
  UndoOutlined,
} from '@ant-design/icons';
import { useQueryClient } from '@tanstack/react-query';
import { cloneDeep } from 'lodash-es';
import styled from 'styled-components';
import { AnchorsPosition } from './anchors-position';
import { ExtractedFields } from './extracted-fields';
const { DirectoryTree } = Tree;

const ConfigTemplatePage = () => {
  const { i18n } = useLingui();
  const navigate = useNavigate();
  const storeInstance = useStoreInstance();
  const userQuery = useUser();
  const queryClient = useQueryClient();

  const [selectedTemplate, setSelectedTemplate] = useState(null);

  const deleteTemplateMutation = useDeleteTemplate({
    onSuccess() {
      getListTemplatesQuery.refetch();
      setSelectedTemplate(null);
      storeInstance.setBackground('');
      storeInstance.setShapes([]);
      queryClient.invalidateQueries({
        queryKey: ['list-templates', userQuery.data?.userId],
      });
    },
  });

  const updateTemplateMutation = useUpdateTemplate({
    onSuccess(data) {
      getListTemplatesQuery.refetch();
      const templateData = shapesToTemplateData(
        storeInstance.getStore().shapes,
      );
      setSelectedTemplate({
        ...selectedTemplate,
        shapes: cloneDeep(templateData),
      });
    },
  });

  const getListTemplatesQuery = useTemplates(userQuery.data?.userId, {
    enabled: userQuery.isSuccess,
  });

  const templateTree = useTemplateTree(getListTemplatesQuery.data);

  const onSelect = (_, info) => {
    if (info.node.isLeaf) {
      if (
        !!selectedTemplate &&
        selectedTemplate.id !== info.node.id &&
        isTemplateChanged(selectedTemplate, {
          ...selectedTemplate,
          shapes: shapesToTemplateData(storeInstance.getStore().shapes),
        })
      ) {
        Modal.confirm({
          title: t(i18n)`Confirm`,
          content: t`Are you sure want to change template without saving?`,
          onOk() {
            setSelectedTemplate(info.node);
            storeInstance.setShapes(cloneDeep(info.node.shapes));
          },
        });
      } else {
        if (!(!!selectedTemplate && selectedTemplate.id === info.node.id)) {
          setSelectedTemplate(info.node);
          storeInstance.setShapes(cloneDeep(info.node.shapes));
        }
      }
    }
  };

  const onCancel = () => {
    storeInstance.setShapes(cloneDeep(selectedTemplate.shapes));
  };

  const onSave = async () => {
    let templateValidation = validateTemplate(storeInstance.getStore().shapes);

    if (!templateValidation.status) {
      notification.warning({
        message: t(i18n)`Template Settings`,
        description: t(
          i18n,
        )`Update template error: ${templateValidation.message}`,
      });
      return;
    }

    try {
      const templateData = shapesToStringData(storeInstance.getStore().shapes);

      await updateTemplateMutation.mutateAsync({
        fileUrl: selectedTemplate.file_url,
        templateId: selectedTemplate.id,
        templateName: selectedTemplate.title,
        userId: userQuery.data?.userId,
        listNameBox: templateData.listNameBox,
        listBBox: templateData.listBBox,
        listAnchor: templateData.listAnchor,
      });
      notification.success({
        message: t(i18n)`Template Settings`,
        description: t(i18n)`Update template successfully.`,
      });
    } catch (error) {
      if (error.response?.data.code == ApiCode.DuplicateBox) {
        notification.warning({
          message: t(i18n)`Template Settings`,
          description: t(
            i18n,
          )`Update template error: Extracted fields must have unique labels.`,
        });
      } else {
        notification.error({
          message: t(i18n)`Template Settings`,
          description: t(i18n)`Update template error: ${error}`,
        });
      }
    }
  };

  return (
    <Row
      style={{
        height: '100%',
        width: '100%',
      }}
      gutter={[8, 8]}
      align="stretch"
    >
      <Col span={5} style={{ height: '100%' }}>
        <Card
          bordered
          title={t(i18n)`Templates Editor`}
          extra={
            <Tooltip
              title={
                getListTemplatesQuery.data?.length >= testingUser.maxTemplate
                  ? t(
                      i18n,
                    )`You are not allowed to create more than ${testingUser.maxTemplate} templates! Please contact us for further support.`
                  : null
              }
            >
              <Button
                type="primary"
                icon={<PlusOutlined />}
                onClick={() => navigate('/template/create')}
                disabled={
                  getListTemplatesQuery.data?.length >= testingUser.maxTemplate
                }
              >
                {t(i18n)`New`}
              </Button>
            </Tooltip>
          }
          style={{
            height: '100%',
            display: 'flex',
            flexDirection: 'column',
          }}
          headStyle={{
            padding: '0 16px',
          }}
          bodyStyle={{
            overflow: 'auto',
            display: 'flex',
            flexDirection: 'column',
            flex: 1,
            padding: 16,
          }}
          actions={
            selectedTemplate
              ? [
                  <Button icon={<UndoOutlined />} onClick={() => onCancel()}>{t(
                    i18n,
                  )`Cancel`}</Button>,
                  <Button
                    type="primary"
                    icon={<SaveOutlined />}
                    onClick={onSave}
                    loading={updateTemplateMutation.isLoading}
                  >{t(i18n)`Save`}</Button>,
                ]
              : []
          }
        >
          <Row
            style={{
              flexGrow: 1,
            }}
          >
            {getListTemplatesQuery.isFetching ? (
              <div style={{ padding: 5, textAlign: 'center' }}>
                <Spin />
              </div>
            ) : (
              <StyledDirectoryTree
                showLine
                showIcon={false}
                defaultExpandAll
                onSelect={onSelect}
                treeData={templateTree}
                selectedKeys={[selectedTemplate?.key]}
                rootStyle={{ width: '100%' }}
                titleRender={({ title, key }) => {
                  return (
                    <>
                      <span className="filename">{title}</span>
                      {key === selectedTemplate?.key && (
                        <DeleteOutlined
                          title={t(i18n)`Delete Template`}
                          style={{ marginLeft: 'auto', marginRight: 4 }}
                          onClick={(e) => {
                            e.stopPropagation();
                            Modal.confirm({
                              title: t(i18n)`Delete Template`,
                              content: t`Are you sure to delete template?`,
                              async onOk() {
                                try {
                                  await deleteTemplateMutation.mutateAsync({
                                    templateId: selectedTemplate.key,
                                  });
                                  notification.success({
                                    message: t(i18n)`Template Settings`,
                                    description: t(
                                      i18n,
                                    )`Delete template successfully.`,
                                  });
                                } catch (error) {
                                  notification.error({
                                    message: t(i18n)`Template Settings`,
                                    description: t(
                                      i18n,
                                    )`Delete template error: ${error}`,
                                  });
                                }
                              },
                            });
                          }}
                        />
                      )}
                    </>
                  );
                }}
              />
            )}
          </Row>
        </Card>
      </Col>
      <Col
        span={12}
        style={{ height: '100%', padding: 0 }}
        className="ant-card ant-card-bordered"
      >
        <ImageAnnotator background={selectedTemplate?.file_url} />
      </Col>
      <Col
        span={7}
        style={{ display: 'flex', flexDirection: 'column', gap: 8 }}
      >
        <AnchorsPosition />
        <ExtractedFields />
      </Col>
    </Row>
  );
};

function useTemplateTree(templates) {
  const { i18n } = useLingui();

  return [
    {
      title: t(i18n)`Saved Templates`,
      key: 'saved',
      children: !!templates
        ? templates.map((temp) => {
            return {
              title: temp.name,
              key: `${temp.id}`,
              isLeaf: true,
              shapes: extractShapesFromTemplateData(
                temp.data_boxs,
                temp.anchor_boxs,
              ),
              file_url: temp.file_url,
              id: temp.id,
            };
          })
        : [],
    },
  ];
}

export default function () {
  return (
    <AnnotatorProvider>
      <ConfigTemplatePage />
    </AnnotatorProvider>
  );
}

const StyledDirectoryTree: typeof DirectoryTree = styled(DirectoryTree)`
  &
    .ant-tree-treenode
    .ant-tree-node-content-wrapper.ant-tree-node-content-wrapper-normal {
    overflow: hidden;
  }

  & .ant-tree-treenode .ant-tree-indent {
    background: white;
  }

  & span.ant-tree-title {
    display: flex;

    .filename {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
`;
