/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

import React from 'react';
import { render, screen } from '@nocobase/test/client';
import {
  CollectionRecordProvider,
  CollectionRecord,
  useCollectionParentRecordData,
  useCollectionParentRecord,
  useCollectionRecordData,
  useCollectionRecord,
} from '../../collection-record';

describe('CollectionRecordProvider', () => {
  describe('record and parentRecord', () => {
    test('record parameter is a `Record` instance', () => {
      const Demo = () => {
        const record = useCollectionRecord();
        return <pre data-testid="content">{JSON.stringify(record)}</pre>;
      };
      const record = new CollectionRecord({ data: { id: 1, name: 'foo' } });

      render(
        <CollectionRecordProvider record={record}>
          <Demo />
        </CollectionRecordProvider>,
      );

      expect(screen.getByTestId('content')).toHaveTextContent(JSON.stringify({ id: 1, name: 'foo' }));
    });

    test('record parameter is a `plain object`', () => {
      const Demo = () => {
        const record = useCollectionRecord();
        return <pre data-testid="content">{JSON.stringify(record)}</pre>;
      };

      render(
        <CollectionRecordProvider record={{ id: 1, name: 'foo' }}>
          <Demo />
        </CollectionRecordProvider>,
      );

      expect(screen.getByTestId('content')).toHaveTextContent(JSON.stringify({ id: 1, name: 'foo' }));
    });

    test('record parameter is a `Record` instance with parent record', () => {
      const Demo = () => {
        const record = useCollectionRecord();
        return <pre data-testid="content">{JSON.stringify(record)}</pre>;
      };

      const parentRecord = new CollectionRecord({ data: { id: 1, role: 'admin' } });
      const record = new CollectionRecord({ data: { id: 1, name: 'foo' }, parentRecord });

      render(
        <CollectionRecordProvider record={record}>
          <Demo />
        </CollectionRecordProvider>,
      );

      expect(screen.getByTestId('content')).toHaveTextContent(
        JSON.stringify({
          data: {
            id: 1,
            name: 'foo',
          },
          parentRecord: {
            data: {
              id: 1,
              role: 'admin',
            },
          },
        }),
      );
    });

    test('record parameter is a `Record` instance, parent record is passed through parentRecord parameter', () => {
      const Demo = () => {
        const record = useCollectionRecord();
        return <pre data-testid="content">{JSON.stringify(record)}</pre>;
      };

      const parentRecord = new CollectionRecord({ data: { id: 1, role: 'admin' } });
      const record = new CollectionRecord({ data: { id: 1, name: 'foo' } });

      render(
        <CollectionRecordProvider record={record} parentRecord={parentRecord}>
          <Demo />
        </CollectionRecordProvider>,
      );

      expect(screen.getByTestId('content')).toHaveTextContent(
        JSON.stringify({
          data: {
            id: 1,
            name: 'foo',
          },
          parentRecord: {
            data: {
              id: 1,
              role: 'admin',
            },
          },
        }),
      );
    });

    test('record parameter is a `plain object`, parent record is also a `plain object`', () => {
      const Demo = () => {
        const record = useCollectionRecord();
        return <pre data-testid="content">{JSON.stringify(record)}</pre>;
      };

      render(
        <CollectionRecordProvider record={{ id: 1, name: 'foo' }} parentRecord={{ id: 1, role: 'admin' }}>
          <Demo />
        </CollectionRecordProvider>,
      );

      expect(screen.getByTestId('content')).toHaveTextContent(
        JSON.stringify({
          data: {
            id: 1,
            name: 'foo',
          },
          parentRecord: {
            data: {
              id: 1,
              role: 'admin',
            },
          },
        }),
      );
    });
  });

  describe('hooks', () => {
    test('useCollectionRecordData()', () => {
      const Demo = () => {
        const data = useCollectionRecordData();
        return <pre data-testid="content">{JSON.stringify(data)}</pre>;
      };
      const parentRecord = new CollectionRecord({ data: { id: 1, role: 'admin' } });
      const record = new CollectionRecord({ data: { id: 1, name: 'foo' }, parentRecord });

      render(
        <CollectionRecordProvider record={record}>
          <Demo />
        </CollectionRecordProvider>,
      );

      expect(screen.getByTestId('content')).toHaveTextContent(JSON.stringify({ id: 1, name: 'foo' }));
    });

    test('useCollectionParentRecord()', () => {
      const Demo = () => {
        const data = useCollectionParentRecord();
        return <pre data-testid="content">{JSON.stringify(data)}</pre>;
      };
      const parentRecord = new CollectionRecord({ data: { id: 1, role: 'admin' } });
      const record = new CollectionRecord({ data: { id: 1, name: 'foo' }, parentRecord });

      render(
        <CollectionRecordProvider record={record}>
          <Demo />
        </CollectionRecordProvider>,
      );

      expect(screen.getByTestId('content')).toHaveTextContent(
        JSON.stringify({
          data: {
            id: 1,
            role: 'admin',
          },
        }),
      );
    });

    test('useCollectionParentRecordData()', () => {
      const Demo = () => {
        const data = useCollectionParentRecordData();
        return <pre data-testid="content">{JSON.stringify(data)}</pre>;
      };
      const parentRecord = new CollectionRecord({ data: { id: 1, role: 'admin' } });
      const record = new CollectionRecord({ data: { id: 1, name: 'foo' }, parentRecord });

      render(
        <CollectionRecordProvider record={record}>
          <Demo />
        </CollectionRecordProvider>,
      );

      expect(screen.getByTestId('content')).toHaveTextContent(
        JSON.stringify({
          id: 1,
          role: 'admin',
        }),
      );
    });
  });
});
