/**
 * FFAI Agent — personas API 集成测试（Phase 2）
 *
 * 覆盖：
 *   - GET 首次访问触发系统预设 seed（7 条），含 createdById=NULL + systemKey
 *   - POST 用户自创（systemKey=NULL）
 *   - PATCH 系统预设：仅允许改 enabled / instructions / icon / description；改 name 返 403
 *   - DELETE 系统预设软隐藏（enabled=false，soft=true）；用户自创真删（soft=false）
 *   - 跨 org 拒绝
 *   - 校验：name required + > 120 → 400
 */
import { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { PrismaService } from '@/core/database/prisma/prisma.service';
import { cleanupDatabase } from '../../helpers/cleanup.helper';
import { createTestApp } from '../../helpers/app.helper';
import { setupIntegrationTest } from '../../helpers/test-setup.helper';

describe('FFAI Agent - Personas API (Phase 2)', () => {
  let app: INestApplication;
  let prisma: PrismaService;
  let adminToken: string;
  let adminUserId: string;
  let orgId: string;

  beforeAll(async () => {
    app = await createTestApp();
    prisma = app.get<PrismaService>(PrismaService);
  });

  beforeEach(async () => {
    const ctx = await setupIntegrationTest(app, prisma);
    adminToken = ctx.adminToken;
    adminUserId = ctx.adminUser.id;
    const org = await prisma.organization.findFirst({ orderBy: { createdAt: 'asc' } });
    orgId = org!.id;
  });

  afterEach(async () => {
    await cleanupDatabase(prisma);
  });

  afterAll(async () => {
    await app.close();
  });

  it('[AGENT-PERS-001] GET /agent/personas 首次访问 seed 7 个系统预设（createdById=NULL + systemKey 非空）', async () => {
    const res = await request(app.getHttpServer())
      .get('/api/v1/agent/personas')
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId)
      .expect(200);

    const items = res.body.data.items as Array<{
      createdById: string | null;
      systemKey: string | null;
      name: string;
    }>;
    const seeded = items.filter((p) => p.createdById === null && p.systemKey);
    expect(seeded.length).toBe(7);
    const keys = seeded.map((p) => p.systemKey).sort();
    expect(keys).toEqual(
      ['approver-helper', 'code-reviewer', 'data-analyst', 'general', 'knowledge-qa', 'translator', 'writer'].sort(),
    );
  });

  it('[AGENT-PERS-002] POST /agent/personas 用户自创（systemKey=NULL）', async () => {
    const res = await request(app.getHttpServer())
      .post('/api/v1/agent/personas')
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId)
      .send({ name: 'My Custom Persona', icon: '🎯', instructions: 'Be brutally honest.' })
      .expect(201);

    expect(res.body.data.systemKey).toBeNull();
    expect(res.body.data.createdById).toBe(adminUserId);
    expect(res.body.data.name).toBe('My Custom Persona');
  });

  it('[AGENT-PERS-003] POST 校验：name required + > 120 → 400', async () => {
    await request(app.getHttpServer())
      .post('/api/v1/agent/personas')
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId)
      .send({ name: '' })
      .expect(400);
    await request(app.getHttpServer())
      .post('/api/v1/agent/personas')
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId)
      .send({ name: 'x'.repeat(121) })
      .expect(400);
  });

  it('[AGENT-PERS-004] PATCH 系统预设：name 不可改 → 403；instructions 可改 → 200', async () => {
    // 先触发 seed
    await request(app.getHttpServer())
      .get('/api/v1/agent/personas')
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId);
    const sys = await prisma.agentPersona.findFirst({
      where: { organizationId: orgId, systemKey: 'code-reviewer' },
    });
    expect(sys).not.toBeNull();

    await request(app.getHttpServer())
      .patch(`/api/v1/agent/personas/${sys!.id}`)
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId)
      .send({ name: 'Hacked Name' })
      .expect(403);

    await request(app.getHttpServer())
      .patch(`/api/v1/agent/personas/${sys!.id}`)
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId)
      .send({ instructions: 'Updated instructions for code review' })
      .expect(200);
  });

  it('[AGENT-PERS-005] DELETE 系统预设 → 软隐藏 (soft=true, enabled=false)', async () => {
    await request(app.getHttpServer())
      .get('/api/v1/agent/personas')
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId);
    const sys = await prisma.agentPersona.findFirst({
      where: { organizationId: orgId, systemKey: 'translator' },
    });
    const res = await request(app.getHttpServer())
      .delete(`/api/v1/agent/personas/${sys!.id}`)
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId)
      .expect(200);
    expect(res.body.data.soft).toBe(true);
    const row = await prisma.agentPersona.findUnique({ where: { id: sys!.id } });
    expect(row?.enabled).toBe(false);
  });

  it('[AGENT-PERS-006] DELETE 用户自创 → 真删 (soft=false)', async () => {
    const created = await request(app.getHttpServer())
      .post('/api/v1/agent/personas')
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId)
      .send({ name: 'to-delete-user-custom' });
    const res = await request(app.getHttpServer())
      .delete(`/api/v1/agent/personas/${created.body.data.id}`)
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId)
      .expect(200);
    expect(res.body.data.soft).toBe(false);
    const row = await prisma.agentPersona.findUnique({ where: { id: created.body.data.id } });
    expect(row).toBeNull();
  });

  it('[AGENT-PERS-007] PATCH 跨 org → 403', async () => {
    const otherOrg = await prisma.organization.create({
      data: { code: `T_PERS_${Date.now()}`, name: 'other-org-pers' },
    });
    const p = await prisma.agentPersona.create({
      data: {
        organizationId: otherOrg.id,
        createdById: '00000000-0000-0000-0000-000000000000',
        systemKey: null,
        name: 'cross-org-persona',
      },
    });
    await request(app.getHttpServer())
      .patch(`/api/v1/agent/personas/${p.id}`)
      .set('Authorization', `Bearer ${adminToken}`)
      .set('X-Organization-Id', orgId)
      .send({ name: 'pwned' })
      .expect(403);
  });

  it('[AGENT-PERS-008] 无 JWT → 401', async () => {
    await request(app.getHttpServer())
      .get('/api/v1/agent/personas')
      .set('X-Organization-Id', orgId)
      .expect(401);
  });
});
