import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication, ExecutionContext } from '@nestjs/common';
import * as request from 'supertest';
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import { AuthController } from '../src/auth/auth.controller';
import { JwtAuthGuard } from '../src/auth/guards/jwt-auth.guard';
import { UserJwtGuard } from '../src/auth/guards/user-jwt.guard';
import { ClientJwtGuard } from '../src/auth/guards/client-jwt.guard';
import { ConfigModule } from '@nestjs/config';

// Mock dos guards
const mockJwtAuthGuard = {
  canActivate: jest.fn((_context: ExecutionContext) => true),
};

const mockUserJwtGuard = {
  canActivate: jest.fn((_context: ExecutionContext) => true),
};

const mockClientJwtGuard = {
  canActivate: jest.fn((_context: ExecutionContext) => true),
};

describe('Auth Module (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [
        ConfigModule.forRoot({
          isGlobal: true,
          ignoreEnvFile: true,
          load: [
            () => ({
              JWT_SECRET: 'test-secret-key',
              JWT_ALGORITHM: 'HS256',
            }),
          ],
        }),
      ],
      controllers: [AuthController],
      providers: [
        {
          provide: JwtAuthGuard,
          useValue: mockJwtAuthGuard,
        },
        {
          provide: UserJwtGuard,
          useValue: mockUserJwtGuard,
        },
        {
          provide: ClientJwtGuard,
          useValue: mockClientJwtGuard,
        },
      ],
    })
      .overrideGuard(JwtAuthGuard)
      .useValue(mockJwtAuthGuard)
      .overrideGuard(UserJwtGuard)
      .useValue(mockUserJwtGuard)
      .overrideGuard(ClientJwtGuard)
      .useValue(mockClientJwtGuard)
      .compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

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

  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('GET /auth/health', () => {
    it('deve retornar status de saúde sem autenticação', () => {
      return request(app.getHttpServer())
        .get('/auth/health')
        .expect(200)
        .expect((res: request.Response) => {
          expect(res.body).toHaveProperty('status', 'OK');
          expect(res.body).toHaveProperty('timestamp');
        });
    });
  });

  describe('GET /auth/profile', () => {
    it('deve acessar perfil com token válido', () => {
      mockJwtAuthGuard.canActivate.mockImplementation(
        (context: ExecutionContext) => {
          const req = context.switchToHttp().getRequest();
          (req as any).user = {
            id: 'user-123',
            type: 'user',
            expiresAt: new Date(),
            issuedAt: new Date(),
            payload: { sub: 'user-123' },
          };
          return true;
        },
      );

      return request(app.getHttpServer())
        .get('/auth/profile')
        .set('Authorization', 'Bearer valid_token')
        .expect(200)
        .expect((res: request.Response) => {
          expect(res.body).toHaveProperty('message');
          expect(res.body).toHaveProperty('user');
        });
    });

    it('deve retornar erro 401 sem token', () => {
      mockJwtAuthGuard.canActivate.mockReturnValue(false);

      return request(app.getHttpServer()).get('/auth/profile').expect(403);
    });
  });

  describe('GET /auth/user/dashboard', () => {
    it('deve acessar dashboard de usuário com token válido', () => {
      mockUserJwtGuard.canActivate.mockImplementation(
        (context: ExecutionContext) => {
          const req = context.switchToHttp().getRequest();
          (req as any).user = {
            id: 'user-123',
            type: 'user',
            expiresAt: new Date(),
            issuedAt: new Date(),
            payload: { sub: 'user-123' },
          };
          return true;
        },
      );

      return request(app.getHttpServer())
        .get('/auth/user/dashboard')
        .set('Authorization', 'Bearer valid_user_token')
        .expect(200)
        .expect((res: request.Response) => {
          expect(res.body).toHaveProperty('message');
        });
    });

    it('deve retornar erro 401 sem token', () => {
      mockUserJwtGuard.canActivate.mockReturnValue(false);

      return request(app.getHttpServer())
        .get('/auth/user/dashboard')
        .expect(403);
    });
  });

  describe('GET /auth/client/dashboard', () => {
    it('deve acessar dashboard de client com token válido', () => {
      mockClientJwtGuard.canActivate.mockImplementation(
        (context: ExecutionContext) => {
          const req = context.switchToHttp().getRequest();
          (req as any).user = {
            id: 'client-123',
            type: 'client',
            expiresAt: new Date(),
            issuedAt: new Date(),
            payload: { sub: 'client-123' },
          };
          return true;
        },
      );

      return request(app.getHttpServer())
        .get('/auth/client/dashboard')
        .set('Authorization', 'Bearer valid_client_token')
        .expect(200)
        .expect((res: request.Response) => {
          expect(res.body).toHaveProperty('message');
        });
    });

    it('deve retornar erro 401 sem token', () => {
      mockClientJwtGuard.canActivate.mockReturnValue(false);

      return request(app.getHttpServer())
        .get('/auth/client/dashboard')
        .expect(403);
    });
  });
});
