/**
 * 实例相关 DTOs
 */

import { IsString, IsOptional, IsObject, IsNotEmpty, IsInt, Min, IsEnum, IsUUID } from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';

/**
 * 创建实例 DTO
 */
export class CreateInstanceDto {
  @ApiProperty({
    description: '表单定义 ID',
    example: 'fd-001',
  })
  @IsNotEmpty({ message: '表单定义 ID 不能为空' })
  @IsString()
  formDefinitionId: string;

  @ApiProperty({
    description: '表单数据',
    example: { amount: 5000, reason: '出差报销' },
  })
  @IsNotEmpty({ message: '表单数据不能为空' })
  @IsObject()
  formData: Record<string, any>;

  @ApiPropertyOptional({
    description: '发起人所属部门 ID',
    example: 'dept-001',
  })
  @IsOptional()
  @IsString()
  departmentId?: string;
}

/**
 * 表单实例响应
 */
export class FormInstanceResponse {
  @ApiProperty() id: string;
  @ApiProperty() snapshotId: string;
  @ApiProperty() formDefinitionId: string;
  @ApiProperty() formVersionId: string;
  @ApiProperty() regionId: string;
  @ApiProperty() status: string;
  @ApiProperty() formData: Record<string, any>;
}

/**
 * 流程实例响应
 */
export class ProcessInstanceResponse {
  @ApiProperty() id: string;
  @ApiProperty() processDefinitionId: string;
  @ApiProperty() processVersionId: string;
  @ApiProperty() status: string;
  @ApiProperty() currentNode: string;
}

/**
 * 创建实例响应
 */
export class CreateInstanceResponse {
  @ApiProperty() formInstance: FormInstanceResponse;
  @ApiProperty() processInstance: ProcessInstanceResponse;
  @ApiProperty() createdAt: string;
}

/**
 * 字段访问权限
 */
export class FieldAccess {
  @ApiProperty({
    description: '是否可编辑',
    example: false,
  })
  editable: boolean;

  @ApiProperty({
    description: '是否必填',
    example: false,
  })
  required: boolean;

  @ApiProperty({
    description: '是否隐藏',
    example: false,
  })
  hidden: boolean;
}

/**
 * 字段访问权限响应
 */
export class FieldAccessResponse {
  @ApiProperty() instanceId: string;
  @ApiProperty() currentNodeId: string;
  @ApiProperty() currentNodeName: string;
  @ApiProperty({
    description: '字段访问权限映射',
    example: {
      amount: { editable: false, required: false, hidden: false },
      approvalComment: { editable: true, required: true, hidden: false },
    },
  })
  fieldAccess: Record<string, FieldAccess>;
}

/**
 * 更新实例 DTO
 */
export class UpdateInstanceDto {
  @ApiProperty({
    description: '表单数据',
    example: { amount: 6000, reason: '出差报销-已修改' },
  })
  @IsNotEmpty({ message: '表单数据不能为空' })
  @IsObject()
  formData: Record<string, any>;
}

/**
 * 提交实例 DTO
 */
export class SubmitInstanceDto {
  @ApiPropertyOptional({
    description: '提交备注',
    example: '请审批',
  })
  @IsOptional()
  @IsString()
  comment?: string;

  @ApiPropertyOptional({
    description: '附件 IDs',
    example: ['file-001', 'file-002'],
  })
  @IsOptional()
  attachments?: string[];
}

/**
 * 撤回实例 DTO
 */
export class WithdrawInstanceDto {
  @ApiPropertyOptional({
    description: '撤回原因',
    example: '信息填写有误，需要修改',
  })
  @IsOptional()
  @IsString()
  reason?: string;
}

/**
 * 撤回实例响应
 */
export class WithdrawInstanceResponse {
  @ApiProperty() id: string;
  @ApiProperty() status: string;
  @ApiProperty() withdrawnAt: string;
  @ApiProperty() withdrawnBy: string;
  @ApiPropertyOptional() reason?: string;
  @ApiProperty() message: string;
}

