import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { AppModule } from '../src/app.module';

describe('M1 E2E Tests', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();
    app = moduleFixture.createNestApplication();
    app.setGlobalPrefix('api', { exclude: ['admin-api/(.*)', 'internal/(.*)'] });
    await app.init();
  });

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

  async function loginAdmin(): Promise<string> {
    const res = await request(app.getHttpServer())
      .post('/admin-api/auth/login')
      .send({ email: 'admin@zhixi.app', password: 'admin123' });
    return res.body?.data?.accessToken || '';
  }

  // ══════════════════════════════════════════════
  // M1-01: AI Gateway 深化
  // ══════════════════════════════════════════════
  describe('M1-01 AI Gateway Deepening', () => {
    let token: string;
    beforeAll(async () => { token = await loginAdmin(); });

    it('GET /admin-api/ai-gateway/status → 200 with routes info', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/ai-gateway/status')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(res.body.data).toHaveProperty('providers');
      expect(res.body.data).toHaveProperty('routes');
      expect(res.body.data).toHaveProperty('activeRoutes');
    });

    // ── Model Routes CRUD ──

    it('GET /admin-api/ai-gateway/routes → 200 with route list', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/ai-gateway/routes')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(Array.isArray(res.body.data)).toBe(true);
    });

    it('GET /admin-api/ai-gateway/routes → 401 without token', async () => {
      await request(app.getHttpServer())
        .get('/admin-api/ai-gateway/routes')
        .expect(401);
    });

    it('POST /admin-api/ai-gateway/routes → creates route and reloads cache', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .post('/admin-api/ai-gateway/routes')
        .set('Authorization', `Bearer ${token}`)
        .send({
          tier: 'cheap',
          taskType: 'test-e2e',
          preferredProvider: 'deepseek',
          preferredModel: 'deepseek-v4-flash',
          fallbackProvider: 'deepseek',
          fallbackModel: 'deepseek-v4-flash',
          maxRetries: 1,
        })
        .expect([200, 201]);
      if (res.body?.data?.id) {
        await request(app.getHttpServer())
          .delete(`/admin-api/ai-gateway/routes/${res.body.data.id}`)
          .set('Authorization', `Bearer ${token}`);
      }
    });

    it('PUT /admin-api/ai-gateway/routes/:id → updates route', async () => {
      if (!token) return;
      const create = await request(app.getHttpServer())
        .post('/admin-api/ai-gateway/routes')
        .set('Authorization', `Bearer ${token}`)
        .send({
          tier: 'strong',
          taskType: 'test-update',
          preferredProvider: 'deepseek',
          preferredModel: 'deepseek-v4-pro',
          fallbackProvider: 'minimax',
          fallbackModel: 'minimax-m2.7',
          maxRetries: 2,
        });
      const id = create.body?.data?.id;
      if (!id) return;

      await request(app.getHttpServer())
        .put(`/admin-api/ai-gateway/routes/${id}`)
        .set('Authorization', `Bearer ${token}`)
        .send({ maxRetries: 4 })
        .expect(200);

      await request(app.getHttpServer())
        .delete(`/admin-api/ai-gateway/routes/${id}`)
        .set('Authorization', `Bearer ${token}`);
    });

    // ── Provider management ──

    it('GET /admin-api/ai-gateway/providers → 200 with provider list', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/ai-gateway/providers')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(Array.isArray(res.body.data)).toBe(true);
    });

    it('PUT /admin-api/ai-gateway/providers/:name → enables/disables provider', async () => {
      if (!token) return;
      await request(app.getHttpServer())
        .put('/admin-api/ai-gateway/providers/deepseek')
        .set('Authorization', `Bearer ${token}`)
        .send({ enabled: true })
        .expect(200);
    });

    // ── Fallback events ──

    it('GET /admin-api/ai-gateway/fallback-events → 200 with events list', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/ai-gateway/fallback-events')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(Array.isArray(res.body.data)).toBe(true);
    });
  });

  // ══════════════════════════════════════════════
  // M1-02: Vector & Retrieval Module
  // ══════════════════════════════════════════════
  describe('M1-02 Vector & Retrieval', () => {
    let token: string;
    beforeAll(async () => { token = await loginAdmin(); });

    it('GET /admin-api/vector/collection → 200 with collection info', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/vector/collection')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(res.body.data).toHaveProperty('name');
      expect(res.body.data).toHaveProperty('pointsCount');
    });

    it('GET /admin-api/vector/collection → 401 without token', async () => {
      await request(app.getHttpServer())
        .get('/admin-api/vector/collection')
        .expect(401);
    });

    it('GET /admin-api/vector/count → 200 with vector count', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/vector/count')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(res.body.data).toHaveProperty('collection');
      expect(res.body.data).toHaveProperty('count');
    });

    it('POST /admin-api/vector/reindex → 200 (reserved)', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .post('/admin-api/vector/reindex')
        .set('Authorization', `Bearer ${token}`)
        .expect([200, 201]);
      expect(res.body.data).toHaveProperty('message');
    });
  });

  // ══════════════════════════════════════════════
  // M1-03: Task Queue 深化
  // ══════════════════════════════════════════════
  describe('M1-03 Task Queue Deepening', () => {
    let token: string;
    beforeAll(async () => { token = await loginAdmin(); });

    it('GET /admin-api/events/stats → 200 with task type configs', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/events/stats')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(res.body.data).toHaveProperty('taskStats');
      expect(res.body.data).toHaveProperty('totalTaskTypes');
    });

    it('GET /admin-api/events/stats → 401 without token', async () => {
      await request(app.getHttpServer())
        .get('/admin-api/events/stats')
        .expect(401);
    });

    it('GET /admin-api/events/workers → 200 with worker status', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/events/workers')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(res.body.data).toHaveProperty('workers');
      expect(res.body.data).toHaveProperty('count');
    });

    it('POST /admin-api/events/:queue/jobs/batch-retry → 200', async () => {
      if (!token) return;
      await request(app.getHttpServer())
        .post('/admin-api/events/ai-analysis/jobs/batch-retry')
        .set('Authorization', `Bearer ${token}`)
        .send({ count: 10 })
        .expect([200, 201]);
    });
  });

  // ══════════════════════════════════════════════
  // M1-04: Content Safety 深化
  // ══════════════════════════════════════════════
  describe('M1-04 Content Safety Deepening', () => {
    let token: string;
    beforeAll(async () => { token = await loginAdmin(); });

    it('POST /api/reports → 201 submit user report', async () => {
      const res = await request(app.getHttpServer())
        .post('/api/reports')
        .send({ targetType: 'knowledge_item', targetId: 'test123', reason: '包含错误信息', reporterId: 'user1' })
        .expect([200, 201]);
      expect(res.body.success).toBe(true);
    });

    it('GET /admin-api/content-safety/reports → 200 list reports', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/content-safety/reports')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(Array.isArray(res.body.data)).toBe(true);
    });

    it('GET /admin-api/content-safety/reports → 401 without token', async () => {
      await request(app.getHttpServer())
        .get('/admin-api/content-safety/reports')
        .expect(401);
    });

    it('GET /admin-api/content-safety/violations → 200 list violations', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/content-safety/violations')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(Array.isArray(res.body.data)).toBe(true);
    });

    it('POST /admin-api/content-safety/violations/:id/penalty → apply penalty', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .post('/admin-api/content-safety/violations/test-id/penalty')
        .set('Authorization', `Bearer ${token}`)
        .send({ penalty: 'warning' })
        .expect([200, 201]);
      expect(res.body.success).toBe(true);
    });

    it('POST /admin-api/content-safety/reports/:id/handle → handle report', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .post('/admin-api/content-safety/reports/test-id/handle')
        .set('Authorization', `Bearer ${token}`)
        .send({ action: 'dismissed', note: '已处理' })
        .expect([200, 201]);
      expect(res.body.success).toBe(true);
    });
  });

  // ══════════════════════════════════════════════
  // M1-05: Observability 深化
  // ══════════════════════════════════════════════
  describe('M1-05 Observability Deepening', () => {
    let token: string;
    beforeAll(async () => { token = await loginAdmin(); });

    it('GET /admin-api/metrics/ai → 200 AI performance stats', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/metrics/ai?days=7')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(res.body.data).toHaveProperty('totalCalls');
      expect(res.body.data).toHaveProperty('providers');
      expect(res.body.data).toHaveProperty('models');
    });

    it('GET /admin-api/metrics/ai → 401 without token', async () => {
      await request(app.getHttpServer())
        .get('/admin-api/metrics/ai')
        .expect(401);
    });

    it('GET /admin-api/metrics/worker → 200 Worker performance stats', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/metrics/worker?days=7')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(res.body.data).toHaveProperty('totalTasks');
      expect(res.body.data).toHaveProperty('queues');
    });
  });

  // ══════════════════════════════════════════════
  // M1-06: Quota/Cost 闭环
  // ══════════════════════════════════════════════
  describe('M1-06 Quota/Cost Closing', () => {
    let token: string;
    beforeAll(async () => { token = await loginAdmin(); });

    it('GET /admin-api/costs/report → 200 AI cost report', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/costs/report?days=30')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(res.body.data).toHaveProperty('totalCost');
      expect(res.body.data).toHaveProperty('byProvider');
      expect(res.body.data).toHaveProperty('dailyTrend');
    });

    it('POST /admin-api/costs/aggregate → 200 trigger aggregation', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .post('/admin-api/costs/aggregate')
        .set('Authorization', `Bearer ${token}`)
        .expect([200, 201]);
      expect(res.body.success).toBe(true);
    });

    it('GET /admin-api/costs/top-users → 200 top consumers', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/costs/top-users?days=30&limit=10')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(res.body.data).toHaveProperty('top');
    });

    it('GET /admin-api/costs/export-csv → 200 CSV download', async () => {
      if (!token) return;
      const res = await request(app.getHttpServer())
        .get('/admin-api/costs/export-csv?days=7')
        .set('Authorization', `Bearer ${token}`)
        .expect(200);
      expect(res.headers['content-type']).toContain('text/csv');
    });
  });
});
