import { NotFoundException } from '@nestjs/common';
import { TestCaseService } from './test-case.service';

describe('TestCaseService domain writes', () => {
  const makeService = () => {
    const workActivity = {
      record: jest.fn().mockResolvedValue({ id: 'activity-1' }),
    };
    const prisma = {
      version: {
        findUnique: jest.fn(),
      },
      testCase: {
        create: jest.fn(),
        createMany: jest.fn(),
        delete: jest.fn(),
        findFirst: jest.fn(),
        findMany: jest.fn(),
        update: jest.fn(),
      },
    };

    return {
      prisma,
      workActivity,
      service: new TestCaseService(prisma as any, workActivity as any),
    };
  };

  it('creates test cases directly under a version partition', async () => {
    const { prisma, workActivity, service } = makeService();
    prisma.version.findUnique.mockResolvedValue({ id: 'version-1', productId: 'product-1', projectId: 'project-1' });
    prisma.testCase.create.mockResolvedValue({ id: 'tc-1', versionId: 'version-1', title: '登录冒烟' });

    await service.create('version-1', {
      requirementId: 'req-1',
      requirementProductId: 'product-1',
      caseNo: 'TC-001',
      title: '登录冒烟',
      categoryId: 'cat-test',
      assigneeId: 'tester-1',
      priority: 'P1',
      plannedTestAt: '2026-07-08T09:00:00.000Z',
      plannedEndAt: '2026-07-08T10:00:00.000Z',
      estimateHours: 1,
      references: [{ type: 'requirement', id: 'REQ-001', label: 'REQ-001 登录' }],
      createdBy: 'member-pm',
    } as any);

    expect(prisma.testCase.create).toHaveBeenCalledWith({
      data: expect.objectContaining({
        versionId: 'version-1',
        productId: 'product-1',
        projectId: 'project-1',
        requirementId: 'req-1',
        requirementProductId: 'product-1',
        code: 'TC-001',
        title: '登录冒烟',
        categoryId: 'cat-test',
        assigneeId: 'tester-1',
        priority: 1,
        plannedTestAt: new Date('2026-07-08T09:00:00.000Z'),
        plannedEndAt: new Date('2026-07-08T10:00:00.000Z'),
        estimateHours: 1,
        status: 'pending',
      }),
    });
    expect(workActivity.record).toHaveBeenCalledWith(expect.objectContaining({
      versionId: 'version-1',
      sourceType: 'test_case',
      sourceId: 'tc-1',
      action: 'test_case_created',
    }));
  });

  it('changes status by id plus version id and records activity evidence', async () => {
    const { prisma, workActivity, service } = makeService();
    prisma.testCase.findFirst.mockResolvedValue({
      id: 'tc-1',
      versionId: 'version-1',
      productId: 'product-1',
      projectId: 'project-1',
      status: 'pending',
      title: '登录冒烟',
      assigneeId: 'tester-1',
    });
    prisma.testCase.update.mockResolvedValue({
      id: 'tc-1',
      versionId: 'version-1',
      productId: 'product-1',
      projectId: 'project-1',
      status: 'running',
      title: '登录冒烟',
      assigneeId: 'tester-1',
    });

    await service.updateStatus('version-1', 'tc-1', 'running');

    expect(prisma.testCase.update).toHaveBeenCalledWith({
      where: { id_versionId: { id: 'tc-1', versionId: 'version-1' } },
      data: expect.objectContaining({
        status: 'running',
        startedAt: expect.any(Date),
      }),
    });
    expect(workActivity.record).toHaveBeenCalledWith(expect.objectContaining({
      versionId: 'version-1',
      sourceType: 'test_case',
      sourceId: 'tc-1',
      action: 'test_case_started',
    }));
  });

  it('creates copied round test cases in the same version partition', async () => {
    const { prisma, service } = makeService();
    prisma.version.findUnique.mockResolvedValue({ id: 'version-1', productId: 'product-1', projectId: 'project-1' });
    prisma.testCase.createMany.mockResolvedValue({ count: 2 });
    prisma.testCase.findMany.mockResolvedValue([{ id: 'tc-copy-1' }, { id: 'tc-copy-2' }]);

    await service.createMany('version-1', [
      { caseNo: 'TC-101', title: '第二轮登录', roundNo: 2, createdBy: 'tester-1' },
      { caseNo: 'TC-102', title: '第二轮支付', roundNo: 2, createdBy: 'tester-1' },
    ] as any);

    expect(prisma.testCase.createMany).toHaveBeenCalledWith({
      data: [
        expect.objectContaining({ versionId: 'version-1', productId: 'product-1', projectId: 'project-1', roundNo: 2, status: 'pending' }),
        expect.objectContaining({ versionId: 'version-1', productId: 'product-1', projectId: 'project-1', roundNo: 2, status: 'pending' }),
      ],
      skipDuplicates: true,
    });
  });

  it('rejects updates outside the version partition', async () => {
    const { prisma, service } = makeService();
    prisma.testCase.findFirst.mockResolvedValue(null);

    await expect(service.update('version-1', 'missing-case', { title: 'Ghost' })).rejects.toBeInstanceOf(NotFoundException);
    expect(prisma.testCase.update).not.toHaveBeenCalled();
  });
});
