import { App as AntApp, Button, Checkbox, Col, Form, Input, InputNumber, Modal, Row, Select, Space } from "antd";
import { useEffect, useState } from "react";

import type {
  CreateModelRequest,
  Model,
  ModelCapability,
  ModelTestResponse,
  ProviderOption,
  TestModelRequest,
  UpdateModelRequest,
} from "../../../../shared/api";

interface FormValues {
  capabilities: ModelCapability[];
  contextLength: null | number;
  maxOutputTokens: null | number;
  modelId: string;
  name: string;
  providerId: string;
}

interface ModelFormModalProps {
  editingModel: Model | null;
  onCancel: () => void;
  onCreate: (data: CreateModelRequest) => Promise<unknown>;
  onOpenChange: (open: boolean) => void;
  onUpdate: (args: { data: UpdateModelRequest; id: string }) => Promise<unknown>;
  open: boolean;
  providers: ProviderOption[];
  providersError: Error | null;
  providersLoading: boolean;
  submitting: boolean;
  testModelConnection?: (data: TestModelRequest) => Promise<ModelTestResponse>;
}

const DEFAULT_CAPABILITIES: ModelCapability[] = ["text", "reasoning"];

const CAPABILITY_OPTIONS: Array<{ label: string; value: ModelCapability }> = [
  { label: "文本", value: "text" },
  { label: "推理", value: "reasoning" },
  { label: "图片生成", value: "image-generation" },
  { label: "视频生成", value: "video-generation" },
  { label: "音频生成", value: "audio-generation" },
  { label: "图片识别", value: "image-recognition" },
  { label: "视频识别", value: "video-recognition" },
  { label: "音频识别", value: "audio-recognition" },
];

