import {expect, test} from '@playwright/test';
import dedent from 'dedent';
import * as fs from 'fs';
import {mockGedcomResponse, setupHermeticEnvironment} from './helpers';

test.describe('Details panel visual validation @visual', () => {
  test.beforeEach(async ({context}) => {
    await setupHermeticEnvironment(context);
  });

  test('Complex Names Test', async ({page, context}) => {
    const complexNameGedcom = dedent`
      0 HEAD
      1 GEDC
      2 VERS 5.5.1
      2 FORM Lineage-Linked
      1 CHAR UTF-8
      0 @I1@ INDI
      1 NAME Dr. Bonifacy "Boni" /Gibbs/ III
      2 NPFX Dr.
      2 GIVN Bonifacy
      2 NICK Boni
      2 SURN Gibbs
      2 NSFX III
      2 _RUFNAME Bonifacy
      1 SEX M
      1 FAMS @F1@
      0 @F1@ FAM
      1 HUSB @I1@
      0 TRLR
    `;

    await mockGedcomResponse(context, complexNameGedcom);

    await page.goto('/#/view?url=https://example.org/family.ged');
    const sidebar = page.locator('#sidebar');
    await sidebar.waitFor();
    await expect(sidebar).toHaveScreenshot('details-complex-name.png');
  });

  test('Image / Photo Rendering Test', async ({page, context}) => {
    const photoGedcom = dedent`
      0 HEAD
      1 GEDC
      2 VERS 5.5.1
      2 FORM Lineage-Linked
      1 CHAR UTF-8
      0 @I1@ INDI
      1 NAME Bonifacy /Gibbs/
      1 SEX M
      1 FAMS @F1@
      1 OBJE @O1@
      0 @O1@ OBJE
      1 FILE http://example.org/photos/I1.jpg
      2 FORM jpeg
      0 @F1@ FAM
      1 HUSB @I1@
      0 TRLR
    `;

    await mockGedcomResponse(context, photoGedcom);

    await context.route('**/photos/I1.jpg', async (route) => {
      const imageBuffer = fs.readFileSync(
        'docker/examples/photos/photos/I1.jpg',
      );
      await route.fulfill({
        status: 200,
        contentType: 'image/jpeg',
        body: imageBuffer,
      });
    });

    await page.goto('/#/view?url=https://example.org/family.ged');
    const sidebar = page.locator('#sidebar');
    await sidebar.waitFor();

    // Wait for image loading to complete
    const img = sidebar.locator('img').first();
    await img.waitFor({state: 'visible'});
    await img.evaluate((image) => {
      return new Promise((resolve, reject) => {
        if ((image as HTMLImageElement).complete) resolve(true);
        image.addEventListener('load', () => resolve(true));
        image.addEventListener('error', () =>
          reject(new Error('Image failed to load')),
        );
      });
    });

    await expect(sidebar).toHaveScreenshot('details-photo-render.png');
  });

  test('Custom Facts & Citations Test', async ({page, context}) => {
    const customFactsGedcom = dedent`
      0 HEAD
      1 GEDC
      2 VERS 5.5.1
      2 FORM Lineage-Linked
      1 CHAR UTF-8
      0 @I1@ INDI
      1 NAME Bonifacy /Gibbs/
      1 SEX M
      1 FAMS @F1@
      1 FACT Custom fact data
      2 TYPE Custom Fact Type
      2 SOUR @S1@
      3 PAGE 42
      3 DATA
      4 DATE 12 JAN 1850
      2 NOTE This is a note nested under a custom fact.
      1 BIRT
      2 DATE 1 JAN 1800
      2 PLAC Paris, France
      2 SOUR @S1@
      3 PAGE 10
      2 NOTE Birth event note.
      1 DEAT
      2 DATE 31 DEC 1880
      2 PLAC London, UK
      1 NOTE This is a top-level note for the individual.
      0 @S1@ SOUR
      1 TITL Great Genealogy Book
      1 AUTH John Doe
      1 PUBL London Publishing, 1890
      0 @F1@ FAM
      1 HUSB @I1@
      0 TRLR
    `;

    await mockGedcomResponse(context, customFactsGedcom);

    await page.goto('/#/view?url=https://example.org/family.ged');
    const sidebar = page.locator('#sidebar');
    await sidebar.waitFor();
    await expect(sidebar).toHaveScreenshot('details-events-sources.png');
  });

  test('Immediate Family Rendering Test', async ({page, context}) => {
    const immediateFamilyGedcom = dedent`
      0 HEAD
      1 GEDC
      2 VERS 5.5.1
      2 FORM Lineage-Linked
      1 CHAR UTF-8
      0 @I1@ INDI
      1 NAME Focus /Person/
      1 SEX M
      1 FAMC @F1@
      1 FAMS @F2@
      1 FAMS @F3@
      0 @I2@ INDI
      1 NAME Father /Person/
      1 SEX M
      1 FAMS @F1@
      0 @I3@ INDI
      1 NAME Mother /Person/
      1 SEX F
      1 FAMS @F1@
      0 @I4@ INDI
      1 NAME Spouse /Person/
      1 SEX F
      1 FAMS @F2@
      0 @I5@ INDI
      1 NAME Older /Child/
      1 SEX M
      1 BIRT
      2 DATE 1 JAN 2000
      1 FAMC @F2@
      0 @I6@ INDI
      1 NAME Younger /Child/
      1 SEX F
      1 BIRT
      2 DATE 1 JAN 2005
      1 FAMC @F2@
      0 @I7@ INDI
      1 NAME Half /Child/
      1 SEX M
      1 BIRT
      2 DATE 1 JAN 2010
      1 FAMC @F3@
      0 @F1@ FAM
      1 HUSB @I2@
      1 WIFE @I3@
      1 CHIL @I1@
      0 @F2@ FAM
      1 HUSB @I1@
      1 WIFE @I4@
      1 CHIL @I5@
      1 CHIL @I6@
      0 @F3@ FAM
      1 HUSB @I1@
      1 CHIL @I7@
      0 TRLR
    `;

    await mockGedcomResponse(context, immediateFamilyGedcom);

    await page.goto('/#/view?url=https://example.org/family.ged');
    const sidebar = page.locator('#sidebar');
    await sidebar.waitFor();
    await expect(sidebar).toHaveScreenshot('details-immediate-family.png');
  });

  test('Media Fallback Rendering Test', async ({page, context}) => {
    const fallbackGedcom = dedent`
      0 HEAD
      1 GEDC
      2 VERS 5.5.1
      2 FORM Lineage-Linked
      1 CHAR UTF-8
      0 @I1@ INDI
      1 NAME Bonifacy /Gibbs/
      1 SEX M
      1 FAMS @F1@
      1 OBJE @O1@
      0 @O1@ OBJE
      1 FILE photos/not_uploaded_image.jpg
      2 FORM jpeg
      2 TITL A Not Uploaded Image
      0 @F1@ FAM
      1 HUSB @I1@
      0 TRLR
    `;

    await mockGedcomResponse(context, fallbackGedcom);

    await page.goto('/#/view?url=https://example.org/family.ged');
    const sidebar = page.locator('#sidebar');
    await sidebar.waitFor();

    // Verify fallback placeholder text is present
    await expect(sidebar.getByText('File not uploaded').first()).toBeVisible();
    await expect(
      sidebar.getByText('A Not Uploaded Image').first(),
    ).toBeVisible();

    await expect(sidebar).toHaveScreenshot('details-media-fallback.png');
  });
});
