import { BootstrapConfig, StaticPageConfig } from '../../../shared/models/config';
import { ContentPage } from '../models/content-page.model';
import { ContentPageService } from './content-page.service';

function makePage(overrides: Partial<StaticPageConfig> = {}): StaticPageConfig {
  return {
    id: 'about',
    slug: 'about',
    title: 'About',
    translations: { en: { title: 'About', html: '<p>Hello</p>' } },
    ...overrides,
  };
}

function makeContentPage(overrides: Partial<ContentPage> = {}): ContentPage {
  return {
    id: 'about',
    slug: 'about',
    route: 'about',
    title: 'About',
    order: 1,
    showInFooter: true,
    showInHeader: false,
    showInSitemap: true,
    visibility: { desktop: true, tablet: true, mobile: true },
    requiresAuthentication: false,
    translations: { en: { title: 'About', html: '<p>Hello</p>' } },
    enabled: true,
    status: 'published',
    ...overrides,
  };
}

describe('ContentPageService', () => {
  let service: ContentPageService;

  beforeEach(() => {
    service = new ContentPageService();
  });

  describe('normalizePages', () => {
    it('defaults a page with no enabled/status to enabled + published (preserves pre-existing bootstrap data)', () => {
      const [page] = service.normalizePages({ about: makePage() });
      expect(page.enabled).toBeTrue();
      expect(page.status).toBe('published');
    });

    it('respects explicit enabled/status when present', () => {
      const [page] = service.normalizePages({ about: makePage({ enabled: false, status: 'draft' }) });
      expect(page.enabled).toBeFalse();
      expect(page.status).toBe('draft');
    });

    it('defaults route from slug when route is absent', () => {
      const [page] = service.normalizePages({ about: makePage({ slug: 'about-us' }) });
      expect(page.route).toBe('about-us');
    });

    it('keeps an explicitly different route independent of slug', () => {
      const [page] = service.normalizePages({ about: makePage({ slug: 'about-us', route: '/legacy/about' }) });
      expect(page.route).toBe('legacy/about');
    });

    it('normalizes legacy array-format pages as enabled + published', () => {
      const [page] = service.normalizePages([{ key: 'terms', route: '/terms', title: 'Terms' }]);
      expect(page.enabled).toBeTrue();
      expect(page.status).toBe('published');
    });
  });

  describe('resolvePage', () => {
    function bootstrapWith(page: StaticPageConfig): BootstrapConfig {
      return { staticPages: { [page.id]: page } } as unknown as BootstrapConfig;
    }

    it('resolves an enabled, published page', () => {
      const resolved = service.resolvePage(bootstrapWith(makePage()), 'about', 'en');
      expect(resolved).not.toBeNull();
      expect(resolved?.html).toBe('<p>Hello</p>');
    });

    it('returns null for a disabled page even though it exists', () => {
      const resolved = service.resolvePage(bootstrapWith(makePage({ enabled: false })), 'about', 'en');
      expect(resolved).toBeNull();
    });

    it('returns null for a draft page', () => {
      const resolved = service.resolvePage(bootstrapWith(makePage({ status: 'draft' })), 'about', 'en');
      expect(resolved).toBeNull();
    });

    it('returns null for a page that does not exist', () => {
      const resolved = service.resolvePage(bootstrapWith(makePage()), 'missing', 'en');
      expect(resolved).toBeNull();
    });
  });

  describe('validatePages', () => {
    it('reports no issues for two distinct, valid pages', () => {
      const pages = [makeContentPage({ id: 'a', slug: 'a', route: 'a' }), makeContentPage({ id: 'b', slug: 'b', route: 'b' })];
      const result = service.validatePages(pages);
      expect(result.duplicateSlugs).toEqual([]);
      expect(result.duplicateRoutes).toEqual([]);
      expect(result.emptyTitles).toEqual([]);
      expect(result.invalidHtml).toEqual([]);
      expect(result.invalidSeo).toEqual([]);
    });

    it('flags duplicate routes even when slugs differ', () => {
      const pages = [
        makeContentPage({ id: 'a', slug: 'a-page', route: 'shared' }),
        makeContentPage({ id: 'b', slug: 'b-page', route: 'shared' }),
      ];
      expect(service.validatePages(pages).duplicateRoutes).toEqual(['shared']);
    });

    it('flags malformed HTML content', () => {
      const pages = [makeContentPage({ translations: { en: { title: 'About', html: '<p>Hello <strong>world</p>' } } })];
      expect(service.validatePages(pages).invalidHtml).toEqual(['about']);
    });

    it('flags an invalid canonical URL and an unknown robots token', () => {
      const pages = [makeContentPage({ seo: { canonical: 'not-a-url', robots: 'maybe' } })];
      expect(service.validatePages(pages).invalidSeo).toEqual(['about']);
    });

    it('accepts a known robots token and a valid canonical URL', () => {
      const pages = [makeContentPage({ seo: { canonical: 'https://dexar.market/about', robots: 'index,follow' } })];
      expect(service.validatePages(pages).invalidSeo).toEqual([]);
    });
  });

  describe('toBootstrapRecord', () => {
    it('round-trips enabled/status/route/media through serialization', () => {
      const page = makeContentPage({ enabled: false, status: 'draft', heroImage: 'hero.png', thumbnail: 'thumb.png', gallery: ['a.png'] });
      const record = service.toBootstrapRecord([page]);
      expect(record['about'].enabled).toBeFalse();
      expect(record['about'].status).toBe('draft');
      expect(record['about'].visible).toBeFalse();
      expect(record['about'].heroImage).toBe('hero.png');
      expect(record['about'].thumbnail).toBe('thumb.png');
      expect(record['about'].gallery).toEqual(['a.png']);
      expect(record['about'].route).toBe('/about');
    });

    it('serializes an explicitly different route', () => {
      const page = makeContentPage({ route: 'legacy/about' });
      const record = service.toBootstrapRecord([page]);
      expect(record['about'].route).toBe('/legacy/about');
    });
  });

  describe('normalizeSlug', () => {
    it('strips leading slashes and trims', () => {
      expect(service.normalizeSlug('/about ')).toBe('about');
    });
  });
});
