/**
 * form-management 集成测试通用 helper
 *
 * 提供 form definition / version / instance 的快速 fixture 注入，
 * 命名统一带 `t_` 前缀，cleanupByPrefix 自动清理。
 */

import * as bcrypt from 'bcrypt';
import { PrismaService } from '@/core/database/prisma/prisma.service';

export interface TestFormDefinitionOptions {
  prefix: string;
  createdBy: string;
  requiresApproval?: boolean;
  approvalProcessKey?: string;
  schema?: Record<string, unknown>;
}

export interface TestFormDefinition {
  definitionId: string;
  versionId: string;
  formKey: string;
  formSlug: string;
  formVersion: number;
}

/**
 * 直接通过 prisma 创建测试用 form definition + 默认 published version。
 *
 * 不走 form-management API 是因为：
 *  - API 创建时附带 review/publish 流程，对纯状态机测试是 noise
 *  - 直接 prisma 写入更快，且 cleanupByPrefix 通过 name/slug 前缀仍可清理
 */
export async function createTestFormDefinition(
  prisma: PrismaService,
  opts: TestFormDefinitionOptions,
): Promise<TestFormDefinition> {
  const { prefix, createdBy, requiresApproval = false, approvalProcessKey } = opts;
  const schema = opts.schema ?? {
    type: 'object',
    required: [],
    properties: {
      amount: { type: 'number', title: '金额' },
      reason: { type: 'string', title: '事由' },
    },
  };

  const slug = `${prefix}_form_${Date.now()}`;
  const key = slug;
  const name = `${prefix}_FormDef_${Date.now()}`;

  const def = await prisma.formDefinition.create({
    data: {
      key,
      slug,
      name,
      category: 'TEST',
      defaultLocale: 'zh-CN',
      supportedLocales: ['zh-CN'],
      latestVersion: 1,
      status: 'PUBLISHED',
      requiresApproval,
      approvalProcessKey: approvalProcessKey ?? null,
      createdBy,
    },
  });

  const version = await prisma.formVersion.create({
    data: {
      definitionId: def.id,
      version: 1,
      schema: schema as any,
      nameI18n: { 'zh-CN': name } as any,
      isDefault: true,
      status: 'PUBLISHED',
      publishedAt: new Date(),
      createdBy,
    },
  });

  // 创建 ACTIVE release snapshot — instance.create 必备前置条件
  await prisma.releaseSnapshot.create({
    data: {
      formDefinitionId: def.id,
      formVersionId: version.id,
      status: 'ACTIVE',
      versionName: 'v1',
      submittedBy: createdBy,
      submittedAt: new Date(),
      publishedBy: createdBy,
      publishedAt: new Date(),
    },
  });

  return {
    definitionId: def.id,
    versionId: version.id,
    formKey: key,
    formSlug: slug,
    formVersion: 1,
  };
}

/**
 * 生成符合 UUID v4 格式的占位 approvalInstanceId，用于不需要真实 ApprovalInstance
 * 的状态机测试（FormInstance.approvalInstanceId 字段是 UUID 类型，但本身没有 FK）。
 */
export function fakeApprovalInstanceId(): string {
  const tail = Date.now().toString().padStart(12, '0').slice(0, 12);
  return `00000000-0000-4000-8000-${tail}`;
}

/**
 * 创建仅持 form:use 权限的普通表单用户（非 Administrator），用于 RBAC 可见性测试。
 *
 * createAdminUser 默认绑 Administrator 角色 → isAdministrator() 返回 true 直接绕过可见性门，
 * 无法验证非管理员用户的访问拒绝路径。
 *
 * 该 helper 会按需 upsert 'TestFormUser' 角色（仅 form:use）+ 'form:use' 权限。
 */
let _cachedFormUserRoleId: string | null = null;
export async function createPlainFormUser(
  prisma: PrismaService,
  overrides: { username: string; email: string; password: string; displayName?: string },
): Promise<{ id: string; username: string }> {
  if (!_cachedFormUserRoleId) {
    const role = await prisma.role.upsert({
      where: { code: 'TestFormUser' },
      create: {
        code: 'TestFormUser',
        name: 'Test Form User',
        description: 'L1 RBAC test fixture — form:use only',
        isBuiltIn: false,
        enabled: true,
      },
      update: {},
    });
    const perm = await prisma.permission.upsert({
      where: { resource_action: { resource: 'form', action: 'use' } },
      create: { resource: 'form', action: 'use', module: 'form-management', isBuiltIn: true },
      update: {},
    });
    await prisma.rolePermission.upsert({
      where: { roleId_permissionId: { roleId: role.id, permissionId: perm.id } },
      create: { roleId: role.id, permissionId: perm.id },
      update: {},
    });
    _cachedFormUserRoleId = role.id;
  }

  const testOrg = await prisma.organization.upsert({
    where: { code: 'TEST_ADMIN_ORG' },
    create: { code: 'TEST_ADMIN_ORG', name: 'Test Admin Organization', status: 'ACTIVE' },
    update: {},
  });

  const passwordHash = await bcrypt.hash(overrides.password, 10);
  const user = await prisma.user.create({
    data: {
      username: overrides.username,
      email: overrides.email,
      displayName: overrides.displayName ?? overrides.username,
      status: 'ACTIVE',
      source: 'LOCAL',
      defaultRegion: 'CN',
      passwordHash,
    },
  });

  await prisma.userRole.create({
    data: {
      userId: user.id,
      roleId: _cachedFormUserRoleId,
      organizationId: testOrg.id,
    },
  });

  return { id: user.id, username: user.username };
}

