import IconFont from '@/components/IconFont';
import TreeGroup from '@/components/shared/TreeGroup';
import { DEFAULT_PAGE_SIZE } from '@/constants';
import {
  apiSearchThings,
  apiUpdateThing,
} from '@/services/master/ThingController';
import { EditOutlined, EnvironmentOutlined } from '@ant-design/icons';
import {
  ActionType,
  ProCard,
  ProColumns,
  ProTable,
} from '@ant-design/pro-components';
import { FormattedMessage, history, useIntl } from '@umijs/max';
import { Button, Divider, Grid, Space, Tag, theme } from 'antd';
import message from 'antd/es/message';
import Paragraph from 'antd/lib/typography/Paragraph';
import { useRef, useState } from 'react';
import CreateDevice from './components/CreateDevice';
import EditDeviceModal from './components/EditDeviceModal';
import LocationModal from './components/LocationModal';

const ManagerDevicePage = () => {
  const { useBreakpoint } = Grid;
  const intl = useIntl();
  const screens = useBreakpoint();
  const { token } = theme.useToken();
  const actionRef = useRef<ActionType | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [messageApi, contextHolder] = message.useMessage();
  const [selectedRowsState, setSelectedRowsState] = useState<
    MasterModel.Thing[]
  >([]);
  const [groupCheckedKeys, setGroupCheckedKeys] = useState<
    string | string[] | null
  >(null);
  const [isEditModalVisible, setIsEditModalVisible] = useState<boolean>(false);
  const [editingDevice, setEditingDevice] = useState<MasterModel.Thing | null>(
    null,
  );
  const [isLocationModalVisible, setIsLocationModalVisible] =
    useState<boolean>(false);
  const [locationDevice, setLocationDevice] =
    useState<MasterModel.Thing | null>(null);

  const handleLocation = (device: MasterModel.Thing) => {
    setLocationDevice(device);
    setIsLocationModalVisible(true);
  };

  const handleEdit = (device: MasterModel.Thing) => {
    setEditingDevice(device);
    setIsEditModalVisible(true);
  };

  const handleEditCancel = () => {
    setIsEditModalVisible(false);
    setEditingDevice(null);
  };

  const handleLocationCancel = () => {
    setIsLocationModalVisible(false);
    setLocationDevice(null);
  };

  const handleLocationSubmit = async (values: MasterModel.Thing) => {
    try {
      await apiUpdateThing(values);
      messageApi.success(
        intl.formatMessage({
          id: 'master.devices.location.update.success',
          defaultMessage: 'Location updated successfully',
        }),
      );
      setIsLocationModalVisible(false);
      setLocationDevice(null);
      actionRef.current?.reload();
    } catch (error) {
      messageApi.error(
        intl.formatMessage({
          id: 'master.devices.location.update.error',
          defaultMessage: 'Location update failed',
        }),
      );
    }
  };

  const handleEditSubmit = async (values: MasterModel.Thing) => {
    try {
      await apiUpdateThing(values);
      messageApi.success(
        intl.formatMessage({
          id: 'master.devices.update.success',
          defaultMessage: 'Updated successfully',
        }),
      );
      setIsEditModalVisible(false);
      setEditingDevice(null);
      actionRef.current?.reload();
    } catch (error) {
      messageApi.error(
        intl.formatMessage({
          id: 'master.devices.update.error',
          defaultMessage: 'Update failed',
        }),
      );
    }
  };

  const columns: ProColumns<MasterModel.Thing>[] = [
    {
      key: 'name',
      title: (
        <FormattedMessage id="master.devices.name" defaultMessage="Name" />
      ),
      tip: intl.formatMessage({
        id: 'master.devices.name.tip',
        defaultMessage: 'The device name',
      }),
      dataIndex: 'name',
      render: (_, record) => (
        <Paragraph
          style={{
            marginBottom: 0,
            verticalAlign: 'middle',
            display: 'inline-block',
            color: token.colorText,
          }}
          copyable
        >
          {record?.name}
        </Paragraph>
      ),
    },

    {
      key: 'external_id',
      title: (
        <FormattedMessage
          id="master.devices.external_id"
          defaultMessage="External ID"
        />
      ),
      tip: intl.formatMessage({
        id: 'master.devices.external_id.tip',
        defaultMessage: 'The external identifier',
      }),
      responsive: ['lg', 'md'],
      dataIndex: ['metadata', 'external_id'],
      render: (_, record) =>
        record?.metadata?.external_id ? (
          <Paragraph
            style={{
              marginBottom: 0,
              verticalAlign: 'middle',
              display: 'inline-block',
              color: token.colorText,
            }}
            copyable
          >
            {record?.metadata?.external_id}
          </Paragraph>
        ) : (
          '-'
        ),
    },
    {
      key: 'type',
      hideInSearch: true,
      title: (
        <FormattedMessage id="master.devices.type" defaultMessage="Type" />
      ),
      tip: intl.formatMessage({
        id: 'master.devices.type.tip',
        defaultMessage: 'The device type',
      }),
      dataIndex: ['metadata', 'type'],
      render: (_, record) => record?.metadata?.type || '...',
    },

    {
      key: 'connected',
      hideInSearch: true,
      title: <FormattedMessage id="common.status" defaultMessage="Status" />,
      dataIndex: ['metadata', 'connected'],
      render: (_, record) => (
        <Tag color={record?.metadata?.connected ? 'green' : 'red'}>
          {record?.metadata?.connected
            ? intl.formatMessage({
                id: 'master.devices.online',
                defaultMessage: 'Online',
              })
            : intl.formatMessage({
                id: 'master.devices.offline',
                defaultMessage: 'Offline',
              })}
        </Tag>
      ),
    },

    {
      title: (
        <FormattedMessage id="common.actions" defaultMessage="Operating" />
      ),
      hideInSearch: true,
      render: (_, device) => {
        return (
          <Space
            size={5}
            split={<Divider type="vertical" style={{ margin: '0 4px' }} />}
          >
            <Button
              shape="default"
              size="small"
              icon={<EditOutlined />}
              onClick={() => handleEdit(device)}
            />
            <Button
              shape="default"
              size="small"
              icon={<EnvironmentOutlined />}
              onClick={() => handleLocation(device)}
            />
            <Button
              shape="default"
              size="small"
              icon={<IconFont type="icon-camera" />}
              onClick={() => {
                history.push(`/manager/devices/${device.id}/camera`);
              }}
            />
            {device?.metadata?.type === 'gmsv6' && (
              <Button
                shape="default"
                size="small"
                icon={<IconFont type="icon-terminal" />}
              />
            )}
          </Space>
        );
      },
    },
  ];

  return (
    <>
      <EditDeviceModal
        visible={isEditModalVisible}
        device={editingDevice}
        onCancel={handleEditCancel}
        onSubmit={handleEditSubmit}
      />
      <LocationModal
        visible={isLocationModalVisible}
        device={locationDevice}
        onCancel={handleLocationCancel}
        onSubmit={handleLocationSubmit}
      />
      {contextHolder}
      <ProCard split={screens.md ? 'vertical' : 'horizontal'}>
        <ProCard colSpan={{ xs: 24, sm: 24, md: 6, lg: 6, xl: 6 }}>
          <TreeGroup
            disable={isLoading}
            multiple={true}
            groupIds={groupCheckedKeys}
            onSelected={(value: string | string[] | null) => {
              setGroupCheckedKeys(value);
              if (actionRef.current) {
                actionRef.current.reload();
              }
            }}
          />
        </ProCard>
        <ProCard colSpan={{ xs: 24, sm: 24, md: 18, lg: 18, xl: 18 }}>
          <ProTable<MasterModel.Thing>
            columns={columns}
            tableLayout="auto"
            actionRef={actionRef}
            rowKey="id"
            search={{
              layout: 'vertical',
              defaultCollapsed: false,
            }}
            dateFormatter="string"
            rowSelection={{
              selectedRowKeys: selectedRowsState.map((row) => row.id!),
              onChange: (_: React.Key[], selectedRows: MasterModel.Thing[]) => {
                setSelectedRowsState(selectedRows);
              },
            }}
            pagination={{
              defaultPageSize: DEFAULT_PAGE_SIZE * 2,
              showSizeChanger: true,
              pageSizeOptions: ['10', '15', '20'],
              showTotal: (total, range) =>
                `${range[0]}-${range[1]} 
                      ${intl.formatMessage({
                        id: 'common.paginations.of',
                        defaultMessage: 'of',
                      })}
                    ${total} ${intl.formatMessage({
                  id: 'master.devices.table.pagination',
                  defaultMessage: 'devices',
                })}`,
            }}
            request={async (params = {}) => {
              const { current = 1, pageSize, name, external_id } = params;
              const size = pageSize || DEFAULT_PAGE_SIZE * 2;
              const offset = current === 1 ? 0 : (current - 1) * size;
              setIsLoading(true);

              const metadata: Partial<MasterModel.SearchThingMetadata> = {};
              if (external_id) metadata.external_id = external_id;

              // Add group filter if groups are selected
              if (groupCheckedKeys && groupCheckedKeys.length > 0) {
                const groupId = Array.isArray(groupCheckedKeys)
                  ? groupCheckedKeys.join(',')
                  : groupCheckedKeys;
                metadata.group_id = groupId;
              }

              const query: MasterModel.SearchThingPaginationBody = {
                offset: offset,
                limit: size,
                order: 'name',
                dir: 'asc',
              };
              if (name) query.name = name;
              if (Object.keys(metadata).length > 0) query.metadata = metadata;

              try {
                const response = await apiSearchThings(query);
                setIsLoading(false);
                return {
                  data: response.things || [],
                  success: true,
                  total: response.total || 0,
                };
              } catch (error) {
                setIsLoading(false);
                return {
                  data: [],
                  success: false,
                  total: 0,
                };
              }
            }}
            options={{
              search: false,
              setting: false,
              density: false,
              reload: true,
            }}
            toolBarRender={() => [
              <CreateDevice
                message={messageApi}
                onSuccess={(isSuccess) => {
                  if (isSuccess) {
                    actionRef.current?.reload();
                  }
                }}
                key="create-device"
              />,
            ]}
          />
        </ProCard>
      </ProCard>
    </>
  );
};

export default ManagerDevicePage;
