import 'reflect-metadata';

import { ValidationPipe } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import request from 'supertest';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';

import { requestContextMiddleware } from '@adapters/http/RequestContext';
import { AuthModule } from './AuthModule';

describe('Auth session (HTTP, inmemory)', () => {
  let app: import("@nestjs/common").INestApplication;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      imports: [AuthModule],
    }).compile();

    app = module.createNestApplication();

    app.use(requestContextMiddleware);

    app.useGlobalPipes(
      new ValidationPipe({
        whitelist: true,
        forbidNonWhitelisted: true,
        transform: true,
      }),
    );

    await app.init();
  });

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

  it('signup sets gp_session cookie and session persists across requests', async () => {
    const agent = request.agent(app.getHttpServer());

    const signupRes = await agent
      .post('/auth/signup')
      .send({ email: 'u1@gridpilot.local', password: 'Password123!', displayName: 'John Smith' })
      .expect(201);

    const setCookie = signupRes.headers['set-cookie'] as string[] | undefined;
    expect(setCookie?.some((v) => v.startsWith('gp_session='))).toBe(true);

    const sessionRes = await agent.get('/auth/session').expect(200);

    expect(sessionRes.body).toMatchObject({
      token: expect.stringMatching(/^gp_/),
      user: {
        email: 'u1@gridpilot.local',
        displayName: 'John Smith',
        userId: expect.any(String),
      },
    });
  });

  it('login sets gp_session cookie for seeded admin and logout clears it', async () => {
    const agent = request.agent(app.getHttpServer());

    const loginRes = await agent
      .post('/auth/login')
      .send({ email: 'admin@gridpilot.local', password: 'admin123' })
      .expect(201);

    const setCookie = loginRes.headers['set-cookie'] as string[] | undefined;
    expect(setCookie?.some((v) => v.startsWith('gp_session='))).toBe(true);

    const sessionRes = await agent.get('/auth/session').expect(200);
    expect(sessionRes.body).toMatchObject({
      token: expect.any(String),
      user: {
        userId: 'driver-1',
        email: 'admin@gridpilot.local',
        displayName: 'Alex Martinez',
      },
    });

    const logoutRes = await agent.post('/auth/logout').expect(201);
    expect(logoutRes.body).toEqual({ success: true });

    const logoutCookies = logoutRes.headers['set-cookie'] as string[] | undefined;
    expect(logoutCookies?.some((v) => v.includes('gp_session=') && v.includes('Max-Age=0'))).toBe(true);

    await agent.get('/auth/session').expect(200).expect((res) => {
      expect(res.body).toBeNull();
    });
  });
});