/* eslint-disable max-lines-per-function */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { testTransform } from '@aws-amplify/graphql-transformer-test-utils';
import { ModelTransformer } from '@aws-amplify/graphql-model-transformer';
import { BelongsToTransformer, HasManyTransformer, HasOneTransformer } from '@aws-amplify/graphql-relational-transformer';
import { getSchemaDeployer, SchemaDeployer } from '../deploySchema';

jest.setTimeout(1000 * 60 * 10); // 10 minutes

describe('@belongsTo transformer', () => {
  const transform = (schema: string) =>
    testTransform({
      schema,
      transformers: [new ModelTransformer(), new BelongsToTransformer(), new HasManyTransformer(), new HasOneTransformer()],
      transformParameters: {
        respectPrimaryKeyAttributesOnConnectionField: false,
        sandboxModeEnabled: true,
      },
    });
  const validSchema = /* GraphQL */ `
    type Blog @model {
      id: ID!
      name: String!
      post: Post @hasOne
    }

    type Post @model {
      id: ID!
      title: String!
      blog: Blog @belongsTo
      comments: [Comment] @hasMany
    }

    type Comment @model {
      id: ID!
      post: Post @belongsTo
      content: String!
    }
  `;
  let testSchemaDeployer: SchemaDeployer;
  beforeEach(async () => {
    testSchemaDeployer = await getSchemaDeployer('belongsToV2Test', transform);
  });

  afterEach(async () => {
    await testSchemaDeployer?.cleanup();
  });

  it('reuses foreign key fields generated by corresponding hasOne and hasMany directives', async () => {
    const graphqlClient = await testSchemaDeployer.deploy(validSchema);
    const mutationResponse = await graphqlClient.query(/* GraphQL */ `
      mutation CreateRecords {
        createComment(input: { content: "test comment 1", id: "comment1", postCommentsId: "post1" }) {
          id
        }
        createBlog(input: { id: "blog1", name: "test blog 1", blogPostId: "post1" }) {
          id
        }
        createPost(input: { postBlogId: "blog1", id: "post1", title: "test post 1" }) {
          id
        }
      }
    `);

    expect(mutationResponse.errors).toBeUndefined();
    expect(mutationResponse.data.createComment.id).toEqual('comment1');
    expect(mutationResponse.data.createBlog.id).toEqual('blog1');
    expect(mutationResponse.data.createPost.id).toEqual('post1');

    const queryResponse = await graphqlClient.query(/* GraphQL */ `
      query GetRecords {
        getBlog(id: "blog1") {
          name
          post {
            id
            title
          }
        }
        getComment(id: "comment1") {
          content
          post {
            id
            title
          }
        }
        getPost(id: "post1") {
          title
          blog {
            id
            name
          }
          comments {
            items {
              content
              id
            }
          }
        }
      }
    `);

    expect(queryResponse.errors).toBeUndefined();
    expect(queryResponse.data.getBlog.post.id).toEqual('post1');
    expect(queryResponse.data.getComment.post.id).toEqual('post1');
    expect(queryResponse.data.getPost.blog.id).toEqual('blog1');
    expect(queryResponse.data.getPost.comments.items[0].id).toEqual('comment1');
  });
});
