import { describe, expect, it } from 'vitest';
import {
  createCosmosMocks,
  TEST_JWT_SECRET,
  TEST_USERS,
  createTestTokenPayload,
  injectGet,
  expectHealthOk,
} from '../index.js';
import { createServiceApp } from '@bytelyst/fastify-core';

describe('createCosmosMocks', () => {
  it('returns all mock objects', () => {
    const mocks = createCosmosMocks();
    expect(mocks.mockContainer).toBeDefined();
    expect(mocks.mockContainer.id).toBe('test-container');
    expect(mocks.mockDatabase).toBeDefined();
    expect(mocks.mockDatabases).toBeDefined();
    expect(mocks.MockCosmosClient).toBeDefined();
    expect(typeof mocks.resetMocks).toBe('function');
  });

  it('MockCosmosClient returns database', () => {
    const { MockCosmosClient, mockDatabase } = createCosmosMocks();
    const client = new MockCosmosClient('endpoint', 'key');
    expect(client.database('test-db')).toBe(mockDatabase);
  });

  it('mockContainer.items has CRUD methods', () => {
    const { mockContainer } = createCosmosMocks();
    expect(typeof mockContainer.items.create).toBe('function');
    expect(typeof mockContainer.items.query).toBe('function');
    expect(typeof mockContainer.items.upsert).toBe('function');
    expect(typeof mockContainer.item).toBe('function');
  });

  it('resetMocks clears all mock state', () => {
    const { mockContainer, resetMocks } = createCosmosMocks();
    mockContainer.items.create({ id: '1' });
    expect(mockContainer.items.create).toHaveBeenCalledOnce();
    resetMocks();
    expect(mockContainer.items.create).not.toHaveBeenCalled();
  });
});

describe('auth fixtures', () => {
  it('TEST_JWT_SECRET is a non-empty string', () => {
    expect(TEST_JWT_SECRET).toBeTruthy();
    expect(TEST_JWT_SECRET.length).toBeGreaterThanOrEqual(16);
  });

  it('TEST_USERS has admin, viewer, and user', () => {
    expect(TEST_USERS.admin.email).toBe('admin@test.com');
    expect(TEST_USERS.viewer.role).toBe('viewer');
    expect(TEST_USERS.user.productId).toBe('lysnrai');
  });

  it('createTestTokenPayload returns valid shape', () => {
    const payload = createTestTokenPayload('admin');
    expect(payload.sub).toBe('user-admin-001');
    expect(payload.email).toBe('admin@test.com');
    expect(payload.role).toBe('super_admin');
    expect(payload.iss).toBe('test');
    expect(payload.exp).toBeGreaterThan(payload.iat);
  });

  it('createTestTokenPayload defaults to admin', () => {
    const payload = createTestTokenPayload();
    expect(payload.sub).toBe('user-admin-001');
  });
});

describe('fastify helpers', () => {
  it('injectGet + expectHealthOk work with a real fastify-core app', async () => {
    const app = await createServiceApp({
      name: 'test-svc',
      version: '1.0.0',
      logger: false,
    });

    const res = await injectGet(app, '/health');
    expect(res.statusCode).toBe(200);
    expectHealthOk(res, 'test-svc');

    await app.close();
  });

  it('expectHealthOk throws on wrong service name', async () => {
    const app = await createServiceApp({
      name: 'real-svc',
      version: '1.0.0',
      logger: false,
    });

    const res = await injectGet(app, '/health');
    expect(() => expectHealthOk(res, 'wrong-name')).toThrow('Expected service "wrong-name"');

    await app.close();
  });
});
