/**
 * 实例服务
 * 
 * 管理表单实例的创建和字段权限
 */

import { Injectable, Logger, Inject, forwardRef } from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { FormInstanceService } from '@engines/form/form-engine/services/form-instance.service';
import { FormBusinessKeyService } from '@engines/form/form-engine/services/form-business-key.service';
import { ApprovalService } from '@engines/approval/approval.service';
import { isAdministrator, hasPermissionCode } from '@common/utils/role-check.util';
import type { CurrentUserPayload } from '@common/decorators/current-user.decorator';
import {
  CreateInstanceDto,
  CreateInstanceResponse,
  FieldAccessResponse,
  FieldAccess,
  UpdateInstanceDto,
  SubmitInstanceDto,
  QueryMyInstancesDto,
  WithdrawInstanceDto,
  WithdrawInstanceResponse,
} from '../dto/instance.dto';
import {
  FormNotFoundException,
  FormDefinitionDisabledException,
  FormDefinitionArchivedException,
  NoActiveSnapshotException,
  InstanceNotFoundException,
  FormDataInvalidException,
  TransactionFailedException,
  ForbiddenOperationException,
  InvalidStatusException,
  WithdrawFailedException,
} from '../exceptions';
import { RegionId } from '../decorators/region.decorator';
import { safeFindUnique } from '../utils/prisma-error-handler';

/**
 * 实例可见性判定接受的 user 形态。
 * 兼容 CurrentUser() 完整 payload（含 roles / permissions / organizationRoles）。
 */
export interface AccessUser {
  userId: string;
  roles?: string[];
  permissions?: string[];
  organizationRoles?: Record<string, string[]>;
}

@Injectable()
export class InstanceService {
  private readonly logger = new Logger(InstanceService.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly formInstanceService: FormInstanceService,
    private readonly businessKeyService: FormBusinessKeyService,
    @Inject(forwardRef(() => ApprovalService))
    private readonly approvalService: ApprovalService,
  ) {}

  // ============================================
  // 1. 创建实例（聚合）
  // ============================================

  async create(
    dto: CreateInstanceDto,
    regionId: RegionId,
    userId: string,
  ): Promise<CreateInstanceResponse> {
    this.logger.log(
      `Creating instance for form ${dto.formDefinitionId} in region ${regionId}`,
    );

    // 1. 获取表单定义
    const form = await safeFindUnique(() =>
      this.prisma.formDefinition.findUnique({
        where: { id: dto.formDefinitionId },
        include: {
          organization: {
            include: {
              organizationRegions: {
                include: {
                  region: true, // v2.0: 修复为 organizationRegions
                },
              },
            },
          },
        },
      }),
    );

    if (!form) {
      throw new FormNotFoundException(dto.formDefinitionId, regionId);
    }

    // 2. 验证区域访问
    this.validateRegionAccess(form, regionId);

    // 3. 验证表单定义状态
    if (form.status === 'ARCHIVED') {
      throw new FormDefinitionArchivedException(dto.formDefinitionId);
    }

    // 检查是否已禁用
    if (form.status === 'DISABLED') {
      throw new FormDefinitionDisabledException(dto.formDefinitionId);
    }

    // 4. 获取 ACTIVE 快照
    const activeSnapshot = await this.prisma.releaseSnapshot.findFirst({
      where: {
        formDefinitionId: dto.formDefinitionId,
        status: 'ACTIVE',
      },
    });

    if (!activeSnapshot) {
      throw new NoActiveSnapshotException(dto.formDefinitionId, regionId);
    }

    // 5. 获取快照绑定的表单版本
    const formVersion = await this.prisma.formVersion.findUnique({
      where: { id: activeSnapshot.formVersionId },
    });

    if (!formVersion) {
      throw new NoActiveSnapshotException(dto.formDefinitionId, regionId);
    }

    // 6. 验证表单数据
    this.validateFormData(dto.formData, formVersion.schema as any);

    // 7. 执行初始化钩子（预处理）
    const processedFormData = await this.applyInitializationHooks(
      dto.formData,
      formVersion,
      userId,
      regionId,
    );

    // 8. 创建实例（事务）
    // 注意：创建时为 DRAFT 状态，需要调用 submitInstance 才会启动审批流程
    try {
      return await this.prisma.$transaction(async (tx) => {
        // 生成业务单号
        const businessKey = await this.businessKeyService.generateBusinessKey(form.key);

        // 创建表单实例（草稿状态）
        const formInstance = await tx.formInstance.create({
          data: {
            formDefinitionId: form.id,
            formVersionId: formVersion.id,
            snapshotId: activeSnapshot.id, // ✅ 修复：绑定真实的快照 ID
            formKey: form.key,
            formVersion: formVersion.version,
            businessKey,
            regionId,
            data: processedFormData,
            status: 'DRAFT', // 创建时为草稿状态
            createdBy: userId,
            updatedBy: userId,
            // submittedBy 和 submittedAt 在 submit 时才填充
          },
        });

        // 注意：审批流程实例在 submitInstance 时创建，而不是在 create 时创建
        // 这样用户可以先保存草稿，填写完整后再提交

        this.logger.log(`Instance created as DRAFT: ${formInstance.id}, bound to snapshot: ${activeSnapshot.id}`);

        return {
          formInstance: {
            id: formInstance.id,
            snapshotId: activeSnapshot.id, // ✅ 返回真实的快照 ID
            formDefinitionId: form.id,
            formVersionId: formVersion.id,
            regionId,
            status: formInstance.status,
            formData: processedFormData,
          },
          processInstance: {
            id: '',
            processDefinitionId: activeSnapshot.processDefinitionId || '',
            processVersionId: activeSnapshot.processVersionId || '',
            status: 'NOT_STARTED', // 审批流程在提交时才启动
            currentNode: '',
          },
          createdAt: formInstance.createdAt.toISOString(),
        };
      });
    } catch (error) {
      this.logger.error(`Failed to create instance: ${error.message}`);
      throw new TransactionFailedException('createInstance', error.message);
    }
  }

