import { describe, it, expect, beforeEach, vi } from 'vitest';
import { TemplateService } from '../src/services/template.service';
import type { TemplateDefinition } from '../src/types/template.types';

describe('TemplateService', () => {
  let templateService: TemplateService;

  beforeEach(() => {
    templateService = TemplateService.getInstance();
    templateService.clearCache();
  });

  describe('resolveTemplate', () => {
    it('resolves an English email template by ID', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'welcome_email',
        locale: 'en',
        variables: { name: 'John', profile_url: 'https://shieldai.app/profile' },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.id).toBe('welcome_email');
      expect(resolved!.channel).toBe('email');
      expect(resolved!.locale).toBe('en');
      expect(resolved!.subject).toContain('John');
      expect(resolved!.body).toContain('John');
      expect(resolved!.body).toContain('https://shieldai.app/profile');
    });

    it('resolves a Spanish email template when locale is es', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'welcome_email',
        locale: 'es',
        variables: { name: 'Juan', profile_url: 'https://shieldai.app/profile' },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.locale).toBe('es');
      expect(resolved!.subject).toContain('Juan');
      expect(resolved!.body).toContain('Bienvenido');
    });

    it('falls back to English when locale is not found', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'welcome_email',
        locale: 'fr',
        variables: { name: 'Pierre', profile_url: 'https://shieldai.app/profile' },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.locale).toBe('en');
    });

    it('falls back to language code match', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'welcome_email',
        locale: 'es-MX',
        variables: { name: 'Maria', profile_url: 'https://shieldai.app/profile' },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.locale).toBe('es');
    });

    it('returns null for unknown template ID', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'nonexistent_template',
        locale: 'en',
      });

      expect(resolved).toBeNull();
    });

    it('substitutes all variables in the template', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'alert_notification',
        locale: 'en',
        variables: {
          alert_type: 'Dark Web Exposure',
          alert_details: 'Email found in breach',
          alert_time: '2026-05-01',
          alert_url: 'https://shieldai.app/alerts/123',
        },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.subject).toBe('ShieldAI Alert: Dark Web Exposure');
      expect(resolved!.body).toContain('Dark Web Exposure');
      expect(resolved!.body).toContain('Email found in breach');
      expect(resolved!.body).toContain('2026-05-01');
      expect(resolved!.body).toContain('https://shieldai.app/alerts/123');
    });

    it('uses default values for optional variables', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'alert_notification',
        locale: 'en',
        variables: {
          alert_type: 'Test Alert',
          alert_details: 'Test details',
        },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.body).toContain('Just now');
    });

    it('keeps unsubstituted variables as-is', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'password_reset',
        locale: 'en',
        variables: {
          name: 'John',
          reset_url: 'https://shieldai.app/reset/abc',
        },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.body).toContain('24');
    });

    it('resolves SMS templates', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'verification_sms',
        locale: 'en',
        variables: { code: '123456' },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.channel).toBe('sms');
      expect(resolved!.body).toContain('123456');
      expect(resolved!.body).toContain('10');
    });

    it('resolves push notification templates', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'alert_push',
        locale: 'en',
        variables: {
          alert_type: 'Voice Clone',
          alert_details: 'Suspicious call detected',
        },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.channel).toBe('push');
      expect(resolved!.subject).toContain('Voice Clone');
      expect(resolved!.body).toBe('Suspicious call detected');
    });
  });

  describe('registerTemplate', () => {
    it('registers a custom template', () => {
      const customTemplate: TemplateDefinition = {
        id: 'custom_welcome',
        name: 'Custom Welcome',
        channel: 'email',
        locale: 'en',
        category: 'onboarding',
        subject: 'Welcome, {{name}}!',
        body: 'Custom welcome message for {{name}}.',
        variables: [
          { name: 'name', type: 'string', required: true },
        ],
      };

      templateService.registerTemplate(customTemplate);

      const resolved = templateService.resolveTemplate({
        templateId: 'custom_welcome',
        locale: 'en',
        variables: { name: 'Alice' },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.subject).toBe('Welcome, Alice!');
      expect(resolved!.body).toBe('Custom welcome message for Alice.');
    });

    it('registers multiple templates at once', () => {
      const templates: TemplateDefinition[] = [
        {
          id: 'bulk_template',
          name: 'Bulk Template',
          channel: 'email',
          locale: 'en',
          category: 'test',
          subject: 'Bulk test',
          body: 'Bulk body {{var1}} {{var2}}',
          variables: [
            { name: 'var1', type: 'string', required: true },
            { name: 'var2', type: 'string', required: true },
          ],
        },
        {
          id: 'bulk_template',
          name: 'Bulk Template ES',
          channel: 'email',
          locale: 'es',
          category: 'test',
          subject: 'Prueba masiva',
          body: 'Cuerpo masivo {{var1}} {{var2}}',
          variables: [
            { name: 'var1', type: 'string', required: true },
            { name: 'var2', type: 'string', required: true },
          ],
        },
      ];

      templateService.registerTemplates(templates);

      const enResolved = templateService.resolveTemplate({
        templateId: 'bulk_template',
        locale: 'en',
        variables: { var1: 'A', var2: 'B' },
      });

      expect(enResolved!.locale).toBe('en');
      expect(enResolved!.body).toBe('Bulk body A B');

      const esResolved = templateService.resolveTemplate({
        templateId: 'bulk_template',
        locale: 'es',
        variables: { var1: 'A', var2: 'B' },
      });

      expect(esResolved!.locale).toBe('es');
      expect(esResolved!.body).toBe('Cuerpo masivo A B');
    });

    it('invalidates cache after registration', () => {
      const template: TemplateDefinition = {
        id: 'cache_test',
        name: 'Cache Test',
        channel: 'email',
        locale: 'en',
        category: 'test',
        subject: 'Original',
        body: 'Original body',
        variables: [],
      };

      templateService.registerTemplate(template);

      templateService.resolveTemplate({
        templateId: 'cache_test',
        locale: 'en',
      });

      const statsBefore = templateService.getCacheStats();
      expect(statsBefore.size).toBeGreaterThan(0);

      templateService.registerTemplate({
        ...template,
        subject: 'Updated',
        body: 'Updated body',
      });

      const resolved = templateService.resolveTemplate({
        templateId: 'cache_test',
        locale: 'en',
      });

      expect(resolved!.subject).toBe('Updated');
    });
  });

  describe('caching', () => {
    it('caches resolved templates', () => {
      templateService.resolveTemplate({
        templateId: 'welcome_email',
        locale: 'en',
        variables: { name: 'Test', profile_url: 'http://test.com' },
      });

      const stats = templateService.getCacheStats();
      expect(stats.size).toBeGreaterThan(0);
    });

    it('clears cache on clearCache call', () => {
      templateService.resolveTemplate({
        templateId: 'welcome_email',
        locale: 'en',
        variables: { name: 'Test', profile_url: 'http://test.com' },
      });

      templateService.clearCache();

      const stats = templateService.getCacheStats();
      expect(stats.size).toBe(0);
    });
  });

  describe('getAvailableLocales', () => {
    it('returns available locales for a template', () => {
      const locales = templateService.getAvailableLocales('welcome_email');
      expect(locales).toContain('en');
      expect(locales).toContain('es');
    });

    it('returns empty array for unknown template', () => {
      const locales = templateService.getAvailableLocales('nonexistent');
      expect(locales).toEqual([]);
    });
  });

  describe('getTemplateIds', () => {
    it('returns all registered template IDs', () => {
      const ids = templateService.getTemplateIds();
      expect(ids).toContain('welcome_email');
      expect(ids).toContain('alert_notification');
      expect(ids).toContain('password_reset');
      expect(ids).toContain('scan_complete');
      expect(ids).toContain('alert_sms');
      expect(ids).toContain('verification_sms');
      expect(ids).toContain('alert_push');
    });
  });

  describe('getTemplateInfo', () => {
    it('returns template metadata', () => {
      const info = templateService.getTemplateInfo('welcome_email');
      expect(info).not.toBeNull();
      expect(info!.id).toBe('welcome_email');
      expect(info!.channel).toBe('email');
      expect(info!.category).toBe('onboarding');
      expect(info!.locales).toContain('en');
      expect(info!.locales).toContain('es');
      expect(info!.variables).toContain('name');
      expect(info!.variables).toContain('profile_url');
    });

    it('returns null for unknown template', () => {
      const info = templateService.getTemplateInfo('nonexistent');
      expect(info).toBeNull();
    });
  });

  describe('locale normalization', () => {
    it('normalizes locale with underscore separator', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'welcome_email',
        locale: 'es_ES',
        variables: { name: 'Test', profile_url: 'http://test.com' },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.locale).toBe('es');
    });

    it('normalizes mixed case locale', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'welcome_email',
        locale: 'EN-US',
        variables: { name: 'Test', profile_url: 'http://test.com' },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.locale).toBe('en');
    });
  });

  describe('variable substitution edge cases', () => {
    it('handles numeric variable values', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'password_reset',
        locale: 'en',
        variables: {
          name: 'John',
          reset_url: 'https://shieldai.app/reset',
          expiry_hours: 48,
        },
      });

      expect(resolved).not.toBeNull();
      expect(resolved!.body).toContain('48');
    });

    it('handles boolean variable values', () => {
      templateService.registerTemplate({
        id: 'bool_test',
        name: 'Bool Test',
        channel: 'email',
        locale: 'en',
        category: 'test',
        subject: 'Test',
        body: 'Value is {{flag}}',
        variables: [
          { name: 'flag', type: 'boolean', required: true },
        ],
      });

      const resolved = templateService.resolveTemplate({
        templateId: 'bool_test',
        locale: 'en',
        variables: { flag: true },
      });

      expect(resolved!.body).toBe('Value is true');
    });

    it('preserves HTML in htmlBody', () => {
      const resolved = templateService.resolveTemplate({
        templateId: 'welcome_email',
        locale: 'en',
        variables: { name: 'John', profile_url: 'https://shieldai.app/profile' },
      });

      expect(resolved!.htmlBody).toContain('<h1>');
      expect(resolved!.htmlBody).toContain('<a href="https://shieldai.app/profile">');
    });
  });
});