export function ModelFormModal({
  editingModel,
  onCancel,
  onCreate,
  onOpenChange,
  onUpdate,
  open,
  providers,
  providersError,
  providersLoading,
  submitting,
  testModelConnection,
}: ModelFormModalProps) {
  const { message } = AntApp.useApp();
  const [form] = Form.useForm<FormValues>();
  const [testing, setTesting] = useState(false);

  useEffect(() => {
    if (!open) return;
    if (editingModel) {
      form.setFieldsValue({
        capabilities: editingModel.capabilities,
        contextLength: editingModel.contextLength,
        maxOutputTokens: editingModel.maxOutputTokens,
        modelId: editingModel.modelId,
        name: editingModel.name,
        providerId: editingModel.providerId,
      });
    } else {
      form.resetFields();
      form.setFieldsValue({ capabilities: DEFAULT_CAPABILITIES });
    }
  }, [editingModel, form, open]);

  const handleFinish = async (values: FormValues) => {
    try {
      if (editingModel) {
        const reqData: UpdateModelRequest = {};
        if (values.name !== editingModel.name) reqData.name = values.name;
        if (values.modelId !== editingModel.modelId) reqData.modelId = values.modelId;
        if (values.providerId !== editingModel.providerId) reqData.providerId = values.providerId;
        const capsChanged =
          values.capabilities.length !== editingModel.capabilities.length ||
          values.capabilities.some((c, i) => c !== editingModel.capabilities[i]);
        if (capsChanged) reqData.capabilities = values.capabilities;
        if (values.contextLength !== editingModel.contextLength) reqData.contextLength = values.contextLength;
        if (values.maxOutputTokens !== editingModel.maxOutputTokens) reqData.maxOutputTokens = values.maxOutputTokens;
        await onUpdate({ data: reqData, id: editingModel.id });
        message.success("模型已更新");
      } else {
        const reqData: CreateModelRequest = {
          capabilities: values.capabilities,
          contextLength: values.contextLength ?? undefined,
          maxOutputTokens: values.maxOutputTokens ?? undefined,
          modelId: values.modelId,
          name: values.name,
          providerId: values.providerId,
        };
        await onCreate(reqData);
        message.success("模型已创建");
      }
      onOpenChange(false);
    } catch (err: unknown) {
      if (err instanceof Error) {
        message.error(err.message);
      }
    }
  };

  const handleTest = async () => {
    if (!testModelConnection) return;
    const providerId: unknown = form.getFieldValue("providerId");
    const modelId: unknown = form.getFieldValue("modelId");
    if (typeof providerId !== "string" || !providerId) {
      message.warning("请先选择供应商");
      return;
    }
    if (typeof modelId !== "string" || !modelId) {
      message.warning("请先输入模型 ID");
      return;
    }
    setTesting(true);
    try {
      const result = await testModelConnection({ modelId, providerId });
      if (result.ok) {
        message.success(result.message);
      } else {
        message.error(result.message);
      }
    } catch (err: unknown) {
      message.error((err as Error).message);
    } finally {
      setTesting(false);
    }
  };

  const providerOptions = providers.map((p) => ({ label: p.name, value: p.id }));

  return (
    <Modal
      confirmLoading={submitting}
      destroyOnHidden
      okText="确定"
      onCancel={onCancel}
      onOk={() => void form.submit()}
      open={open}
      title={editingModel ? "编辑模型" : "新建模型"}
      width={600}
    >
      <Form form={form} layout="vertical" onFinish={(values) => void handleFinish(values)}>
        <Form.Item
          label="模型名称"
          name="name"
          rules={[{ message: "请输入模型名称", required: true, whitespace: true }]}
        >
          <Input placeholder="请输入模型名称" />
        </Form.Item>
        <Form.Item label="所属供应商" name="providerId" rules={[{ message: "请选择供应商", required: true }]}>
          <Select
            loading={providersLoading}
            notFoundContent={getProviderNotFoundContent(providersLoading, providersError)}
            optionFilterProp="label"
            options={providerOptions}
            placeholder="请选择供应商"
            showSearch
            status={providersError ? "error" : undefined}
          />
        </Form.Item>
        <Form.Item
          label="模型 ID"
          name="modelId"
          rules={[{ message: "请输入模型 ID", required: true, whitespace: true }]}
        >
          <Input placeholder="gpt-4o, claude-3-opus-20240229, deepseek-chat 等" />
        </Form.Item>
        <Form.Item label="能力标签" name="capabilities" rules={[{ message: "请至少选择一个能力标签", required: true }]}>
          <Checkbox.Group>
            <Row gutter={[8, 8]}>
              {CAPABILITY_OPTIONS.map((opt) => (
                <Col key={opt.value} md={8} sm={12} xs={24}>
                  <Checkbox value={opt.value}>{opt.label}</Checkbox>
                </Col>
              ))}
            </Row>
          </Checkbox.Group>
        </Form.Item>
        <Row gutter={16}>
          <Col sm={12} xs={24}>
            <Form.Item label="上下文长度" name="contextLength" rules={[positiveIntegerRule("上下文长度")]}>
              <InputNumber min={1} placeholder="可选" precision={0} styles={{ root: { width: "100%" } }} />
            </Form.Item>
          </Col>
          <Col sm={12} xs={24}>
            <Form.Item label="最大输出 Token" name="maxOutputTokens" rules={[positiveIntegerRule("最大输出 Token")]}>
              <InputNumber min={1} placeholder="可选" precision={0} styles={{ root: { width: "100%" } }} />
            </Form.Item>
          </Col>
        </Row>
        {testModelConnection && (
          <Form.Item>
            <Space>
              <Button loading={testing} onClick={() => void handleTest()}>
                测试连接
              </Button>
            </Space>
          </Form.Item>
        )}
      </Form>
    </Modal>
  );
}

function getProviderNotFoundContent(loading: boolean, error: Error | null): string {
  if (loading) return "正在加载供应商";
  if (error) return `供应商加载失败：${error.message}`;
  return "暂无供应商，请先新建供应商";
}

function positiveIntegerRule(label: string) {
  return {
    validator(_: unknown, value: null | number | undefined) {
      if (value === undefined || value === null) return Promise.resolve();
      if (Number.isInteger(value) && value > 0) return Promise.resolve();
      return Promise.reject(new Error(`${label}必须为正整数`));
    },
  };
}