  // ============================================
  // 2. 获取当前节点字段权限
  // ============================================

  async getFieldAccess(
    instanceId: string,
    regionId: RegionId,
    user: AccessUser,
  ): Promise<FieldAccessResponse> {
    // 获取表单实例
    const formInstance = await safeFindUnique(() =>
      this.prisma.formInstance.findUnique({
        where: { id: instanceId },
        include: {
          version: true,
          definition: true,
        },
      }),
    );

    if (!formInstance) {
      throw new InstanceNotFoundException(instanceId, regionId);
    }

    // 验证区域
    if (formInstance.regionId && formInstance.regionId !== regionId) {
      throw new InstanceNotFoundException(instanceId, regionId);
    }

    await this.assertInstanceVisibility(formInstance, user);

    // 获取当前流程节点
    let currentNode: { id: string; name: string } | null = null;
    let nodeConfig: any = null;

    if (formInstance.approvalInstanceId) {
      const approvalInstance = await this.prisma.approvalInstance.findUnique({
        where: { id: formInstance.approvalInstanceId },
        include: {
          version: true,
        },
      });

      if (approvalInstance) {
        const nodeId = approvalInstance.currentNodeId || 'unknown';
        const nodeName = approvalInstance.currentNode || '未知节点';
        currentNode = {
          id: nodeId,
          name: nodeName,
        };

        // 从流程模型中获取节点配置
        const processModel = approvalInstance.version.processModel as any;
        if (processModel?.nodes) {
          const node = processModel.nodes.find(
            (n: any) => n.id === nodeId,
          );
          if (node) {
            nodeConfig = node.config || {};
            currentNode.name = node.name || currentNode.name;
          }
        }
      }
    }

    // 构建字段访问权限
    const schema = formInstance.version.schema as any;
    const fieldAccess: Record<string, FieldAccess> = {};

    if (schema?.properties) {
      const editableFields = nodeConfig?.editableFields || [];
      const requiredFields = nodeConfig?.requiredFields || [];
      const hiddenFields = nodeConfig?.hiddenFields || [];

      for (const fieldKey of Object.keys(schema.properties)) {
        fieldAccess[fieldKey] = {
          editable: editableFields.includes(fieldKey),
          required: requiredFields.includes(fieldKey),
          hidden: hiddenFields.includes(fieldKey),
        };
      }
    }

    return {
      instanceId,
      currentNodeId: currentNode?.id || 'unknown',
      currentNodeName: currentNode?.name || '未知节点',
      fieldAccess,
    };
  }

  // ============================================
  // 3. 获取我的实例列表
  // ============================================

