/**
 * Tests for landing page template generator
 */
import { describe, it, expect } from 'vitest';

import {
  generateSaaSLandingPageTemplate,
  LANDING_PAGE_TEMPLATES,
  validatePuckData,
} from '../templates';

describe('Landing Page Templates', () => {
  describe('LANDING_PAGE_TEMPLATES', () => {
    it('should include SaaS Landing Page (Dark Hero) template', () => {
      const template = LANDING_PAGE_TEMPLATES.find(t => t.id === 'saas-dark-hero');
      expect(template).toBeDefined();
      expect(template?.name).toBe('SaaS Landing Page (Dark Hero)');
      expect(template?.description).toBeDefined();
      expect(template?.thumbnail).toBeDefined();
    });

    it('should have generate function for each template', () => {
      LANDING_PAGE_TEMPLATES.forEach(template => {
        expect(typeof template.generate).toBe('function');
      });
    });
  });

  describe('generateSaaSLandingPageTemplate', () => {
    it('should return valid Puck data structure', () => {
      const data = generateSaaSLandingPageTemplate();

      expect(data).toHaveProperty('content');
      expect(data).toHaveProperty('root');
      expect(Array.isArray(data.content)).toBe(true);
    });

    it('should include all required sections', () => {
      const data = generateSaaSLandingPageTemplate();
      const componentTypes = data.content.map((c: { type: string }) => c.type);

      // Verify all required sections are present
      expect(componentTypes).toContain('TopNav');
      expect(componentTypes).toContain('HeroSaaS');
      expect(componentTypes).toContain('LogoCloud');
      expect(componentTypes).toContain('FeatureSplit');
      expect(componentTypes).toContain('CTASection');
      expect(componentTypes).toContain('StatsStrip');
      expect(componentTypes).toContain('GalleryGrid');
      expect(componentTypes).toContain('TestimonialCarousel');
      expect(componentTypes).toContain('VideoFeature');
      expect(componentTypes).toContain('AlternatingFeatures');
      expect(componentTypes).toContain('PricingPlans');
      expect(componentTypes).toContain('FooterMega');
      expect(componentTypes).toContain('FAQAccordion');
    });

    it('should generate unique IDs for all components', () => {
      const data = generateSaaSLandingPageTemplate();
      const ids = data.content.map((c: { props: { id: string } }) => c.props.id);

      // Check all IDs are unique
      const uniqueIds = new Set(ids);
      expect(uniqueIds.size).toBe(ids.length);
    });

    it('should include placeholder content in each section', () => {
      const data = generateSaaSLandingPageTemplate();

      data.content.forEach((component: { type: string; props: Record<string, unknown> }) => {
        expect(component.props).toBeDefined();
        // Each component should have some props set
        expect(Object.keys(component.props).length).toBeGreaterThan(0);
      });
    });

    describe('HeroSaaS section', () => {
      it('should have headline and subheadline', () => {
        const data = generateSaaSLandingPageTemplate();
        const hero = data.content.find((c: { type: string }) => c.type === 'HeroSaaS');

        expect(hero.props.headline).toBeDefined();
        expect(hero.props.subheadline).toBeDefined();
        expect(hero.props.headline.length).toBeGreaterThan(0);
      });

      it('should have primary CTA', () => {
        const data = generateSaaSLandingPageTemplate();
        const hero = data.content.find((c: { type: string }) => c.type === 'HeroSaaS');

        expect(hero.props.primaryCta).toBeDefined();
        expect(hero.props.primaryCta.text).toBeDefined();
        expect(hero.props.primaryCta.href).toBeDefined();
      });

      it('should have dark gradient background', () => {
        const data = generateSaaSLandingPageTemplate();
        const hero = data.content.find((c: { type: string }) => c.type === 'HeroSaaS');

        expect(hero.props.backgroundVariant).toBe('gradient');
        expect(hero.props.gradientPreset).toBeDefined();
      });

      it('should have hero image/mockup', () => {
        const data = generateSaaSLandingPageTemplate();
        const hero = data.content.find((c: { type: string }) => c.type === 'HeroSaaS');

        expect(hero.props.heroImage).toBeDefined();
        expect(hero.props.heroImage.src).toBeDefined();
      });
    });

    describe('LogoCloud section', () => {
      it('should have multiple logos', () => {
        const data = generateSaaSLandingPageTemplate();
        const logoCloud = data.content.find((c: { type: string }) => c.type === 'LogoCloud');

        expect(logoCloud.props.logos).toBeDefined();
        expect(Array.isArray(logoCloud.props.logos)).toBe(true);
        expect(logoCloud.props.logos.length).toBeGreaterThanOrEqual(4);
      });
    });

    describe('PricingPlans section', () => {
      it('should have 3 pricing plans', () => {
        const data = generateSaaSLandingPageTemplate();
        const pricing = data.content.find((c: { type: string }) => c.type === 'PricingPlans');

        expect(pricing.props.plans).toBeDefined();
        expect(pricing.props.plans.length).toBe(3);
      });

      it('should highlight the middle plan', () => {
        const data = generateSaaSLandingPageTemplate();
        const pricing = data.content.find((c: { type: string }) => c.type === 'PricingPlans');

        expect(pricing.props.highlightIndex).toBe(1);
      });

      it('should have currency and billing period', () => {
        const data = generateSaaSLandingPageTemplate();
        const pricing = data.content.find((c: { type: string }) => c.type === 'PricingPlans');

        expect(pricing.props.currency).toBeDefined();
        expect(pricing.props.billingPeriod).toBeDefined();
      });
    });

    describe('TestimonialCarousel section', () => {
      it('should have multiple testimonials', () => {
        const data = generateSaaSLandingPageTemplate();
        const testimonials = data.content.find((c: { type: string }) => c.type === 'TestimonialCarousel');

        expect(testimonials.props.items).toBeDefined();
        expect(testimonials.props.items.length).toBeGreaterThanOrEqual(3);
      });
    });

    describe('FAQAccordion section', () => {
      it('should have multiple Q&A items', () => {
        const data = generateSaaSLandingPageTemplate();
        const faq = data.content.find((c: { type: string }) => c.type === 'FAQAccordion');

        expect(faq.props.items).toBeDefined();
        expect(faq.props.items.length).toBeGreaterThanOrEqual(4);
      });
    });

    describe('VideoFeature section', () => {
      it('should have a valid video configuration', () => {
        const data = generateSaaSLandingPageTemplate();
        const video = data.content.find((c: { type: string }) => c.type === 'VideoFeature');

        expect(video.props.provider).toMatch(/^(youtube|vimeo)$/);
        expect(video.props.videoId).toBeDefined();
      });
    });
  });

  describe('validatePuckData', () => {
    it('should accept valid Puck data', () => {
      const validData = {
        content: [{ type: 'HeroSaaS', props: { id: 'hero-1', headline: 'Test' } }],
        root: {},
      };

      const result = validatePuckData(validData);
      expect(result.isValid).toBe(true);
    });

    it('should reject data without content array', () => {
      const invalidData = { root: {} };

      const result = validatePuckData(invalidData);
      expect(result.isValid).toBe(false);
      expect(result.error).toContain('content');
    });

    it('should reject data with non-array content', () => {
      const invalidData = { content: 'not an array', root: {} };

      const result = validatePuckData(invalidData);
      expect(result.isValid).toBe(false);
    });

    it('should reject components without type', () => {
      const invalidData = {
        content: [{ props: { id: 'test' } }],
        root: {},
      };

      const result = validatePuckData(invalidData);
      expect(result.isValid).toBe(false);
      expect(result.error).toContain('type');
    });

    it('should validate generated template', () => {
      const data = generateSaaSLandingPageTemplate();
      const result = validatePuckData(data);

      expect(result.isValid).toBe(true);
    });
  });
});

describe('Block Presets', () => {
  describe('HeroSaaS presets', () => {
    it('should have dark gradient centered preset', () => {
      const { BLOCK_PRESETS } = require('../templates');
      const heroPresets = BLOCK_PRESETS.HeroSaaS;

      expect(heroPresets).toBeDefined();
      const darkCentered = heroPresets.find(
        (p: { id: string }) => p.id === 'dark-gradient-centered'
      );
      expect(darkCentered).toBeDefined();
      expect(darkCentered.props.backgroundVariant).toBe('gradient');
      expect(darkCentered.props.alignment).toBe('center');
    });
  });

  describe('PricingPlans presets', () => {
    it('should have 3-card highlighted middle preset', () => {
      const { BLOCK_PRESETS } = require('../templates');
      const pricingPresets = BLOCK_PRESETS.PricingPlans;

      expect(pricingPresets).toBeDefined();
      const threeCard = pricingPresets.find(
        (p: { id: string }) => p.id === 'three-card-highlighted'
      );
      expect(threeCard).toBeDefined();
      expect(threeCard.props.highlightIndex).toBe(1);
    });
  });
});
