// lib/__tests__/og-image-generator.test.tsx
import {
  buildOgImageParams,
  OgImageConfig,
  getHeroImageUrl,
  extractFirstImageFromPageContent,
} from '../og-image-generator';

describe('buildOgImageParams', () => {
  it('should include AMSOIL logo always', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
    };
    const params = buildOgImageParams(config);
    expect(params.showAmsoilLogo).toBe(true);
  });

  it('should include dealer logo when logoUrl is set', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
      logoUrl: 'https://example.com/logo.png',
    };
    const params = buildOgImageParams(config);
    expect(params.dealerLogoUrl).toBe('https://example.com/logo.png');
  });

  it('should not include dealer logo when logoUrl is empty', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
      logoUrl: '',
    };
    const params = buildOgImageParams(config);
    expect(params.dealerLogoUrl).toBeUndefined();
  });

  it('should show contact name only when showContactName is true', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
      contactName: 'John Doe',
      showContactName: true,
    };
    const params = buildOgImageParams(config);
    expect(params.contactName).toBe('John Doe');
  });

  it('should hide contact name when showContactName is false', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
      contactName: 'John Doe',
      showContactName: false,
    };
    const params = buildOgImageParams(config);
    expect(params.contactName).toBeUndefined();
  });

  it('should use contactName as the display name when there is no businessName and the dealer opted in', () => {
    const config: OgImageConfig = {
      businessName: null,
      contactName: 'John Doe',
      showContactName: true,
    };
    const params = buildOgImageParams(config);
    // contactName becomes the display name, so the separate contact line is omitted
    expect(params.businessName).toBe('John Doe');
    expect(params.contactName).toBeUndefined();
  });

  it('must NOT use contactName as the display name when showContactName is false (privacy gate)', () => {
    const config: OgImageConfig = {
      businessName: null,
      contactName: 'John Doe',
      showContactName: false,
    };
    const params = buildOgImageParams(config);
    expect(params.businessName).toBe('AMSOIL Independent Dealer');
    expect(JSON.stringify(params)).not.toContain('John Doe');
  });

  it('should show location only when hideAddress is false', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
      city: 'Denver',
      state: 'CO',
      hideAddress: false,
    };
    const params = buildOgImageParams(config);
    expect(params.location).toBe('Denver, CO');
  });

  it('should hide location when hideAddress is true', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
      city: 'Denver',
      state: 'CO',
      hideAddress: true,
    };
    const params = buildOgImageParams(config);
    expect(params.location).toBeUndefined();
  });

  it('should use "AMSOIL Independent Dealer" as fallback business name', () => {
    const config: OgImageConfig = {};
    const params = buildOgImageParams(config);
    expect(params.businessName).toBe('AMSOIL Independent Dealer');
  });

  // Edge cases for null vs undefined
  it('should handle null businessName same as undefined', () => {
    const config: OgImageConfig = { businessName: null };
    const params = buildOgImageParams(config);
    expect(params.businessName).toBe('AMSOIL Independent Dealer');
  });

  it('should not duplicate contactName when it is used as the display name fallback', () => {
    const config: OgImageConfig = {
      businessName: null,
      contactName: 'John Doe',
      showContactName: true,
    };
    const params = buildOgImageParams(config);
    expect(params.businessName).toBe('John Doe');
    expect(params.contactName).toBeUndefined();
  });

  it('should not duplicate contactName when businessName and contactName are identical', () => {
    const config: OgImageConfig = {
      businessName: 'John Doe',
      contactName: 'John Doe',
      showContactName: true,
    };
    const params = buildOgImageParams(config);
    expect(params.businessName).toBe('John Doe');
    expect(params.contactName).toBeUndefined();
  });

  it('should not use contactName as display name when showContactName is false', () => {
    const config: OgImageConfig = {
      businessName: null,
      contactName: 'John Doe',
      showContactName: false,
    };
    const params = buildOgImageParams(config);
    expect(params.businessName).toBe('AMSOIL Independent Dealer');
    expect(params.contactName).toBeUndefined();
  });

  it('should hide contact name when showContactName is null (treated as falsy)', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
      contactName: 'John Doe',
      showContactName: null,
    };
    const params = buildOgImageParams(config);
    expect(params.contactName).toBeUndefined();
  });

  it('should not show location when city is missing', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
      state: 'CO',
      hideAddress: false,
    };
    const params = buildOgImageParams(config);
    expect(params.location).toBeUndefined();
  });

  it('should not show location when state is missing', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
      city: 'Denver',
      hideAddress: false,
    };
    const params = buildOgImageParams(config);
    expect(params.location).toBeUndefined();
  });

  it('should not include dealer logo when logoUrl is null', () => {
    const config: OgImageConfig = {
      businessName: 'Test Dealer',
      logoUrl: null,
    };
    const params = buildOgImageParams(config);
    expect(params.dealerLogoUrl).toBeUndefined();
  });
});

