import path from 'path';
import { ContentApi } from '@squiz/component-web-api-lib';
import {
  addComponentSet,
  contentService,
  deleteComponents,
  deleteComponentSet,
  deleteContentItem,
  deleteContentSchema,
  getTestComponent,
  pageRenderService,
  uploadTestComponent,
} from './helper';
import fsp from 'fs/promises';
import { buildDevelopmentSession } from '@squiz/dxp-session-lib';
import { DxpCacheAccess, DxpSession, DxpSessionVersion } from '@squiz/dxp-session-lib';
import {
  COMPONENT_CONTENT_ID,
  COMPONENT_NAME,
  COMPONENT_NODE_ID,
  COMPONENT_SET_WEB_PATH,
  componentContentItem,
  componentSet,
  pageContents,
  pageContentsWithVariants,
} from './upload-and-render-page.integration.mocks';

describe('PageRenderController- Integration', () => {
  let PAGE_CONTENT_ID: string;
  const testFilesDir = path.resolve(__dirname, 'test-files');
  const pageContentIds: string[] = [];
  const createPage = async (page: ContentApi.PageContentsCreate): Promise<string> => {
    try {
      const response = await contentService.post('page-contents', page);
      pageContentIds.push(response.data.id);
      return response.data.id;
    } catch (error) {
      console.log('error', error, JSON.stringify((error as any).response.data));
      throw error;
    }
  };

  beforeAll(async () => {
    await fsp.rm(testFilesDir, { force: true, recursive: true });
    await fsp.mkdir(testFilesDir);
    // Component Configuration
    await uploadTestComponent('/__components__/test-page-render', testFilesDir);
    await addComponentSet(componentSet);
    // Post component items
    await contentService.post('content-item', componentContentItem);
  });

  afterAll(async () => {
    await deleteContentItem(componentContentItem.id!);
    await deleteContentSchema(COMPONENT_NODE_ID);
    await deleteComponentSet(COMPONENT_SET_WEB_PATH);
    await deleteComponents(await getTestComponent(COMPONENT_NAME));
    await Promise.all(pageContentIds.map((id) => contentService.delete(`page-contents/${id}`)));
  });

  it('should render a page', async () => {
    PAGE_CONTENT_ID = await createPage(pageContents);

    const mockSession = buildDevelopmentSession({
      version: DxpSessionVersion.version1,
    });
    const page = await pageRenderService.get(`p/${PAGE_CONTENT_ID}`, {
      headers: { 'x-dxp-session': mockSession },
    });
    expect(page.data).toEqual(
      `<div class="container"><h1>Hello World!</h1><esi:include src="/__dxp/au/components-render/${process.env.TENANT_ID}/r/unit-test-components/test-page-render/1.0.0/main?_componentSet=${COMPONENT_SET_WEB_PATH}&_contentItemId=${COMPONENT_CONTENT_ID}"/><p>Bottom text</p></div>`,
    );
  });

  describe('should render a page with variations', () => {
    beforeAll(async () => {
      PAGE_CONTENT_ID = await createPage(pageContentsWithVariants);
    });

    it.each([
      [
        'a segment variant',
        {
          version: DxpSessionVersion.version1,
          cdp: {
            anonymous: false,
            customerid: 'test-id-123',
            segments: ['is-authenticated'],
          },
        },
        '<div class="container"><h1>Hello Authenticated User!</h1></div>',
        {
          version: DxpSessionVersion.version1,
          cdp: {
            segments: ['is-authenticated'],
          },
          optimize: {
            experiments: [{ id: 'experiment1', variant: 'B' }],
          },
        },
      ],
      [
        'another segment variant',
        {
          version: DxpSessionVersion.version1,
          cdp: {
            anonymous: false,
            customerid: 'test-id-123',
            segments: ['is-unauthenticated'],
          },
        },
        '<div class="container"><h1>Hello Unauthenticated User!</h1></div>',
        {
          version: DxpSessionVersion.version1,
          cdp: {
            segments: ['is-authenticated', 'is-unauthenticated'],
          },
          optimize: {
            experiments: [],
          },
        },
      ],
      [
        'an experiment variant',
        {
          version: DxpSessionVersion.version1,
          cdp: {
            anonymous: false,
            customerid: 'test-id-123',
            segments: ['is-authenticated'],
          },
          optimize: {
            experiments: [{ id: 'experiment1', variant: 'B' }],
          },
        },
        '<div class="container"><h1>Hello Authenticated User with experiment B!</h1></div>',
        {
          version: DxpSessionVersion.version1,
          cdp: {
            segments: ['is-authenticated'],
          },
          optimize: {
            experiments: [{ id: 'experiment1', variant: 'B' }],
          },
        },
      ],
      [
        'the default variant',
        {
          version: DxpSessionVersion.version1,
          cdp: {
            anonymous: false,
            customerid: 'test-id-123',
            segments: ['not-valid'],
          },
        },
        '<div class="container"><h1>Hello World!</h1></div>',
        {
          version: DxpSessionVersion.version1,
          cdp: {
            segments: ['is-authenticated', 'is-unauthenticated'],
          },
          optimize: {
            experiments: [],
          },
        },
      ],
    ])(
      'renders the matching variation for %s',
      async (description: string, session: DxpSession, expectedBody: string, expectedCacheAccess: DxpCacheAccess) => {
        const page = await pageRenderService.get(`p/${PAGE_CONTENT_ID}`, {
          headers: { 'x-dxp-session': buildDevelopmentSession(session) },
        });
        const dxpCacheAccess = JSON.parse(Buffer.from(page.headers['x-dxp-cache-access'], 'base64').toString());

        expect(page.data).toEqual(expectedBody);
        expect(dxpCacheAccess).toEqual(expectedCacheAccess);
      },
    );
  });
});