  async getMyInstances(
    query: QueryMyInstancesDto,
    regionId: RegionId,
    userId: string,
  ) {
    const { page = 1, limit = 20, formDefinitionId, status } = query;
    const skip = (page - 1) * limit;

    const where: any = {
      regionId,
      createdBy: userId,
      deletedAt: null,
    };

    if (formDefinitionId) {
      where.formDefinitionId = formDefinitionId;
    }

    if (status) {
      where.status = status;
    }

    const [instances, total] = await Promise.all([
      this.prisma.formInstance.findMany({
        where,
        include: {
          definition: {
            select: {
              id: true,
              key: true,
              slug: true,
              name: true,
              category: true,
            },
          },
          version: {
            select: {
              id: true,
              version: true,
            },
          },
        },
        orderBy: { createdAt: 'desc' },
        skip,
        take: limit,
      }),
      this.prisma.formInstance.count({ where }),
    ]);

    return {
      items: instances.map((instance) => ({
        id: instance.id,
        formDefinitionId: instance.formDefinitionId,
        formVersionId: instance.formVersionId,
        businessKey: instance.businessKey,
        status: instance.status,
        form: instance.definition,
        version: instance.version.version,
        data: instance.data,
        createdAt: instance.createdAt.toISOString(),
        updatedAt: instance.updatedAt.toISOString(),
        submittedAt: instance.submittedAt?.toISOString(),
      })),
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  // ============================================
  // 4. 获取实例详情
  // ============================================

  async getInstance(
    instanceId: string,
    regionId: RegionId,
    user: AccessUser,
  ) {
    const userId = user.userId;
    const instance = await safeFindUnique(() =>
      this.prisma.formInstance.findUnique({
        where: { id: instanceId },
        include: {
          definition: true,
          version: true,
          creator: {
            select: {
              id: true,
              username: true,
              displayName: true,
              email: true,
            },
          },
          submitter: {
            select: {
              id: true,
              username: true,
              displayName: true,
              email: true,
            },
          },
        },
      }),
    );

    if (!instance) {
      throw new InstanceNotFoundException(instanceId, regionId);
    }

    // 验证区域和权限
    if (instance.regionId !== regionId) {
      throw new InstanceNotFoundException(instanceId, regionId);
    }

    // 可见性门：申请人 / 提交人 / 当前或历史处理人 / form:admin / Administrator 才可见
    // 不可见返回 404 而非 403，避免泄露实例存在性
    await this.assertInstanceVisibility(instance, user);

    return {
      id: instance.id,
      formDefinitionId: instance.formDefinitionId,
      formVersionId: instance.formVersionId,
      businessKey: instance.businessKey,
      regionId: instance.regionId,
      status: instance.status,
      approvalStatus: instance.approvalStatus,
      data: instance.data,
      definition: instance.definition,
      version: instance.version,
      createdBy: instance.creator,
      submittedBy: instance.submitter,
      createdAt: instance.createdAt.toISOString(),
      updatedAt: instance.updatedAt.toISOString(),
      submittedAt: instance.submittedAt?.toISOString(),
      approvalStartTime: instance.approvalStartTime?.toISOString(),
      approvalEndTime: instance.approvalEndTime?.toISOString(),
    };
  }

  // ============================================
  // 5. 更新实例
  // ============================================

  async updateInstance(
    instanceId: string,
    dto: UpdateInstanceDto,
    regionId: RegionId,
    userId: string,
  ) {
    // 获取实例
    const instance = await safeFindUnique(() =>
      this.prisma.formInstance.findUnique({
        where: { id: instanceId },
        include: {
          version: true,
        },
      }),
    );

    if (!instance) {
      throw new InstanceNotFoundException(instanceId, regionId);
    }

    // 验证区域
    if (instance.regionId !== regionId) {
      throw new InstanceNotFoundException(instanceId, regionId);
    }

    // 验证是否有权限修改（只有创建者可以修改草稿）
    if (instance.createdBy !== userId) {
      throw new Error('无权修改此实例');
    }

    // 验证状态（只有草稿、驳回和已撤回状态可以修改）
    if (instance.status !== 'DRAFT' && instance.status !== 'REJECTED' && instance.status !== 'WITHDRAWN') {
      throw new InvalidStatusException(instance.id, instance.status, 'update');
    }

    // 验证表单数据
    this.validateFormData(dto.formData, instance.version.schema as any);

    // 更新实例
    const updated = await this.prisma.formInstance.update({
      where: { id: instanceId },
      data: {
        data: dto.formData,
        updatedAt: new Date(),
      },
    });

    return {
      id: updated.id,
      status: updated.status,
      data: updated.data,
      updatedAt: updated.updatedAt.toISOString(),
    };
  }

  // ============================================
  // 6. 提交实例
  // ============================================

  async submitInstance(
    instanceId: string,
    dto: SubmitInstanceDto,
    regionId: RegionId,
    userId: string,
  ) {
    // 获取实例
    const instance = await safeFindUnique(() =>
      this.prisma.formInstance.findUnique({
        where: { id: instanceId },
        include: {
          definition: true,
          version: true,
        },
      }),
    );

    if (!instance) {
      throw new InstanceNotFoundException(instanceId, regionId);
    }

    // 验证权限
    if (instance.createdBy !== userId) {
      throw new Error('无权提交此实例');
    }

    // 验证状态：只有 DRAFT、REJECTED、WITHDRAWN 可以提交
    if (instance.status !== 'DRAFT' && instance.status !== 'REJECTED' && instance.status !== 'WITHDRAWN') {
      throw new InvalidStatusException(instance.id, instance.status, 'submit');
    }

    // 验证表单数据
    this.validateFormData(instance.data as any, instance.version.schema as any);

    const approvalProcessKey = instance.definition.approvalProcessKey;
    const needsApproval = Boolean(instance.definition.requiresApproval && approvalProcessKey);

    // 在事务中更新实例状态
    const result = await this.prisma.$transaction(async (tx) => {
      // 1. 更新实例状态（需要审批 -> PENDING_APPROVAL，否则 -> SUBMITTED）
      const updated = await tx.formInstance.update({
        where: { id: instanceId },
        data: {
          status: needsApproval ? 'PENDING_APPROVAL' : 'SUBMITTED',
          submittedAt: new Date(),
          submittedBy: userId,
        },
      });

      return updated;
    });

    // 2. 如果需要审批，启动审批流程（在事务外）
    let approvalInstanceId: string | undefined;
    if (needsApproval && approvalProcessKey) {
      try {
        // 调用审批服务启动流程
        // ⚠️ 设计决策 TD-6: FormInstance.data 是唯一数据源
        // variables 中不存储 formData 副本，只存储流程上下文信息
        // 审批引擎需要表单数据时，通过 businessId 关联查询 FormInstance
        const approvalResult = await this.approvalService.startApproval(
          {
            processDefinitionKey: approvalProcessKey,
            businessType: 'FORM_INSTANCE',  // 固定值，符合审批引擎设计规范
            businessId: instance.id,
            title: `${instance.definition.name} - ${instance.businessKey}`,
            variables: {
              formKey: instance.formKey,      // 表单标识（用于条件判断）
              formDefinitionId: instance.formDefinitionId,
              formVersionId: instance.formVersionId,
              businessKey: instance.businessKey,
              submitterId: userId,
              // ⚠️ 不传递 formData，避免数据冗余
              // 需要表单数据时，通过 businessId 查询 FormInstance.data
            },
          },
          userId,
        );

        approvalInstanceId = approvalResult.instanceId;

        // 3. 更新表单实例关联审批流程
        await this.prisma.formInstance.update({
          where: { id: instance.id },
          data: {
            approvalInstanceId: approvalResult.instanceId,
            approvalStatus: 'RUNNING',
            approvalStartTime: new Date(),
          },
        });

        this.logger.log(
          `Instance ${instanceId} submitted, approval workflow started: ${approvalResult.instanceId}`,
        );
      } catch (error) {
        this.logger.error(`Failed to start approval workflow: ${error.message}`);
        this.logger.error(error.stack);
        // 审批流程启动失败，但表单实例已提交，记录错误但不抛出异常
        // TODO: 可以考虑实现重试机制或管理员介入
      }
    }

    return {
      id: result.id,
      status: result.status,
      submittedAt: result.submittedAt?.toISOString(),
      approvalProcessId: approvalInstanceId,
      message: approvalInstanceId ? '提交成功，审批流程已启动' : '提交成功',
    };
  }

  // ============================================
  // 7. 撤回实例（用户主动撤回）
  // ============================================

  async withdrawInstance(
    instanceId: string,
    dto: WithdrawInstanceDto,
    regionId: RegionId,
    userId: string,
  ): Promise<WithdrawInstanceResponse> {
    this.logger.log(`Withdrawing instance ${instanceId} by user ${userId}`);

    // 获取实例
    const instance = await safeFindUnique(() =>
      this.prisma.formInstance.findUnique({
        where: { id: instanceId },
        include: {
          definition: true,
        },
      }),
    );

    if (!instance) {
      throw new InstanceNotFoundException(instanceId, regionId);
    }

    // 验证区域
    if (instance.regionId !== regionId) {
      throw new InstanceNotFoundException(instanceId, regionId);
    }

    // 验证权限：只有发起人可以撤回
    if (instance.createdBy !== userId) {
      throw new ForbiddenOperationException('withdraw', '只有发起人可以撤回');
    }

    // 验证状态：只有 PENDING_APPROVAL 状态可以撤回
    if (instance.status !== 'PENDING_APPROVAL') {
      throw new InvalidStatusException(instanceId, instance.status, 'withdraw');
    }

    // 更新实例状态为 WITHDRAWN
    const result = await this.prisma.$transaction(async (tx) => {
      const updated = await tx.formInstance.update({
        where: { id: instanceId },
        data: {
          status: 'WITHDRAWN',
          approvalStatus: 'WITHDRAWN',
          approvalEndTime: new Date(),
          updatedBy: userId,
          updatedAt: new Date(),
        },
      });

      return updated;
    });

    // 如果有审批流程实例，通知审批引擎撤回流程（终止 Temporal workflow）
    // FormInstance.createdBy 在 submit 时也作为 ApprovalInstance.initiatorId 写入，
    // 这里 userId 已经过 createdBy 校验，必然等于 initiatorId，可以直接调 withdraw。
    if (instance.approvalInstanceId) {
      try {
        await this.approvalService.withdraw(
          instance.approvalInstanceId,
          { reason: dto.reason ?? '表单实例已撤回' },
          userId,
        );
        this.logger.log(`Approval process ${instance.approvalInstanceId} withdrawn`);
      } catch (error) {
        this.logger.error(
          `Failed to withdraw approval process ${instance.approvalInstanceId}: ${error.message}`,
          error.stack,
        );
        // 不抛出异常：FormInstance.status=WITHDRAWN 已落库，
        // 审批端撤回失败由日志/告警兜底，避免单边失败导致整个 API 报错
      }
    }

    this.logger.log(`Instance ${instanceId} withdrawn by ${userId}`);

    return {
      id: result.id,
      status: 'WITHDRAWN',
      withdrawnAt: result.updatedAt.toISOString(),
      withdrawnBy: userId,
      reason: dto.reason,
      message: '实例已撤回',
    };
  }

  // ============================================
  // 8. 删除实例（软删除）
  // ============================================

  async deleteInstance(
    instanceId: string,
    regionId: RegionId,
    userId: string,
  ) {
    // 获取实例
    const instance = await safeFindUnique(() =>
      this.prisma.formInstance.findUnique({
        where: { id: instanceId },
      }),
    );

    if (!instance) {
      throw new InstanceNotFoundException(instanceId, regionId);
    }

    // 验证权限
    if (instance.createdBy !== userId) {
      throw new Error('无权删除此实例');
    }

    // 验证状态（只能删除草稿、被驳回或已撤回的实例）
    if (instance.status !== 'DRAFT' && instance.status !== 'REJECTED' && instance.status !== 'WITHDRAWN') {
      throw new InvalidStatusException(instance.id, instance.status, 'delete');
    }

    // 软删除
    await this.prisma.formInstance.update({
      where: { id: instanceId },
      data: {
        deletedAt: new Date(),
      },
    });

    this.logger.log(`Instance ${instanceId} deleted by ${userId}`);

    return {
      id: instanceId,
      message: '删除成功',
    };
  }

  // ============================================
  // 私有辅助方法
  // ============================================

  /**
   * 实例可见性判定（GET 路径专用，不覆盖写操作权限）。
   *
   * 命中以下任一条件视为可见，否则按"实例不存在"返回 404 避免泄露存在性：
   *   1. 系统 Administrator
   *   2. 持有 form:admin 权限码（含 form:* / *:*）
   *   3. 申请人（createdBy）/ 提交人（submittedBy）
   *   4. 当前或历史审批处理人（ApprovalTask.assignee 或 ApprovalTaskLog.operatorId）
   *
   * 暂不覆盖：
   *   - CC 抄送：FormInstance schema 暂无 ccUserIds 字段（待后续模型扩展）
   *   - 跨组织 / 跨部门：列表查询由 DataScope 兜底；详情这里不再多做
   */
  private async assertInstanceVisibility(
    instance: { id: string; createdBy: string; submittedBy?: string | null; approvalInstanceId?: string | null; regionId?: string | null },
    user: AccessUser,
  ): Promise<void> {
    if (isAdministrator(user)) return;
    if (hasPermissionCode(user.permissions, 'form:admin')) return;
    if (instance.createdBy === user.userId) return;
    if (instance.submittedBy && instance.submittedBy === user.userId) return;

    if (instance.approvalInstanceId) {
      const [activeTask, log] = await Promise.all([
        this.prisma.approvalTask.findFirst({
          where: { instanceId: instance.approvalInstanceId, assignee: user.userId },
          select: { id: true },
        }),
        this.prisma.approvalTaskLog.findFirst({
          where: { instanceId: instance.approvalInstanceId, operatorId: user.userId },
          select: { id: true },
        }),
      ]);
      if (activeTask || log) return;
    }

    throw new InstanceNotFoundException(instance.id, instance.regionId ?? 'unknown');
  }

  private validateRegionAccess(form: any, regionId: RegionId) {
    // 平台级表单：所有区域可访问
    if (!form.organizationId) {
      return;
    }
    
    // 组织专属表单：检查组织是否在当前区域运营
    if (form.organization && form.organization.organizationRegions) {
      // v2.0: 使用 organizationRegions
      const orgRegionCodes = form.organization.organizationRegions
        .map((r: any) => r.region?.code)
        .filter(Boolean);
      
      if (!orgRegionCodes.includes(regionId)) {
        this.logger.warn(`[validateRegionAccess] 表单 ${form.id} 的组织区域 [${orgRegionCodes.join(', ')}] 不包含用户区域 ${regionId}`);
        throw new FormNotFoundException(form.id, regionId);
      }
      
      this.logger.debug(`[validateRegionAccess] 表单 ${form.id} 区域校验通过: ${regionId} in [${orgRegionCodes.join(', ')}]`);
    }
  }

  private validateFormData(data: Record<string, any>, schema: any) {
    // 基础验证：检查必填字段
    const errors: any[] = [];

    if (schema?.required && Array.isArray(schema.required)) {
      for (const field of schema.required) {
        if (data[field] === undefined || data[field] === null || data[field] === '') {
          errors.push({
            field,
            rule: 'required',
            message: `字段 ${field} 是必填的`,
          });
        }
      }
    }

    // 类型验证
    if (schema?.properties) {
      for (const [key, prop] of Object.entries(schema.properties as Record<string, any>)) {
        if (data[key] !== undefined && data[key] !== null) {
          const expectedType = prop.type;
          const actualValue = data[key];

          if (expectedType === 'number' && typeof actualValue !== 'number') {
            errors.push({
              field: key,
              rule: 'type',
              message: `字段 ${key} 应为数字类型`,
              value: actualValue,
            });
          }

          if (expectedType === 'string' && typeof actualValue !== 'string') {
            errors.push({
              field: key,
              rule: 'type',
              message: `字段 ${key} 应为字符串类型`,
              value: actualValue,
            });
          }
        }
      }
    }

    if (errors.length > 0) {
      throw new FormDataInvalidException(errors);
    }
  }

  private async applyInitializationHooks(
    formData: Record<string, any>,
    formVersion: any,
    userId: string,
    regionId: RegionId,
  ): Promise<Record<string, any>> {
    const processedData = { ...formData };

    // 1. 默认值注入
    const schema = formVersion.schema as any;
    if (schema?.properties) {
      for (const [key, prop] of Object.entries(schema.properties as Record<string, any>)) {
        if (processedData[key] === undefined && prop.default !== undefined) {
          processedData[key] = prop.default;
        }
      }
    }

    // 2. 系统字段填充
    const user: any = await this.prisma.user.findUnique({
      where: { id: userId },
      include: {
        departmentMemberships: {
          where: { isPrimary: true },
          include: { department: true },
        },
      } as any,
    });

    if (user) {
      // 自动填充发起人信息
      if (processedData['applicant'] === undefined) {
        processedData['_applicant'] = {
          id: user.id,
          name: user.displayName || user.username,
        };
      }

      const primaryDept = user.departmentMemberships?.[0]?.department;
      if (primaryDept && processedData['applicantDept'] === undefined) {
        processedData['_applicantDept'] = {
          id: primaryDept.id,
          name: primaryDept.name,
        };
      }
    }

    // 3. 时间戳填充
    processedData['_applyTime'] = new Date().toISOString();

    // 4. 区域信息
    processedData['_regionId'] = regionId;

    return processedData;
  }
}