describe('getHeroImageUrl', () => {
  describe('modern SliderContent format', () => {
    it('should extract image from SliderContent with slides[].image.url structure', () => {
      const heroSlider = {
        slides: [
          { image: { url: 'https://example.com/hero1.jpg' } },
          { image: { url: 'https://example.com/hero2.jpg' } },
        ],
      };
      const result = getHeroImageUrl(heroSlider, null);
      expect(result).toBe('https://example.com/hero1.jpg');
    });

    it('should return default when SliderContent has empty slides array', () => {
      const heroSlider = { slides: [] };
      const result = getHeroImageUrl(heroSlider, null);
      expect(result).toBe('/images/slider-defaults/hero-1.jpg');
    });

    it('should return default when slide has no image', () => {
      const heroSlider = { slides: [{}] };
      const result = getHeroImageUrl(heroSlider, null);
      expect(result).toBe('/images/slider-defaults/hero-1.jpg');
    });

    it('should return default when image has no url', () => {
      const heroSlider = { slides: [{ image: {} }] };
      const result = getHeroImageUrl(heroSlider, null);
      expect(result).toBe('/images/slider-defaults/hero-1.jpg');
    });

    it('should skip inactive first slide and use next active slide', () => {
      const heroSlider = {
        slides: [
          { active: false, image: { url: 'https://example.com/hidden.jpg' } },
          { active: true, image: { url: 'https://example.com/shown.jpg' } },
        ],
      };
      const result = getHeroImageUrl(heroSlider, null);
      expect(result).toBe('https://example.com/shown.jpg');
    });

    it('should return default when all slides are inactive', () => {
      const heroSlider = {
        slides: [
          { active: false, image: { url: 'https://example.com/a.jpg' } },
          { active: false, image: { url: 'https://example.com/b.jpg' } },
        ],
      };
      const result = getHeroImageUrl(heroSlider, null);
      expect(result).toBe('/images/slider-defaults/hero-1.jpg');
    });
  });

  describe('legacy flat array format', () => {
    it('should return first hero slider image when available', () => {
      const heroSlider = [
        { imageUrl: 'https://example.com/hero1.jpg' },
        { imageUrl: 'https://example.com/hero2.jpg' },
      ];
      const result = getHeroImageUrl(heroSlider, null);
      expect(result).toBe('https://example.com/hero1.jpg');
    });

    it('should handle image property in legacy format', () => {
      const heroSlider = [{ image: 'https://example.com/hero.jpg' }];
      const result = getHeroImageUrl(heroSlider, null);
      expect(result).toBe('https://example.com/hero.jpg');
    });

    it('should handle src property in legacy format', () => {
      const heroSlider = [{ src: 'https://example.com/hero.jpg' }];
      const result = getHeroImageUrl(heroSlider, null);
      expect(result).toBe('https://example.com/hero.jpg');
    });

    it('should return default hero when heroSlider is empty array', () => {
      const result = getHeroImageUrl([], null);
      expect(result).toBe('/images/slider-defaults/hero-1.jpg');
    });
  });

  describe('fallback behavior', () => {
    it('should return default hero when heroSlider is null', () => {
      const result = getHeroImageUrl(null, null);
      expect(result).toBe('/images/slider-defaults/hero-1.jpg');
    });

    it('should return default hero when heroSlider is undefined', () => {
      const result = getHeroImageUrl(undefined, null);
      expect(result).toBe('/images/slider-defaults/hero-1.jpg');
    });
  });
});

describe('extractFirstImageFromPageContent', () => {
  it('should extract image URL from Puck content', () => {
    const pageContent = {
      content: [{ type: 'Hero', props: { imageUrl: 'https://example.com/page-hero.jpg' } }],
    };
    const result = extractFirstImageFromPageContent(pageContent);
    expect(result).toBe('https://example.com/page-hero.jpg');
  });

  it('should return null when no images in content', () => {
    const pageContent = {
      content: [{ type: 'Text', props: { text: 'Hello world' } }],
    };
    const result = extractFirstImageFromPageContent(pageContent);
    expect(result).toBeNull();
  });

  it('should find nested images', () => {
    const pageContent = {
      content: [
        {
          type: 'Section',
          props: {
            children: [{ type: 'Image', props: { src: 'https://example.com/nested.jpg' } }],
          },
        },
      ],
    };
    const result = extractFirstImageFromPageContent(pageContent);
    expect(result).toBe('https://example.com/nested.jpg');
  });

  // Edge cases
  it('should return null for null content', () => {
    const result = extractFirstImageFromPageContent(null);
    expect(result).toBeNull();
  });

  it('should return null for undefined content', () => {
    const result = extractFirstImageFromPageContent(undefined);
    expect(result).toBeNull();
  });

  it('should return null for primitive values', () => {
    expect(extractFirstImageFromPageContent('string')).toBeNull();
    expect(extractFirstImageFromPageContent(123)).toBeNull();
    expect(extractFirstImageFromPageContent(true)).toBeNull();
  });

  it('should return null for empty object', () => {
    const result = extractFirstImageFromPageContent({});
    expect(result).toBeNull();
  });

  it('should reject URLs that do not start with http or /', () => {
    const pageContent = {
      content: [{ type: 'Hero', props: { imageUrl: 'javascript:alert(1)' } }],
    };
    const result = extractFirstImageFromPageContent(pageContent);
    expect(result).toBeNull();
  });

  it('should accept relative URLs starting with /', () => {
    const pageContent = {
      content: [{ type: 'Hero', props: { imageUrl: '/images/hero.jpg' } }],
    };
    const result = extractFirstImageFromPageContent(pageContent);
    expect(result).toBe('/images/hero.jpg');
  });

  it('should handle deeply nested content up to depth limit', () => {
    // Create content nested 10 levels deep - should find the image
    let deepContent: Record<string, unknown> = {
      props: { imageUrl: 'https://example.com/deep.jpg' },
    };
    for (let i = 0; i < 10; i++) {
      deepContent = { content: [deepContent] };
    }
    const result = extractFirstImageFromPageContent(deepContent);
    expect(result).toBe('https://example.com/deep.jpg');
  });

  it('should return null for content nested beyond depth limit', () => {
    // Create content nested 60 levels deep - should exceed MAX_RECURSION_DEPTH (50)
    let deepContent: Record<string, unknown> = {
      props: { imageUrl: 'https://example.com/tooDeep.jpg' },
    };
    for (let i = 0; i < 60; i++) {
      deepContent = { content: [deepContent] };
    }
    const result = extractFirstImageFromPageContent(deepContent);
    expect(result).toBeNull();
  });
});
