/**
 * GET /api/login — tests for the top-level-nav login entry point.
 *
 * Covers:
 *   1. DEV_AUTH_BYPASS=true: GET /api/login returns 302 → '/'.
 *      Guard is not mounted; handler fires directly.
 *   2. Without DEV_AUTH_BYPASS: oidcAuthMiddleware passthrough mock lets the
 *      request through; handler returns 302 → '/' (mirroring me.test.ts OIDC path).
 *
 * Flow (production):
 *   Unauthenticated top-level nav → guard 302 → Authelia → /callback → `continue`
 *   cookie returns browser to /api/login (now authenticated) → handler 302 → /.
 *   Under DEV_AUTH_BYPASS, guard is not mounted, so /api/login reaches the handler
 *   directly and redirects to '/'.
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';

// ---------------------------------------------------------------------------
// Shared mock: DB — avoids real DB connections across all tests in this file.
// Hoisted so it applies to every dynamic import below.
// ---------------------------------------------------------------------------
vi.mock('../../src/db/client.js', () => ({
  db: {
    execute: vi.fn().mockResolvedValue([[{ '1': 1 }]]),
    select: vi.fn().mockReturnValue({
      from: vi.fn().mockReturnValue({
        where: vi.fn().mockResolvedValue([]),
        innerJoin: vi.fn().mockReturnValue({
          innerJoin: vi.fn().mockReturnValue({
            where: vi.fn().mockResolvedValue([]),
          }),
        }),
      }),
    }),
  },
}));

// ---------------------------------------------------------------------------
// Track whether oidcAuthMiddleware was registered on the app.
// ---------------------------------------------------------------------------
const oidcMiddlewareSpy = vi.fn(() => async (_c: unknown, next: () => Promise<void>) => next());

vi.mock('@hono/oidc-auth', () => ({
  oidcAuthMiddleware: () => oidcMiddlewareSpy(),
  processOAuthCallback: () => async (c: { json: (v: unknown) => unknown }) => c.json({ ok: true }),
  getAuth: vi.fn().mockResolvedValue(null),
}));

// ---------------------------------------------------------------------------
// Env snapshot — restored after each test.
// ---------------------------------------------------------------------------
const originalNodeEnv = process.env.NODE_ENV;
const originalBypassFlag = process.env.DEV_AUTH_BYPASS;

afterEach(() => {
  process.env.NODE_ENV = originalNodeEnv;
  if (originalBypassFlag === undefined) {
    delete process.env.DEV_AUTH_BYPASS;
  } else {
    process.env.DEV_AUTH_BYPASS = originalBypassFlag;
  }
  vi.resetModules();
  oidcMiddlewareSpy.mockClear();
});

// ---------------------------------------------------------------------------

describe('GET /api/login — dev-auth bypass (DEV_AUTH_BYPASS=true)', () => {
  beforeEach(() => {
    process.env.NODE_ENV = 'test';
    process.env.DEV_AUTH_BYPASS = 'true';
  });

  it('returns 302 with location "/" (bypass active, guard not mounted)', async () => {
    const { app } = await import('../../src/index.js');

    const res = await app.request('/api/login');
    expect(res.status).toBe(302);
    expect(res.headers.get('location')).toBe('/');
  });

  it('does not invoke oidcAuthMiddleware when bypass is active', async () => {
    const { app } = await import('../../src/index.js');

    await app.request('/api/login');

    expect(oidcMiddlewareSpy).not.toHaveBeenCalled();
  });
});

describe('GET /api/login — OIDC path (no DEV_AUTH_BYPASS)', () => {
  beforeEach(() => {
    process.env.NODE_ENV = 'test';
    delete process.env.DEV_AUTH_BYPASS;
  });

  it('returns 302 with location "/" when OIDC passthrough allows the request', async () => {
    const { app } = await import('../../src/index.js');

    // oidcAuthMiddleware is mocked as a passthrough — request reaches the handler.
    const res = await app.request('/api/login');
    expect(res.status).toBe(302);
    expect(res.headers.get('location')).toBe('/');
  });
});