/**
 * form-management 测试套件的标准清理：按依赖序删除本套件造的 form 数据。
 *
 * 显式 deleteMany 是因为 cleanupByPrefix 用 `session_replication_role=replica`
 * 在 Prisma 连接池下不可靠（详见 .learnings/2026-05-01-l1-test-form-management-patterns.md）。
 * 同时清掉 t_wf_ 前缀的 ApprovalInstance（withdraw 链路可能造的）。
 */
export async function cleanupFormManagementTestData(prisma: PrismaService) {
  const targetDefs = await prisma.formDefinition.findMany({
    where: { slug: { startsWith: 't_' } },
    select: { id: true },
  });
  const defIds = targetDefs.map((d) => d.id);
  await prisma.$transaction(async (tx) => {
    await tx.formInstance.deleteMany({ where: { businessKey: { startsWith: 't_' } } });
    if (defIds.length > 0) {
      await tx.releaseSnapshot.deleteMany({ where: { formDefinitionId: { in: defIds } } });
      await tx.formVersion.deleteMany({ where: { definitionId: { in: defIds } } });
      await tx.formDefinition.deleteMany({ where: { id: { in: defIds } } });
    }
    // approval 链条：先按 versionId 反查 ApprovalInstance（cascade 会清掉 Node / Task / Log），
    // 再删 ApprovalVersion / ApprovalDefinition，避免 FK 约束
    const apDefIds = (
      await tx.approvalDefinition.findMany({
        where: { key: { startsWith: 't_apr_' } },
        select: { id: true },
      })
    ).map((d) => d.id);
    if (apDefIds.length > 0) {
      const versionIds = (
        await tx.approvalVersion.findMany({
          where: { definitionId: { in: apDefIds } },
          select: { id: true },
        })
      ).map((v) => v.id);
      if (versionIds.length > 0) {
        await tx.approvalInstance.deleteMany({ where: { versionId: { in: versionIds } } });
      }
      await tx.approvalDefinition.deleteMany({ where: { id: { in: apDefIds } } });
    }
    // 兜底清掉历史 t_wf_ 前缀（旧测试模式遗留的 ApprovalInstance）
    await tx.approvalInstance.deleteMany({ where: { workflowId: { startsWith: 't_wf_' } } });
  });
}

/**
 * 造最小可用的 ApprovalInstance + Node + Task 三件套，用于测试可见性 / 处理人查询。
 * 跳过 Temporal worker，仅满足外键和 assertInstanceVisibility 需要。
 */
export async function createMinimalApprovalInstance(
  prisma: PrismaService,
  opts: {
    approvalInstanceId: string;
    formInstanceId: string;
    formBusinessKey: string;
    initiatorId: string;
    suffix: string;
    assigneeUserId?: string;
    historyOperatorIds?: string[];
  },
) {
  const def = await prisma.approvalDefinition.create({
    data: {
      key: `t_apr_${opts.suffix}`,
      name: `t_apr_def_${opts.suffix}`,
      category: 'TEST',
      createdBy: opts.initiatorId,
    },
  });
  const version = await prisma.approvalVersion.create({
    data: {
      definitionId: def.id,
      version: 1,
      name: `t_apr_ver_${opts.suffix}`,
      processModel: { nodes: [] } as any,
    },
  });
  await prisma.approvalInstance.create({
    data: {
      id: opts.approvalInstanceId,
      versionId: version.id,
      businessType: 'FORM_INSTANCE',
      businessId: opts.formInstanceId,
      businessKey: opts.formBusinessKey,
      workflowId: `t_wf_${opts.suffix}`,
      workflowRunId: 't_run',
      initiatorId: opts.initiatorId,
    },
  });
  const node = await prisma.approvalNodeInstance.create({
    data: {
      instanceId: opts.approvalInstanceId,
      nodeId: `t_node_${opts.suffix}`,
      nodeName: 't_node',
      nodeType: 'USER_TASK',
      assignees: opts.assigneeUserId ? [opts.assigneeUserId] : [],
    },
  });
  const task = await prisma.approvalTask.create({
    data: {
      instanceId: opts.approvalInstanceId,
      nodeInstanceId: node.id,
      name: `t_task_${opts.suffix}`,
      assignee: opts.assigneeUserId ?? null,
      status: opts.assigneeUserId ? 'CREATED' : 'COMPLETED',
    },
  });
  if (opts.historyOperatorIds?.length) {
    await prisma.approvalTaskLog.createMany({
      data: opts.historyOperatorIds.map((operatorId) => ({
        taskId: task.id,
        instanceId: opts.approvalInstanceId,
        action: 'APPROVE' as any,
        operatorId,
        comment: `t_log_${opts.suffix}`,
      })),
    });
  }
  return { definitionId: def.id, versionId: version.id, taskId: task.id };
}

/**
 * 直接通过 prisma 创建 FormInstance（不走 submit 流程）。
 * 用于测试 update/withdraw/callback 等状态机切换，无需启动审批工作流。
 */
export async function createTestFormInstance(
  prisma: PrismaService,
  opts: {
    definition: TestFormDefinition;
    createdBy: string;
    status?: string;
    data?: Record<string, unknown>;
    businessKeyPrefix?: string;
    approvalInstanceId?: string | null;
    approvalStatus?: string | null;
  },
) {
  const businessKey = `${opts.businessKeyPrefix ?? 't_'}biz_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
  return prisma.formInstance.create({
    data: {
      formDefinitionId: opts.definition.definitionId,
      formVersionId: opts.definition.versionId,
      formKey: opts.definition.formKey,
      formVersion: opts.definition.formVersion,
      businessKey,
      data: (opts.data ?? { amount: 5000, reason: 't_test' }) as any,
      status: (opts.status ?? 'DRAFT') as any,
      regionId: 'CN',
      createdBy: opts.createdBy,
      approvalInstanceId: opts.approvalInstanceId ?? null,
      approvalStatus: opts.approvalStatus ?? null,
    },
  });
}
