import React, { FC, useCallback, useEffect, useState } from 'react';
import { onSelectAllRow, onSelectOnceRow } from '../DashboardTable';
import { showConfirmModal } from '../Modals/ConfirmModal/ConfirmModal';
import {
  TablePaginationConfig,
  Button,
  Form,
  Input,
  Popconfirm,
  Table,
  Typography,
} from 'antd';
import { DeleteFilled, PlusOutlined } from '@ant-design/icons';
import {
  EditableCellProps,
  Item,
  TypeDynamicTableProps,
} from 'pages/DevicesDashboard/DevicesCardInfo/types';
import { ColumnsType } from 'antd/es/table';
import { TypeDashboardPaginationState } from '../Dashboard/types';
import { TypeEndpointDynamicTablePath } from 'pages/DevicesDashboard';

const { Search } = Input;

export const DynamicTable: FC<TypeDynamicTableProps> = ({
  tableName,
  disabled,
  columns,
  originData,
  setOriginData,
  locales,
  localeValidation,
}) => {
  const [form] = Form.useForm();

  const [editingKey, setEditingKey] = useState<number | string>('');
  const [isAddingNewPath, setIsAddingNewPath] = useState<boolean>(false);
  const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
  const [filteredData, setFilteredData] =
    useState<TypeEndpointDynamicTablePath>(originData);
  const [searchValue, setSearchValue] = useState<string>('');
  const [isAllSelected, setIsAllSelected] = useState<boolean>(false);

  const isEditing = (record: Item): boolean => record.id === editingKey;

  useEffect((): void => {
    if (searchValue === '') {
      setFilteredData(originData);
    } else {
      setFilteredData(
        originData.filter((item) =>
          item.path.toLowerCase().includes(searchValue.toLowerCase()),
        ),
      );
    }
  }, [originData, searchValue]);

  const [dashboardState, setDashboardState] =
    useState<TypeDashboardPaginationState>({
      current: 1,
      pageSize: 10,
      total: originData.length,
    });

  const handleTableChange = ({
    current,
    pageSize,
  }: TablePaginationConfig): void => {
    setDashboardState((prevState) => {
      if (current && pageSize) {
        return {
          ...prevState,
          current: current,
          pageSize: pageSize,
        };
      }
      return prevState;
    });
  };

  const rowSelection = {
    // Выбранные элементы
    selectedRowKeys,

    // Выбор элемента по одному
    onSelect: (record: Item, selected: boolean, selectedRows: Item[]) => {
      if (!disabled) {
        onSelectOnceRow(selected, selectedRows, record, setSelectedRowKeys);
      }
    },

    // Выбор всех элементов
    onSelectAll: (
      selected: boolean,
      selectedRows: Item[],
      changeRows: Item[],
    ) => {
      if (!disabled) {
        if (selected) {
          setIsAllSelected(true);
        } else {
          setIsAllSelected(false);
        }
        onSelectAllRow(selected, selectedRows, changeRows, {
          selectedRowKeys: selectedRowKeys,
          onSetSelectedRowItem: setSelectedRowKeys,
        });
      }
    },
  };

  // Редактирование пути
  const edit = (record: Partial<Item> & { id: React.Key }): void => {
    form.setFieldsValue({ ...record });
    setEditingKey(record.id);
  };

  // отмена
  const cancel = (): void => {
    setEditingKey('');
  };

  const handleAdd = useCallback(async (): Promise<void> => {
    setIsAddingNewPath(true);
    if (originData.length === 10) {
      setDashboardState((prevState) => ({
        ...prevState,
        current: prevState.current + 1,
      }));
    }
    const newData = {
      id: Math.floor(Math.random() * 1000000),
      path: 'path',
    };
    setSearchValue('');
    setEditingKey(newData.id);
    setOriginData([...originData, newData]);
    form.setFieldsValue({ path: 'C:\\\\' });
  }, [form, originData, setOriginData]);

  const save = async (key: React.Key): Promise<void> => {
    try {
      const row = await form.validateFields();
      const newData = [...originData];
      const index = newData.findIndex((item) => key === item.id);
      if (index > -1) {
        const item = newData[index];
        newData.splice(index, 1, {
          ...item,
          ...row,
        });
        setOriginData(newData);
        setEditingKey('');
      } else {
        newData.push(row);
        setOriginData(newData);
        setEditingKey('');
      }
    } catch (errInfo) {
      console.error('Validate Failed:', errInfo);
    }
  };

  const handleDelete = (key: React.Key): void => {
    const newData = originData.filter((item) => item.id !== key);
    setOriginData(newData);
    setEditingKey('');
  };

  const handleDeleteSelectedRows = (): void => {
    let newData = originData;
    for (let i = 0; i < selectedRowKeys.length; i++) {
      newData = newData.filter((item) => item.id !== selectedRowKeys[i]);
    }
    setOriginData(newData);
    setSelectedRowKeys([]);
  };

  const deleteSelectedItems = (): void => {
    showConfirmModal({
      title: locales.deleteMasQuestions,
      okType: 'danger',
      action: () => handleDeleteSelectedRows(),
      okText: locales.ok,
      cancelText: locales.cancel,
    });
  };
  const handleSelectAllItems = (): void => {
    if (originData.length > selectedRowKeys.length) {
      setSelectedRowKeys(originData.map((item) => item.id));
      setIsAllSelected(true);
    }

    if (
      selectedRowKeys.length !== 0 &&
      originData.length === selectedRowKeys.length
    ) {
      setIsAllSelected(false);
      setSelectedRowKeys([]);
    }
  };
  const onSearch = (value: string): void => {
    setSearchValue(value);
    if (value === '') {
      setFilteredData(originData);
    } else {
      setFilteredData(
        originData.filter((item) =>
          item.path.toLowerCase().includes(value.toLowerCase()),
        ),
      );
    }
  };

  const mergedColumns = columns.map((col) => {
    if (!col.editable) {
      return {
        ...col,
        render: (_: unknown, record: Item) => {
          const editable = isEditing(record);
          return editable ? (
            <span key={record.id}>
              <Typography.Link
                onClick={() => save(record.id)}
                style={{ marginRight: 8 }}
                disabled={disabled}
              >
                {locales.save}
              </Typography.Link>
              {!isAddingNewPath && (
                <Popconfirm
                  title={locales.cancelQuestions}
                  onCancel={cancel}
                  onConfirm={cancel}
                  okText={locales.ok}
                  cancelText={locales.cancel}
                >
                  <Typography.Link
                    style={{ marginRight: 8 }}
                    disabled={form.isFieldValidating('path')}
                  >
                    {locales.cancel}
                  </Typography.Link>
                </Popconfirm>
              )}
              <Popconfirm
                placement="topRight"
                title={locales.deleteEditQuestions}
                onConfirm={() => handleDelete(record.id)}
                okText={locales.ok}
                cancelText={locales.cancel}
              >
                <Typography.Link disabled={disabled}>
                  {locales.delete}
                </Typography.Link>
              </Popconfirm>
            </span>
          ) : (
            <>
              <Typography.Link
                disabled={editingKey !== '' || disabled}
                onClick={() => edit(record)}
              >
                {locales.edit}
              </Typography.Link>
              &nbsp; &nbsp; &nbsp;
              <Popconfirm
                title={locales.deleteQuestions}
                okText={locales.ok}
                cancelText={locales.cancel}
                onConfirm={() => handleDelete(record.id)}
              >
                <Typography.Link disabled={editingKey !== '' || disabled}>
                  {locales.delete}
                </Typography.Link>
              </Popconfirm>
            </>
          );
        },
      };
    }
    return {
      ...col,
      onCell: (record: Item) => ({
        record,
        inputType: col.dataIndex,
        dataIndex: col.dataIndex,
        title: col.title,
        editing: isEditing(record),
      }),
    };
  }) as ColumnsType<Item>;

  const EditableCell: React.FC<EditableCellProps> = ({
    editing,
    dataIndex,
    title,
    inputType,
    record,
    index,
    children,
    ...restProps
  }): JSX.Element => {
    const handleChange = (): Promise<void> => form.validateFields();

    const validation = (_: unknown, value: string): Promise<void> => {
      if (
        originData.find((item) => item.path === value && editingKey !== item.id)
      ) {
        return Promise.reject(new Error(locales.validation.thisPathExist));
      }
      return Promise.resolve();
    };

    return (
      <td {...restProps}>
        {editing ? (
          <Form.Item
            name={dataIndex}
            style={{ margin: 0 }}
            rules={[
              {
                required: true,
                message: localeValidation.fieldNotBeEmpty,
              },
              () => ({
                async validator(_, value) {
                  await validation(_, value);
                },
              }),
            ]}
          >
            <Input onChange={handleChange} />
          </Form.Item>
        ) : (
          children
        )}
      </td>
    );
  };

  return (
    <Form scrollToFirstError form={form} component={false}>
      <div style={{ marginBottom: '12px' }}>
        <Button
          onClick={handleSelectAllItems}
          type="link"
          disabled={editingKey !== '' || disabled}
        >
          {isAllSelected ? locales.unSelectAll : locales.selectAll}
        </Button>
        <Button
          icon={<PlusOutlined />}
          onClick={handleAdd}
          type="link"
          disabled={editingKey !== '' || disabled}
        />
        {selectedRowKeys.length !== 0 ? (
          <Button
            icon={<DeleteFilled />}
            onClick={deleteSelectedItems}
            type="link"
          />
        ) : null}
        <span style={{ marginLeft: 8 }}>
          {selectedRowKeys.length !== 0
            ? `${locales.selectedEntries} ${selectedRowKeys.length}`
            : ''}
        </span>
        <Search
          placeholder={locales.searchPlaceholder}
          onChange={(value) => onSearch(value.target.value)}
          enterButton
          allowClear
          style={{ width: 400, float: 'right' }}
          value={searchValue}
          disabled={disabled}
        />
      </div>

      <Table
        size="small"
        components={{
          body: {
            cell: EditableCell,
          },
        }}
        bordered
        rowKey={(record) => record.id}
        dataSource={filteredData}
        columns={mergedColumns}
        rowClassName="editable-row"
        rowSelection={rowSelection}
        pagination={{
          position: ['bottomRight'],
          ...dashboardState,
          total: originData.length,
        }}
        tableLayout="fixed"
        onChange={handleTableChange}
      />
    </Form>
  );
};
