/**
 * Tests for {{pascalCase serviceName}} service.
 * @module @aios/{{kebabCase serviceName}}/tests
 * @story {{storyId}}
 */

import {
  create{{pascalCase serviceName}}Service,
  {{pascalCase serviceName}}Error,
  {{pascalCase serviceName}}ErrorCode,
} from '../index';
import type { {{pascalCase serviceName}}Config, {{pascalCase serviceName}}Service } from '../types';

describe('{{pascalCase serviceName}}Service', () => {
  // ─────────────────────────────────────────────────────────────────────────────
  // Test Configuration
  // ─────────────────────────────────────────────────────────────────────────────

  const validConfig: {{pascalCase serviceName}}Config = {
{{#each envVars}}
    {{camelCase this.name}}: 'test-{{kebabCase this.name}}',
{{/each}}
  };

  // ─────────────────────────────────────────────────────────────────────────────
  // Factory Function Tests
  // ─────────────────────────────────────────────────────────────────────────────

  describe('create{{pascalCase serviceName}}Service', () => {
    it('should create a service instance with valid config', () => {
      const service = create{{pascalCase serviceName}}Service(validConfig);

      expect(service).toBeDefined();
      expect(typeof service.execute).toBe('function');
      expect(typeof service.getConfig).toBe('function');
      expect(typeof service.healthCheck).toBe('function');
    });

    it('should throw on null config', () => {
      expect(() => {
        create{{pascalCase serviceName}}Service(null as unknown as {{pascalCase serviceName}}Config);
      }).toThrow({{pascalCase serviceName}}Error);
    });

    it('should throw on undefined config', () => {
      expect(() => {
        create{{pascalCase serviceName}}Service(undefined as unknown as {{pascalCase serviceName}}Config);
      }).toThrow({{pascalCase serviceName}}Error);
    });

{{#each envVars}}
{{#if this.required}}
    it('should throw when {{this.name}} is missing', () => {
      const configWithoutField = { ...validConfig };
      delete (configWithoutField as Record<string, unknown>).{{camelCase this.name}};

      expect(() => {
        create{{pascalCase serviceName}}Service(configWithoutField as {{pascalCase serviceName}}Config);
      }).toThrow(expect.objectContaining({
        code: {{pascalCase serviceName}}ErrorCode.CONFIGURATION_ERROR,
      }));
    });

{{/if}}
{{/each}}
  });

  // ─────────────────────────────────────────────────────────────────────────────
  // Configuration Tests
  // ─────────────────────────────────────────────────────────────────────────────

  describe('getConfig', () => {
    let service: {{pascalCase serviceName}}Service;

    beforeEach(() => {
      service = create{{pascalCase serviceName}}Service(validConfig);
    });

    it('should return configuration without sensitive values', () => {
      const config = service.getConfig();

      expect(config).toBeDefined();
      expect(typeof config).toBe('object');
    });

    it('should not expose sensitive configuration', () => {
      const config = service.getConfig();

      // Verify sensitive fields are not exposed
{{#each envVars}}
{{#if this.sensitive}}
      expect(config.{{camelCase this.name}}).toBeUndefined();
{{/if}}
{{/each}}
    });
  });

  // ─────────────────────────────────────────────────────────────────────────────
  // Service Method Tests
  // ─────────────────────────────────────────────────────────────────────────────

  describe('execute', () => {
    let service: {{pascalCase serviceName}}Service;

    beforeEach(() => {
      service = create{{pascalCase serviceName}}Service(validConfig);
    });

    it('should throw NOT_IMPLEMENTED for unimplemented execute', async () => {
      await expect(service.execute()).rejects.toThrow(expect.objectContaining({
        code: {{pascalCase serviceName}}ErrorCode.NOT_IMPLEMENTED,
      }));
    });
  });

  describe('healthCheck', () => {
    let service: {{pascalCase serviceName}}Service;

    beforeEach(() => {
      service = create{{pascalCase serviceName}}Service(validConfig);
    });

    it('should return boolean', async () => {
      const result = await service.healthCheck();

      expect(typeof result).toBe('boolean');
    });
  });

  // ─────────────────────────────────────────────────────────────────────────────
  // Error Handling Tests
  // ─────────────────────────────────────────────────────────────────────────────

  describe('{{pascalCase serviceName}}Error', () => {
    it('should have correct name', () => {
      const error = new {{pascalCase serviceName}}Error('Test error');

      expect(error.name).toBe('{{pascalCase serviceName}}Error');
    });

    it('should have default error code', () => {
      const error = new {{pascalCase serviceName}}Error('Test error');

      expect(error.code).toBe({{pascalCase serviceName}}ErrorCode.UNKNOWN_ERROR);
    });

    it('should accept custom error code', () => {
      const error = new {{pascalCase serviceName}}Error(
        'Config error',
        {{pascalCase serviceName}}ErrorCode.CONFIGURATION_ERROR
      );

      expect(error.code).toBe({{pascalCase serviceName}}ErrorCode.CONFIGURATION_ERROR);
    });

    it('should include error details', () => {
      const details = { field: 'test', reason: 'invalid' };
      const error = new {{pascalCase serviceName}}Error(
        'Validation error',
        {{pascalCase serviceName}}ErrorCode.CONFIGURATION_ERROR,
        { details }
      );

      expect(error.details).toEqual(details);
    });

    it('should preserve cause error', () => {
      const cause = new Error('Original error');
      const error = new {{pascalCase serviceName}}Error(
        'Wrapped error',
        {{pascalCase serviceName}}ErrorCode.NETWORK_ERROR,
        { cause }
      );

      expect(error.cause).toBe(cause);
    });

    it('should serialize to JSON correctly', () => {
      const error = new {{pascalCase serviceName}}Error(
        'Test error',
        {{pascalCase serviceName}}ErrorCode.CONFIGURATION_ERROR,
        { details: { key: 'value' } }
      );

      const json = error.toJSON();

      expect(json.name).toBe('{{pascalCase serviceName}}Error');
      expect(json.code).toBe({{pascalCase serviceName}}ErrorCode.CONFIGURATION_ERROR);
      expect(json.message).toBe('Test error');
      expect(json.details).toEqual({ key: 'value' });
    });
  });
});

{{#if isApiIntegration}}
// ─────────────────────────────────────────────────────────────────────────────
// API Client Tests (API Integrations Only)
// ─────────────────────────────────────────────────────────────────────────────

describe('{{pascalCase serviceName}}Client', () => {
  // Import client for API integration testing
  const { {{pascalCase serviceName}}Client } = require('../client');

  const clientConfig: {{pascalCase serviceName}}Config = {
    ...validConfig,
    baseUrl: 'https://api.example.com',
    timeout: 5000,
    maxRetries: 2,
    debug: false,
  };

  describe('constructor', () => {
    it('should create client with config', () => {
      const client = new {{pascalCase serviceName}}Client(clientConfig);

      expect(client).toBeDefined();
    });

    it('should use default values for optional config', () => {
      const client = new {{pascalCase serviceName}}Client(validConfig);

      expect(client).toBeDefined();
    });
  });

  describe('getRateLimit', () => {
    it('should return null initially', () => {
      const client = new {{pascalCase serviceName}}Client(clientConfig);

      expect(client.getRateLimit()).toBeNull();
    });
  });

  // Note: Additional client tests require mocking fetch/network
  // These should be added based on specific API requirements
});
{{/if}}
