import { Test, TestingModule } from '@nestjs/testing'
import { INestApplication, ValidationPipe } from '@nestjs/common'
import * as request from 'supertest'
import { AppModule } from '@/app.module'
import { GlobalExceptionFilter } from '@/shared/filters'
import { TransformInterceptor } from '@/shared/interceptors'
import { PrismaClient } from '@prisma/client'

describe('Authorization Service E2E Tests', () => {
  let app: INestApplication
  let prisma: PrismaClient
  const isDockerEnv = process.env.NODE_ENV === 'test' && process.env.DATABASE_URL?.includes('test-db')

  beforeAll(async () => {
    // In Docker environment, infrastructure must be available
    // In local environment, gracefully skip if infrastructure is not available
    try {
      // Initialize Prisma and run migrations
      prisma = new PrismaClient()
      await prisma.$connect()

      const moduleFixture: TestingModule = await Test.createTestingModule({
        imports: [AppModule],
      }).compile()

      app = moduleFixture.createNestApplication()
      app.setGlobalPrefix('api/v1')
      app.useGlobalPipes(
        new ValidationPipe({
          whitelist: true,
          forbidNonWhitelisted: true,
          transform: true,
        }),
      )
      app.useGlobalFilters(new GlobalExceptionFilter())
      app.useGlobalInterceptors(new TransformInterceptor())

      await app.init()
      console.log('E2E tests initialized successfully with infrastructure')
    } catch (error) {
      if (isDockerEnv) {
        // In Docker, infrastructure should always be available
        throw new Error(`E2E tests failed to initialize in Docker environment: ${error}`)
      }
      console.log('E2E tests skipped: Infrastructure not available')
      console.log('To run E2E tests, ensure PostgreSQL, Redis, and Kafka are running')
      console.log('Or use: docker-compose -f docker-compose.test.yml up')
    }
  }, 60000) // 60 second timeout for initialization

  afterAll(async () => {
    if (app) {
      await app.close()
    }
    if (prisma) {
      await prisma.$disconnect()
    }
  })

  describe('Health Check', () => {
    it('should be defined', () => {
      expect(true).toBe(true)
    })
  })

  describe('Authentication Tests', () => {
    it('should return 401 for unauthorized access to /api/v1/authorizations/my', async () => {
      if (!app) {
        console.log('Skipping test: App not initialized')
        return
      }
      return request(app.getHttpServer())
        .get('/api/v1/authorizations/my')
        .expect(401)
    })

    it('should return 401 for unauthorized access to /api/v1/admin/authorizations/province-company', async () => {
      if (!app) {
        console.log('Skipping test: App not initialized')
        return
      }
      return request(app.getHttpServer())
        .post('/api/v1/admin/authorizations/province-company')
        .send({ userId: 'test', provinceCode: '430000', provinceName: '湖南省' })
        .expect(401)
    })
  })

  describe('Validation Tests', () => {
    it('should return 401 when posting to /api/v1/authorizations/community without token', async () => {
      if (!app) {
        console.log('Skipping test: App not initialized')
        return
      }
      return request(app.getHttpServer())
        .post('/api/v1/authorizations/community')
        .send({ communityName: '测试社区' })
        .expect(401)
    })

    it('should return 401 when posting to /api/v1/authorizations/province without token', async () => {
      if (!app) {
        console.log('Skipping test: App not initialized')
        return
      }
      return request(app.getHttpServer())
        .post('/api/v1/authorizations/province')
        .send({ provinceCode: '430000', provinceName: '湖南省' })
        .expect(401)
    })

    it('should return 401 when posting to /api/v1/authorizations/city without token', async () => {
      if (!app) {
        console.log('Skipping test: App not initialized')
        return
      }
      return request(app.getHttpServer())
        .post('/api/v1/authorizations/city')
        .send({ cityCode: '430100', cityName: '长沙市' })
        .expect(401)
    })
  })
})
