import React, { useEffect, useMemo, useState } from 'react';
import { Alert, Checkbox, Form, Input, Modal, Select, Space, Typography, message } from 'antd';

import { DBQuery } from '../../wailsjs/go/app/App';
import type { SavedConnection } from '../types';
import { buildRpcConnectionConfig } from '../utils/connectionRpcConfig';
import {
  buildMessagePublishCommand,
  createDefaultMessagePublishDraft,
  getMessagePublishPresentation,
  type MessagePublishDraft,
} from '../utils/messagePublish';

const { Text } = Typography;
const { TextArea } = Input;

export type MessagePublishModalProps = {
  open: boolean;
  connection: SavedConnection | null;
  executionDbName?: string;
  defaultDestination?: string;
  onCancel: () => void;
  onSuccess?: (result: { destination: string; affectedRows: number; commandText: string }) => void;
};

const MessagePublishModal: React.FC<MessagePublishModalProps> = ({
  open,
  connection,
  executionDbName = '',
  defaultDestination = '',
  onCancel,
  onSuccess,
}) => {
  const [form] = Form.useForm<MessagePublishDraft>();
  const [submitting, setSubmitting] = useState(false);
  const presentation = useMemo(
    () => getMessagePublishPresentation(connection?.config),
    [connection],
  );

  useEffect(() => {
    if (!open || !connection) return;
    form.setFieldsValue(
      createDefaultMessagePublishDraft(
        connection.config,
        defaultDestination,
      ),
    );
  }, [connection, defaultDestination, form, open]);

  useEffect(() => {
    if (open) return;
    form.resetFields();
    setSubmitting(false);
  }, [form, open]);

  const handleSubmit = async () => {
    if (!connection) return;

    let values: MessagePublishDraft;
    try {
      values = await form.validateFields();
    } catch {
      return;
    }

    let command;
    try {
      command = buildMessagePublishCommand(connection.config, values);
    } catch (error: any) {
      void message.error(error?.message || '构造发送命令失败');
      return;
    }

    setSubmitting(true);
    try {
      const res = await DBQuery(
        buildRpcConnectionConfig(connection.config) as any,
        executionDbName,
        command.commandText,
      );
      if (!res?.success) {
        void message.error(`发送失败: ${res?.message || '未知错误'}`);
        return;
      }

      const affectedRows = Number((res.data as any)?.affectedRows);
      onSuccess?.({
        destination: command.destinationLabel,
        affectedRows: Number.isFinite(affectedRows) ? affectedRows : 0,
        commandText: command.commandText,
      });
    } catch (error: any) {
      void message.error(`发送失败: ${error?.message || String(error)}`);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Modal
      title={`测试发送消息${connection?.name ? ` · ${connection.name}` : ''}`}
      open={open}
      onCancel={onCancel}
      onOk={() => { void handleSubmit(); }}
      okText="发送"
      confirmLoading={submitting}
      width={720}
      destroyOnHidden
      maskClosable={!submitting}
    >
      <Space direction="vertical" size={12} style={{ width: '100%' }}>
        <Alert
          type="info"
          showIcon
          message={presentation.alertMessage}
        />

        <Form<MessagePublishDraft>
          form={form}
          layout="vertical"
          initialValues={createDefaultMessagePublishDraft(connection?.config, defaultDestination)}
        >
          <Form.Item
            label={presentation.destinationLabel}
            name="destination"
            rules={[{ required: true, message: presentation.destinationRequiredMessage }]}
          >
            <Input placeholder={presentation.destinationPlaceholder} />
          </Form.Item>

          {presentation.showExchange && (
            <Form.Item
              label="Exchange（可选）"
              name="exchange"
              extra="留空使用默认交换机；若填写自定义交换机，请确认目标 Queue 已建立 binding。"
            >
              <Input placeholder="例如：events.topic" />
            </Form.Item>
          )}

          {presentation.showRoutingKey && (
            <Form.Item
              label="Routing Key（可选）"
              name="routingKey"
              extra="留空时默认使用当前 Queue 名。"
            >
              <Input placeholder="例如：orders.queue" />
            </Form.Item>
          )}

          {presentation.showQos && (
            <Form.Item
              label="QoS"
              name="qos"
              extra="0 为至多一次，1 为至少一次，2 为仅一次。"
            >
              <Select
                options={[
                  { label: '0 · At most once', value: 0 },
                  { label: '1 · At least once', value: 1 },
                  { label: '2 · Exactly once', value: 2 },
                ]}
              />
            </Form.Item>
          )}

          {presentation.showRetain && (
            <Form.Item name="retain" valuePropName="checked" style={{ marginBottom: 16 }}>
              <Checkbox>Retain 消息</Checkbox>
            </Form.Item>
          )}

          {presentation.showKey && (
            <Form.Item label="消息 Key（可选）">
              <Space.Compact style={{ width: '100%' }}>
                <Form.Item name="keyMode" noStyle>
                  <Select
                    style={{ width: 120 }}
                    options={[
                      { label: '文本', value: 'text' },
                      { label: 'JSON', value: 'json' },
                    ]}
                  />
                </Form.Item>
                <Form.Item name="key" noStyle>
                  <Input placeholder="可留空；JSON 模式请输入一行合法 JSON" />
                </Form.Item>
              </Space.Compact>
            </Form.Item>
          )}

          <Form.Item label="消息体类型" name="bodyMode">
            <Select
              options={[
                { label: 'JSON', value: 'json' },
                { label: '文本', value: 'text' },
              ]}
            />
          </Form.Item>

          <Form.Item
            label="消息体"
            name="body"
            rules={[{ required: true, message: '请输入消息体' }]}
            extra="JSON 模式下需输入合法 JSON；文本模式按原样发送。"
          >
            <TextArea rows={8} placeholder="请输入消息体" />
          </Form.Item>

          <Form.Item
            label="Headers（可选）"
            name="headers"
            extra={'需为 JSON 对象，例如 {"x-source":"gonavi"}。'}
          >
            <TextArea rows={5} placeholder='{"x-source":"gonavi"}' />
          </Form.Item>

          {presentation.showProperties && (
            <Form.Item
              label="Properties（可选）"
              name="properties"
              extra='需为 JSON 对象，例如 {"content_type":"application/json"}。'
            >
              <TextArea rows={5} placeholder='{"content_type":"application/json"}' />
            </Form.Item>
          )}
        </Form>

        <Text type="secondary">
          {presentation.successHint} 发送成功后会返回 <Text code>affectedRows</Text>，用于确认本次测试消息是否已提交。
        </Text>
      </Space>
    </Modal>
  );
};

export default MessagePublishModal;