/**
 * 查询我的实例列表 DTO
 */
export class QueryMyInstancesDto {
  @ApiPropertyOptional({
    description: '页码',
    example: 1,
    default: 1,
  })
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  page?: number = 1;

  @ApiPropertyOptional({
    description: '每页数量',
    example: 20,
    default: 20,
  })
  @IsOptional()
  @Type(() => Number)
  @IsInt()
  @Min(1)
  limit?: number = 20;

  @ApiPropertyOptional({
    description: '表单定义 ID 筛选',
    example: 'fd-001',
  })
  @IsOptional()
  @IsString()
  formDefinitionId?: string;

  @ApiPropertyOptional({
    description: '实例状态筛选',
    enum: ['DRAFT', 'SUBMITTED', 'PENDING_APPROVAL', 'APPROVED', 'REJECTED', 'WITHDRAWN', 'CANCELLED'],
    example: 'PENDING_APPROVAL',
  })
  @IsOptional()
  @IsEnum(['DRAFT', 'SUBMITTED', 'PENDING_APPROVAL', 'APPROVED', 'REJECTED', 'WITHDRAWN', 'CANCELLED'])
  status?: string;
}

/**
 * 预览审批流程 DTO
 */
export class PreviewProcessDto {
  @ApiProperty({
    description: '表单数据',
    example: { amount: 5000, reason: '出差报销' },
  })
  @IsNotEmpty({ message: '表单数据不能为空' })
  @IsObject()
  formData: Record<string, any>;

  @ApiPropertyOptional({
    description: '提交部门ID（多部门用户必填）',
    example: 'dept-001',
  })
  @IsOptional()
  @IsString()
  departmentId?: string;

  @ApiPropertyOptional({
    description: '发起人ID（用于计算审批人，如果不提供则使用当前登录用户）',
    example: 'f4f12524-7b65-4e0c-a356-a6d7c1945fc0',
  })
  @IsOptional()
  @IsUUID('4', { message: '发起人ID格式不正确' })
  initiatorId?: string;
}

/**
 * 审批人信息
 */
export class ApproverInfo {
  @ApiProperty({ description: '用户 ID' })
  id: string;

  @ApiProperty({ description: '用户姓名' })
  name: string;

  @ApiPropertyOptional({ description: '头像 URL' })
  avatar?: string;

  @ApiPropertyOptional({ description: '类型', enum: ['user', 'role', 'department'] })
  type?: string;
}

/**
 * 带审批人的流程节点
 */
export class ProcessNodeWithApprovers {
  @ApiProperty({ description: '节点 ID' })
  id: string;

  @ApiProperty({ description: '节点类型', enum: ['START', 'USER_TASK', 'END', 'GATEWAY', 'CC'] })
  type: string;

  @ApiProperty({ description: '节点名称' })
  name: string;

  @ApiProperty({ description: '审批人列表', type: [ApproverInfo] })
  approvers: ApproverInfo[];

  @ApiPropertyOptional({ description: '审批模式', enum: ['OR', 'AND', 'SEQUENTIAL'] })
  approvalMode?: string;

  @ApiPropertyOptional({ description: '节点配置' })
  config?: Record<string, any>;
}

/**
 * 预览审批流程响应
 */
export class PreviewProcessResponse {
  @ApiProperty({
    description: '流程模型',
    type: 'object',
    properties: {
      nodes: { type: 'array', items: { $ref: '#/components/schemas/ProcessNodeWithApprovers' } },
      edges: { type: 'array' },
    },
  })
  model: {
    nodes: ProcessNodeWithApprovers[];
    edges: any[];
  };

  @ApiProperty({
    description: '发起人信息',
    type: 'object',
    properties: {
      id: { type: 'string' },
      name: { type: 'string' },
      avatar: { type: 'string' },
    },
  })
  initiator: {
    id: string;
    name: string;
    avatar?: string;
  };
}
