import { apiQueryCamera } from '@/services/master/MessageController';
import { apiGetThingDetail } from '@/services/master/ThingController';
import { mqttClient } from '@/utils/mqttClient';
import { ArrowLeftOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { history, useIntl, useModel, useParams } from '@umijs/max';
import { Badge, Button, Col, message, Row, Space, Spin } from 'antd';
import { useEffect, useState } from 'react';
import { v4 as uuidv4 } from 'uuid';
import CameraFormModal from './components/CameraFormModal';
import CameraTable from './components/CameraTable';
import ConfigCameraV5 from './components/ConfigCameraV5';
import ConfigCameraV6 from './components/ConfigCameraV6';

const CameraConfigPage = () => {
  const { thingId } = useParams<{ thingId: string }>();
  const intl = useIntl();
  const [isModalVisible, setIsModalVisible] = useState(false);
  const [loading, setLoading] = useState(true);
  const [cameraLoading, setCameraLoading] = useState(false);
  const [thing, setThing] = useState<MasterModel.Thing | null>(null);
  const [cameras, setCameras] = useState<MasterModel.Camera[] | null>([]);
  const [cameraConfig, setCameraConfig] = useState<MasterModel.CameraV6 | null>(
    null,
  );
  const [isOnline, setIsOnline] = useState(false);
  const [editingCamera, setEditingCamera] = useState<MasterModel.Camera | null>(
    null,
  );
  const { initialState } = useModel('@@initialState');

  // Initialize MQTT connection
  useEffect(() => {
    const { frontend_thing_id, frontend_thing_key } =
      initialState?.currentUserProfile?.metadata || {};

    if (!frontend_thing_id || !frontend_thing_key) return;

    // Connect using mqttClient utility
    mqttClient.connect({
      username: frontend_thing_id,
      password: frontend_thing_key,
    });

    const unConnect = mqttClient.onConnect(() => {
      // MQTT connected
    });

    const unError = mqttClient.onError((error) => {
      console.error('MQTT Error:', error);
    });

    const unClose = mqttClient.onClose(() => {
      // MQTT connection closed
    });

    return () => {
      unConnect();
      unError();
      unClose();
      mqttClient.disconnect();
    };
  }, [initialState]);

  // Check device online status using connected property
  useEffect(() => {
    setIsOnline(thing?.metadata?.connected ?? false);
  }, [thing]);

  // Fetch thing info on mount
  useEffect(() => {
    const fetchThingInfo = async () => {
      if (!thingId) return;

      try {
        setLoading(true);
        const thingData = await apiGetThingDetail(thingId);
        setThing(thingData);
      } catch (error) {
        console.error('Failed to fetch thing info:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchThingInfo();
  }, [thingId]);

  // Fetch camera config when thing data is available
  const fetchCameraConfig = async () => {
    if (
      !thing ||
      !initialState?.currentUserProfile?.metadata?.frontend_thing_key
    ) {
      return;
    }

    try {
      setCameraLoading(true);
      const resp = await apiQueryCamera(
        thing.metadata?.data_channel_id || '',
        initialState.currentUserProfile.metadata.frontend_thing_key,
        {
          offset: 0,
          limit: 1,
          subtopic: `config.${thing.metadata?.type}.cameras`,
        },
      );

      if (resp.messages!.length > 0) {
        setCameras(
          resp.messages![0].string_value_parsed?.cams as MasterModel.Camera[],
        );
        setCameraConfig(
          resp.messages![0].string_value_parsed as MasterModel.CameraV6,
        );
      }
    } catch (error) {
      console.error('Failed to fetch camera config:', error);
    } finally {
      setCameraLoading(false);
    }
  };

  useEffect(() => {
    fetchCameraConfig();
  }, [thing, initialState]);

  const handleOpenModal = () => {
    setIsModalVisible(true);
  };

  const handleCloseModal = () => {
    setIsModalVisible(false);
    setEditingCamera(null);
  };

  // Core function to send camera config via MQTT
  const sendCameraConfig = (configPayload: MasterModel.CameraV6) => {
    // Skip sending for gmsv5
    if (thing?.metadata?.type === 'gmsv5') {
      return true;
    }

    // Check if device is online
    if (!isOnline) {
      message.error(
        intl.formatMessage({
          id: 'master.camera.config.error.deviceOffline',
          defaultMessage: 'Thiết bị đang ngoại tuyến, không thể gửi cấu hình',
        }),
      );
      return false;
    }

    if (!thing?.metadata?.cfg_channel_id || !thing?.metadata?.external_id) {
      message.error(
        intl.formatMessage({
          id: 'master.camera.config.error.missingConfig',
          defaultMessage: 'Thiếu thông tin cấu hình thiết bị',
        }),
      );
      return false;
    }

    const { cfg_channel_id, external_id } = thing.metadata;
    const pubTopic = `channels/${cfg_channel_id}/messages/cameraconfig/${thing.metadata?.type}`;
    const mac = external_id?.replaceAll('-', '');
    const ack = uuidv4();
    const now = Date.now() / 1000;

    const senml: MasterModel.CameraV6ConfigRequest[] = [
      {
        bn: `urn:dev:mac:${mac?.toLowerCase()}:`,
        n: 'ack',
        t: now,
        vs: ack,
      },
      {
        n: initialState?.currentUserProfile?.email?.replaceAll('@', ':') || '',
        vs: JSON.stringify(configPayload),
      },
    ];

    const payload = JSON.stringify(senml);

    if (mqttClient.isConnected()) {
      mqttClient.publish(pubTopic, payload);
      message.success(
        intl.formatMessage({
          id: 'master.camera.config.success',
          defaultMessage: 'Đã gửi cấu hình thành công',
        }),
      );
      return true;
    } else {
      message.error(
        intl.formatMessage({
          id: 'master.camera.config.error.mqttNotConnected',
          defaultMessage: 'MQTT chưa kết nối',
        }),
      );
      return false;
    }
  };

  // Handle camera list config submission (add/edit/delete cameras)
  const handleSubmitCameraConfig = (updatedCams: MasterModel.Camera[]) => {
    const configPayload: MasterModel.CameraV6 = {
      cams: updatedCams,
      record_type: cameraConfig?.record_type || 'all',
      ...(cameraConfig?.record_type === 'alarm' && {
        record_alarm_list: cameraConfig?.record_alarm_list || [],
      }),
    };

    if (sendCameraConfig(configPayload)) {
      // Update local state
      setCameraConfig(configPayload);
      setCameras(updatedCams);
    }
  };

  // Handle open edit modal - open modal with camera data for editing
  const handleOpenEditModal = (camera: MasterModel.Camera) => {
    setEditingCamera(camera);
    setIsModalVisible(true);
  };

  // Handle submit camera (add or edit)
  const handleSubmitCamera = (camera: MasterModel.Camera) => {
    if (editingCamera) {
      // Edit mode: update existing camera
      const updatedCams = (cameraConfig?.cams || []).map((cam) =>
        cam.id === camera.id ? camera : cam,
      );
      handleSubmitCameraConfig(updatedCams);
    } else {
      // Add mode: add new camera
      const updatedCams = [...(cameraConfig?.cams || []), camera];
      handleSubmitCameraConfig(updatedCams);
    }
    handleCloseModal();
  };

  // Handle delete cameras - submit config with cameras removed
  const handleDeleteCameras = (cameraIds: string[]) => {
    const updatedCams = (cameraConfig?.cams || []).filter(
      (cam) => !cameraIds.includes(cam.id || ''),
    );
    handleSubmitCameraConfig(updatedCams);
  };

  // Handle recording config submission from ConfigCameraV6
  const handleSubmitConfig = (configPayload: MasterModel.CameraV6) => {
    if (sendCameraConfig(configPayload)) {
      // Update local state
      setCameraConfig(configPayload);
    }
  };

  // Helper function to determine which camera component to render
  const renderCameraRecordingComponent = () => {
    if (thing?.metadata?.type === 'gmsv5') {
      return <ConfigCameraV5 thing={thing} />;
    }

    // Default: gmsv6, spole, and other types
    return (
      <ConfigCameraV6
        thing={thing}
        cameraConfig={cameraConfig}
        onSubmit={handleSubmitConfig}
        isOnline={isOnline}
      />
    );
  };

  return (
    <Spin spinning={loading}>
      <PageContainer
        header={{
          title: (
            <Space>
              <Button
                type="text"
                icon={<ArrowLeftOutlined />}
                onClick={() => history.push('/manager/devices')}
              />
              <span>
                {thing?.name ||
                  intl.formatMessage({
                    id: 'master.camera.loading',
                    defaultMessage: 'Loading...',
                  })}
              </span>
              <Badge
                status={isOnline ? 'success' : 'default'}
                text={
                  isOnline
                    ? intl.formatMessage({
                        id: 'master.devices.online',
                        defaultMessage: 'Trực tuyến',
                      })
                    : intl.formatMessage({
                        id: 'master.devices.offline',
                        defaultMessage: 'Ngoại tuyến',
                      })
                }
              />
            </Space>
          ),
        }}
      >
        <Row gutter={24}>
          {/* Left Column - Camera Table */}
          <Col xs={24} md={10} lg={8}>
            <CameraTable
              cameraData={cameras}
              onCreateCamera={handleOpenModal}
              onEditCamera={handleOpenEditModal}
              onDeleteCameras={handleDeleteCameras}
              onReload={fetchCameraConfig}
              loading={cameraLoading}
              isOnline={isOnline}
            />
          </Col>

          {/* Right Column - Camera Recording Configuration */}
          <Col xs={24} md={14} lg={16}>
            {renderCameraRecordingComponent()}
          </Col>
        </Row>

        {/* Create/Edit Camera Modal */}
        <CameraFormModal
          open={isModalVisible}
          onCancel={handleCloseModal}
          onSubmit={handleSubmitCamera}
          isOnline={isOnline}
          editingCamera={editingCamera}
        />
      </PageContainer>
    </Spin>
  );
};

export default CameraConfigPage;
