import React, { useEffect, useMemo } from 'react';
import {
  XCard,
  registerCatalog,
  type ActionPayload,
  type XAgentCommand_v0_9,
} from '@ant-design/x-card';
import {
  Alert,
  Button,
  DatePicker,
  Flex,
  Form,
  Input,
  InputNumber,
  Select,
  Typography,
} from 'antd';
import dayjs from 'dayjs';
import type { AiFormField, AiFormSchema } from './types';
import { useSubmissionState, useXCardSurface } from './useSubmissionState';

const FORM_CATALOG_ID = 'gongxue-form-catalog';

registerCatalog({
  catalogId: FORM_CATALOG_ID,
  components: {
    FormPreview: {
      type: 'object',
      properties: {
        form: { type: 'object' },
        disabled: { type: 'boolean' },
      },
    },
  },
});

function surfaceId(formId: string): string {
  return `form-${formId}`;
}

function initialValue(field: AiFormField): unknown {
  if (field.type === 'date' && typeof field.defaultValue === 'string') {
    const parsed = dayjs(field.defaultValue);
    return parsed.isValid() ? parsed : undefined;
  }
  return field.defaultValue;
}

function normalizeValues(
  fields: AiFormField[],
  raw: Record<string, unknown>,
): Record<string, unknown> {
  const values: Record<string, unknown> = {};
  for (const field of fields) {
    const value = raw[field.name];
    if (value === undefined || value === null || value === '') continue;
    values[field.name] =
      field.type === 'date' && dayjs.isDayjs(value) ? value.format('YYYY-MM-DD') : value;
  }
  return values;
}

interface FormPreviewProps {
  form?: AiFormSchema & {
    submitting?: boolean;
    submitted?: boolean;
    error?: string | null;
  };
  disabled?: boolean;
  onAction?: (name: string, context: Record<string, unknown>) => void;
}

/**
 * A2UI component registered for the `gongxue-form-catalog` catalog.
 * Receives the validated form schema through data binding and reports
 * normalized values back through the `form:submit` action.
 */
const FormPreview: React.FC<FormPreviewProps> = ({ form, disabled, onAction }) => {
  const submitting = Boolean(form?.submitting);
  const initialValues = useMemo(
    () =>
      Object.fromEntries((form?.fields ?? []).map((field) => [field.name, initialValue(field)])),
    [form?.fields],
  );
  if (!form) return null;
  const finished = Boolean(form.submitted) || form.status === 'submitted';
  const expired = form.status === 'expired';

  const handleFinish = (values: Record<string, unknown>) => {
    onAction?.('form:submit', { values: normalizeValues(form.fields, values) });
  };

  return (
    <Flex vertical gap={8}>
      <Typography.Text strong>{form.title}</Typography.Text>
      {form.description && (
        <Typography.Text type="secondary" className="ai-chat-dynamic-form__desc">
          {form.description}
        </Typography.Text>
      )}
      {expired ? (
        <Alert type="warning" showIcon title="表单已失效" description="此表单已被新的请求替代，请让助手重新生成。" />
      ) : finished ? (
        <Alert type="success" showIcon title="已提交，AI 正在处理…" />
      ) : (
        <Form
          layout="vertical"
          size="small"
          initialValues={initialValues}
          onFinish={(values) => void handleFinish(values as Record<string, unknown>)}
          disabled={disabled || submitting}
          requiredMark={false}
        >
          {form.fields.map((field) => (
            <Form.Item
              key={field.name}
              name={field.name}
              label={field.label}
              rules={[
                {
                  required: field.required,
                  message: field.required
                    ? field.type === 'select' || field.type === 'date'
                      ? `请选择${field.label}`
                      : `请输入${field.label}`
                    : undefined,
                },
              ]}
            >
              {field.type === 'textarea' ? (
                <Input.TextArea rows={3} placeholder={field.placeholder} />
              ) : field.type === 'number' ? (
                <InputNumber
                  className="ai-chat-dynamic-form__number"
                  placeholder={field.placeholder}
                />
              ) : field.type === 'select' ? (
                <Select
                  allowClear={!field.required}
                  placeholder={field.placeholder}
                  options={field.options}
                />
              ) : field.type === 'date' ? (
                <DatePicker
                  className="ai-chat-dynamic-form__date"
                  placeholder={field.placeholder}
                />
              ) : (
                <Input placeholder={field.placeholder} />
              )}
            </Form.Item>
          ))}
          {form.error && (
            <Alert
              type="error"
              showIcon
              title={form.error}
              className="ai-chat-dynamic-form__error"
            />
          )}
          <Button type="primary" htmlType="submit" loading={submitting} disabled={disabled}>
            {form.submitLabel || '提交'}
          </Button>
        </Form>
      )}
    </Flex>
  );
};

export interface DynamicFormProps {
  form: AiFormSchema;
  disabled?: boolean;
  onSubmit: (values: Record<string, unknown>) => void | Promise<void>;
}

/**
 * A2UI form rendered through the official @ant-design/x-card renderer.
 * The validated schema is bound into the surface data model; submit
 * success/failure/loading transitions are pushed as incremental commands.
 */
export const DynamicForm: React.FC<DynamicFormProps> = ({ form, disabled, onSubmit }) => {
  const sid = surfaceId(form.id);
  const { submitting, submitted, error, run } = useSubmissionState();
  const { commands, pushCommands } = useXCardSurface(sid);

  useEffect(() => {
    const cmds: XAgentCommand_v0_9[] = [
      {
        version: 'v0.9',
        createSurface: { surfaceId: sid, catalogId: FORM_CATALOG_ID },
      },
      {
        version: 'v0.9',
        updateDataModel: {
          surfaceId: sid,
          path: '/form',
          value: { ...form, submitting, submitted, error },
        },
      },
      {
        version: 'v0.9',
        updateComponents: {
          surfaceId: sid,
          components: [
            {
              id: 'root',
              component: 'FormPreview',
              form: { path: '/form' },
              disabled: Boolean(disabled),
            },
          ],
        },
      },
    ];
    pushCommands(cmds);
  }, [disabled, error, form, pushCommands, sid, submitted, submitting]);

  const handleSubmit = (values: Record<string, unknown>) => {
    void run(async () => {
      await onSubmit(values);
    });
  };

  const handleAction = (payload: ActionPayload) => {
    if (payload.name !== 'form:submit') return;
    const values =
      payload.context?.values && typeof payload.context.values === 'object'
        ? (payload.context.values as Record<string, unknown>)
        : {};
    void handleSubmit(values);
  };

  return (
    <div className="ai-chat-dynamic-form">
      <XCard.Box components={{ FormPreview }} commands={commands} onAction={handleAction}>
        <XCard.Card id={surfaceId(form.id)} />
      </XCard.Box>
    </div>
  );
};
