import React from 'react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { LayoutRenderer } from '../src/platform/components/runtime/LayoutRenderer';

vi.mock('@nexuscrm/host-sdk', async () => {
  const ReactModule = await import('react');
  const LayoutInlineEditField = (props: {
    field: { name: string };
    inputId?: string;
    ariaInvalid?: boolean;
    ariaDescribedBy?: string;
    onValidationFailures?: (failures: Array<{
      field?: string;
      label?: string;
      message: string;
      text: string;
    }>) => void;
  }) => ReactModule.createElement('button', {
    type: 'button',
    id: props.inputId,
    'aria-invalid': props.ariaInvalid || undefined,
    'aria-describedby': props.ariaDescribedBy,
    onClick: () => props.onValidationFailures?.(props.field.name === 'Name'
      ? [
        {
          field: 'FirstName',
          label: 'First Name',
          message: 'is required',
          text: 'First Name is required',
        },
        {
          field: 'LastName',
          label: 'Last Name',
          message: 'is required',
          text: 'Last Name is required',
        },
      ]
      : [
        {
          field: 'Collapsed__c',
          label: 'Collapsed Field',
          message: 'is required',
          text: 'Collapsed Field is required',
        },
        {
          field: 'Absent__c',
          label: 'Absent Field',
          message: 'is required',
          text: 'Absent Field is required',
        },
      ]),
  }, `Edit ${props.field.name}`);

  const layoutFieldItemResolver = (input: {
    fieldComponents: Array<{ apiName?: string; value?: string }>;
    objectFields?: Array<{ name: string; label?: string }>;
    record: Record<string, unknown>;
  }) => {
    const names = input.fieldComponents.map(component => component.apiName || component.value);
    if (input.fieldComponents.length < 2 || !names.includes('LastName')) return undefined;
    const permissionField = input.objectFields?.find(candidate => candidate.name === 'LastName');
    if (!permissionField) return undefined;
    return {
      permissionField,
      renderField: { ...permissionField, name: 'Name', label: 'Name' },
      label: 'Name',
      value: input.record.Name,
    };
  };

  return {
    hostApps: {
      apps: new Map([
        ['validation-test', {
          shellComponents: {
            layoutFieldItemResolver,
            layoutInlineEditField: LayoutInlineEditField,
          },
        }],
      ]),
    },
  };
});

const field = (name: string, label: string) => ({
  name,
  label,
  type: 'string',
  readable: true,
  updateable: true,
  createable: true,
  nillable: true,
});

const layout = {
  id: 'layout-validation-test',
  sections: [
    {
      id: 'general',
      heading: 'General',
      layoutRows: [{
        layoutItems: [
          {
            layoutComponents: [{ componentType: 'Field', apiName: 'Publisher__c' }],
          },
          {
            label: 'Name',
            layoutComponents: [
              { componentType: 'Field', apiName: 'FirstName' },
              { componentType: 'Field', apiName: 'LastName' },
            ],
          },
        ],
      }],
    },
    {
      id: 'system',
      heading: 'System Information',
      layoutRows: [{
        layoutItems: [{
          layoutComponents: [{ componentType: 'Field', apiName: 'Collapsed__c' }],
        }],
      }],
    },
  ],
};

const metadata = {
  name: 'Account',
  label: 'Account',
  fields: [
    field('Publisher__c', 'Publisher'),
    field('Collapsed__c', 'Collapsed Field'),
    field('Absent__c', 'Absent Field'),
    field('FirstName', 'First Name'),
    field('LastName', 'Last Name'),
  ],
};

describe('detail validation checklist navigation', () => {
  beforeEach(() => {
    Object.defineProperty(HTMLElement.prototype, 'scrollIntoView', {
      configurable: true,
      value: vi.fn(),
    });
  });

  it('survives equivalent layout rerenders, expands a target section, and never links absent fields', async () => {
    const record = { Id: 'account-1', Publisher__c: '', Collapsed__c: '' };
    const view = render(
      <LayoutRenderer
        layout={layout as never}
        record={record}
        objectMetadata={metadata as never}
        onUpdate={async () => undefined}
        fieldSurfacePolicyScope="validation-test"
      />,
    );

    await waitFor(() => {
      expect(screen.queryByRole('button', { name: 'Edit Collapsed__c' })).not.toBeInTheDocument();
    });
    fireEvent.click(screen.getByRole('button', { name: 'Edit Publisher__c' }));

    expect(screen.getByRole('button', { name: 'Collapsed Field' })).toBeInTheDocument();
    expect(screen.queryByRole('button', { name: 'Absent Field' })).not.toBeInTheDocument();
    expect(screen.getByText('Absent Field')).toBeInTheDocument();

    view.rerender(
      <LayoutRenderer
        layout={{ ...layout, sections: [...layout.sections] } as never}
        record={record}
        objectMetadata={metadata as never}
        onUpdate={async () => undefined}
        fieldSurfacePolicyScope="validation-test"
      />,
    );
    expect(screen.getByRole('button', { name: 'Collapsed Field' })).toBeInTheDocument();

    fireEvent.click(screen.getByRole('button', { name: 'Collapsed Field' }));
    const target = await screen.findByRole('button', { name: 'Edit Collapsed__c' });
    expect(target).toHaveFocus();
    expect(target).toHaveAttribute('aria-invalid', 'true');
    expect(target).toHaveAttribute('aria-describedby', 'inline-edit-field-Collapsed__c-control-error');
  });

  it('maps compound component failures to their shared rendered control', async () => {
    const record = {
      Id: 'contact-1',
      Name: 'Ada Lovelace',
      FirstName: 'Ada',
      LastName: 'Lovelace',
      Publisher__c: '',
      Collapsed__c: '',
    };
    render(
      <LayoutRenderer
        layout={layout as never}
        record={record}
        objectMetadata={metadata as never}
        onUpdate={async () => undefined}
        fieldSurfacePolicyScope="validation-test"
      />,
    );

    fireEvent.click(screen.getByRole('button', { name: 'Edit Name' }));

    const firstNameFailure = screen.getByRole('button', { name: 'First Name' });
    const lastNameFailure = screen.getByRole('button', { name: 'Last Name' });
    expect(firstNameFailure).toBeInTheDocument();
    expect(lastNameFailure).toBeInTheDocument();

    fireEvent.click(lastNameFailure);
    const nameControl = screen.getByRole('button', { name: 'Edit Name' });
    expect(nameControl).toHaveFocus();
    expect(nameControl).toHaveAttribute('aria-invalid', 'true');
    expect(nameControl).toHaveAttribute('aria-describedby', 'inline-edit-field-Name-control-error');
    expect(nameControl.closest('#inline-edit-field-Name')).toHaveClass('ring-2');
    const messages = document.getElementById('inline-edit-field-Name-control-error')?.querySelectorAll('li');
    expect(messages).toHaveLength(2);
    expect(Array.from(messages || []).map(message => message.textContent)).toEqual(['is required', 'is required']);
  });
});
