import {
  entityTableSelector,
  entityDetailsButtonSelector,
  entityDetailsBackButtonSelector,
<%_ if (!readOnly) { _%>
  entityCreateButtonSelector,
  entityCreateSaveButtonSelector,
  entityCreateCancelButtonSelector,
  <%_ if (updatableEntity) { _%>
  entityEditButtonSelector,
  <%_ } _%>
  entityDeleteButtonSelector,
  entityConfirmDeleteButtonSelector,
  listSearchInputSelector,
  listSearchButtonSelector,
  listSearchMoreSelector,
  listSearchFormSelector,
  searchFormSubmitSelector,
  searchFormResetSelector,
  formAdvanceToggleSelector,
<%_ } _%>
} from '../../support/entity';
import {
  passwordLoginSelector,
  leftMenuSelector,
  submitLoginSelector,
  showMenuSelector,
  titleLoginSelector,
  usernameLoginSelector
} from '../../support/commands';
<%_

const baseApi = entityApi + 'api/';

const entityFakeData = generateFakeData('cypress');
const requiredRelationships = relationships.filter(rel => rel.relationshipRequired || rel.id);
const requiredOtherEntities = this._.uniq(requiredRelationships.map(rel => rel.otherEntity));
const otherEntities = this._.uniq(Object.values(differentRelationships).filter(rels => rels.length > 0).map(rels => rels[0].otherEntity));
// We cannot generate a required entity with relationship with required relationships.
const skipCreateTest =
  (
    !cypressBootstrapEntities ||
    requiredRelationships.some(rel => rel.otherEntity.primaryKey && rel.otherEntity.primaryKey.derived) ||
    requiredRelationships.some(rel => rel.otherEntity.builtInUser || rel.otherEntity === this.entity) ||
    requiredRelationships.map(rel => rel.otherEntity.relationships).flat().some(rel => rel.relationshipRequired) ||
    !entityFakeData
  ) ? '.skip' : '';

const sampleFields = fields.filter(f => !f.autoGenerate && !f.nullable);

if (workaroundEntityCannotBeEmpty && sampleFields.length === 0) {
  const sample = fields.find(f => !f.autoGenerate);
  if (sample) {
    sampleFields.push(sample);
  }
} else if (workaroundInstantReactiveMariaDB) {
  const samples = fields.filter(f => !f.autoGenerate && f.nullable && f.fieldType === 'Instant');
  if (samples.length > 0) {
    sampleFields.push(...samples);
  }
}
_%>

describe('<%= entityClass %> e2e test', () => {

  const basePageUrl = '/<%= clientRootFolder %>';
  const <%= entityInstance %>PageUrl = '/<%= clientRootFolder ? clientRootFolder + '/' : ''%><%= entityPage %>';
  const <%= entityInstance %>PageUrlPattern = new RegExp('/<%= entityPage %>(\\?.*)?$');
  const username = Cypress.env('E2E_USERNAME') ?? 'admin';
  const password = Cypress.env('E2E_PASSWORD') ?? 'admin';
  <% if (skipCreateTest) { %>// <% } %>const <%= entityInstance %>Sample = <%- JSON.stringify(this.generateTestEntity(sampleFields.map(field => field.reference))) %>;
  const localStorageValue: any = {};

  let <%= entityInstance %>: any;
<%_ for (otherEntity of requiredOtherEntities) { _%>
  <% if (skipCreateTest) { %>// <% } %>let <%= otherEntity.entityInstance %>;
<%_ } _%>

  beforeEach(() => {
    if (Object.keys(localStorageValue).length === 0) {
      cy.visit('/dashboard/analysis');
      cy.get(titleLoginSelector).should('be.visible');
      cy.get(usernameLoginSelector).clear().type(username);
      cy.get(passwordLoginSelector).clear().type(password);
      cy.get(submitLoginSelector).click();
      cy.wait(1000);
      cy.authenticatedRequest({
        method: 'POST',
        body: { username, password },
        url: Cypress.env('authenticationUrl'),
      }).then(({ body: { id_token } }) => {
        localStorage.setItem(Cypress.env('jwtStorageName'), id_token);
        localStorageValue[Cypress.env('jwtStorageName')] = id_token;
      });
      cy.getAllLocalStorage().then((ls) => {
        Object.assign(localStorageValue, ls!['http://localhost:3100']);
      });
    } else {
      Object.keys(localStorageValue).forEach(key => {
        localStorage.setItem(key, localStorageValue[key]);
        sessionStorage.setItem(key, localStorageValue[key]);
      });
      cy.wait(100);
      cy.visit('/dashboard/analysis');
      cy.wait(1000);
    }
  });

<%_ if (requiredOtherEntities.length > 0) { _%>
  <%_ if (skipCreateTest) { _%>
  /* Disabled due to incompatibility
  <%_ } _%>
  beforeEach(() => {
  <%_ for (otherEntity of requiredOtherEntities) { _%>
    // create an instance at the required relationship entity:
    cy.authenticatedRequest({
      method: 'POST',
      url: '/<%= baseApi + otherEntity.entityApiUrl %>',
      body: <%- JSON.stringify(this.generateTestEntity(otherEntity.fields.filter(f => !f.autoGenerate).map(field => field.reference))) %>,
    }).then(({ body }) => {
      <%= otherEntity.entityInstance %> = body;
    });
  <%_ } _%>
  });
  <%_ if (skipCreateTest) { _%>
   */
  <%_ } _%>

<%_ } _%>
  beforeEach(() => {
    cy.intercept('GET', '/<%= baseApi + entityApiUrl %><%_ if (fieldsContainParentAndChildren) { %>/tree<% } %>+(?*|)').as('entitiesRequest');
    cy.intercept('POST', '/<%= baseApi + entityApiUrl %>').as('postEntityRequest');
    cy.intercept('DELETE', '/<%= baseApi + entityApiUrl %>/*').as('deleteEntityRequest');
  });

<%_ if (requiredOtherEntities.length > 0) { _%>
  <%_ if (skipCreateTest) { _%>
  /* Disabled due to incompatibility
  <%_ } _%>
  beforeEach(() => {
    // Simulate relationships api for better performance and reproducibility.
  <%_ for (otherEntity of otherEntities) { _%>
    cy.intercept('GET', '/<%= baseApi + otherEntity.entityApiUrl %>', {
      statusCode: 200,
      body: [<%= requiredOtherEntities.includes(otherEntity) ? otherEntity.entityInstance : '' %>],
    });

  <%_ } _%>
  });
  <%_ if (skipCreateTest) { _%>
   */
  <%_ } _%>

<%_ } _%>
  afterEach(() => {
    if (<%= entityInstance %>) {
      cy.authenticatedRequest({
        method: 'DELETE',
        url: `/<%= baseApi + entityApiUrl %>/${<%= entityInstance %>.<%= primaryKey.name %>}`,
      }).then(() => {
        <%= entityInstance %> = undefined;
      });
    }
  });

<%_ if (requiredOtherEntities.length > 0) { _%>
  <%_ if (skipCreateTest) { _%>
  /* Disabled due to incompatibility
  <%_ } _%>
  afterEach(() => {
  <%_ for (otherEntity of requiredOtherEntities) { _%>
    if (<%= otherEntity.entityInstance %>) {
      cy.authenticatedRequest({
        method: 'DELETE',
        url: `/<%= baseApi + otherEntity.entityApiUrl %>/${<%= otherEntity.entityInstance %>.<%= otherEntity.primaryKey.name %>}`,
      }).then(() => {
        <%= otherEntity.entityInstance %> = undefined;
      });
    }
  <%_ } _%>
  });
  <%_ if (skipCreateTest) { _%>
   */
  <%_ } _%>

<%_ } _%>

  it('<%= entityClassPlural %> menu should load <%= entityClassPlural %> page', () => {
    cy.get(leftMenuSelector)?.invoke('width').then(value => {
      if (! value || value < 100 ) {
        cy.get(showMenuSelector).click();
      }
    });
    cy.wait(500);
    cy.get(`[data-cy="${basePageUrl}"]`).click();
    cy.wait(500);
    cy.get(`[data-cy="${<%= entityInstance %>PageUrl}"]`).click();
    cy.wait('@entitiesRequest').then(({ response }) => {
      if (response?.body.length === 0) {
        cy.get(entityTableSelector).should('not.exist');
      } else {
        cy.get(entityTableSelector).should('exist');
      }
    });;
    cy.getEntityHeading('<%= entityClass %>').should('exist');
    cy.url().should('match', <%= entityInstance %>PageUrlPattern);
  });

  describe('<%= entityClass %> page', () => {
<%_ if (!readOnly) { _%>
    describe('create button click', () => {
      beforeEach(() => {
        cy.visit(<%= entityInstance %>PageUrl);
        cy.wait('@entitiesRequest');
      });

      it('should load create <%= entityClass %> page', () => {
        cy.get(entityCreateButtonSelector).click();
        cy.url().should('match', new RegExp('/<%= clientRootFolder ? clientRootFolder + '/' : ''%><%= entityPage %>/new$'));
        cy.getEntityCreateUpdateHeading('<%= entityClass %>');
        cy.get(entityCreateSaveButtonSelector).should('exist');
        cy.get(entityCreateCancelButtonSelector).click();
        cy.wait('@entitiesRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(200);
        });
        cy.url().should('match', <%= entityInstance %>PageUrlPattern);
      });
    });

<%_ } _%>
    describe('with existing value', () => {
<% if (!readOnly) { %>
  <%_ if (skipCreateTest) { _%>
      /* Disabled due to incompatibility
  <%_ } _%>
      beforeEach(() => {
        cy.authenticatedRequest({
          method: 'POST',
          url: '/<%= baseApi + entityApiUrl %>',
  <%_ if (requiredRelationships.length > 0) { _%>
          body: {
            ...<%= entityInstance %>Sample,
    <%_ for (relationship of requiredRelationships) { _%>
            <%= relationship.relationshipName %>: <%= relationship.otherEntity.entityInstance %>,
    <%_ } _%>
          },
  <%_ } else { _%>
          body: <%= entityInstance %>Sample,
  <%_ } _%>
        }).then(({ body }) => {
          <%= entityInstance %> = body;

          cy.intercept(
            {
              method: 'GET',
              url: '/<%= baseApi + entityApiUrl %><%_ if (fieldsContainParentAndChildren) { %>/tree<% } %>+(?*|)',
              times: 1,
            },
            {
              statusCode: 200,
  <%_ if (!paginationNo) { _%>
              headers: {
                link: '<http://localhost/<%= baseApi + entityApiUrl %>?page=0&size=20>; rel="last",<http://localhost/<%= baseApi + entityApiUrl %>?page=0&size=20>; rel="first"',
              },
  <%_ } _%>
              body: {
                total: 1,
                records: [<%= entityInstance %>],
              },
            }
          ).as('entitiesRequestInternal');
        });

        cy.visit(<%= entityInstance %>PageUrl);

        cy.wait('@entitiesRequestInternal');
      });
  <%_ if (skipCreateTest) { _%>
       */

  <%_ } _%>
<%_ } _%>
<%_ if (readOnly || skipCreateTest) { _%>
      beforeEach(function () {
        cy.visit(<%= entityInstance %>PageUrl);

        cy.wait('@entitiesRequest').then(({ response }) => {
          if (response?.body.length === 0) {
            this.skip();
          }
        });
      });
<%_ } _%>

      it('detail button click should load details <%= entityClass %> page', () => {
        cy.visit(<%= entityInstance %>PageUrl);
        cy.wait(300);
        <%_ let hasButtonGroupDropdown = false;
          if (addCustomMethod?.includes('listComponent')) {
              hasButtonGroupDropdown = true;
          }
          if (fieldsContainParentAndChildren) {
              hasButtonGroupDropdown = true;
          }
        _%>
        <%_ if (hasButtonGroupDropdown) { _%>
        cy.get('.vxe-table--main-wrapper [data-cy="buttonGroupDropdown"]').first().then(el => {
          if (el) {
            cy.get('.vxe-table--main-wrapper [data-cy="buttonGroupDropdown"]').first().click({force: true});
          }
        });
        <%_ } _%>
        cy.get(entityDetailsButtonSelector).first().click({force: true});
        cy.getEntityDetailsHeading('<%= entityInstance %>');
        cy.get(entityDetailsBackButtonSelector).click();
        cy.wait('@entitiesRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(200);
        });
        cy.url().should('match', <%= entityInstance %>PageUrlPattern);
      });

<%_ if (!readOnly && updatableEntity) { _%>
      it('edit button click should load edit <%= entityClass %> page and go back', () => {
        cy.get(entityEditButtonSelector).first().click({force: true});
        cy.getEntityCreateUpdateHeading('<%= entityClass %>');
        cy.get(entityCreateSaveButtonSelector).should('exist');
        cy.get(entityCreateCancelButtonSelector).click();
        cy.wait('@entitiesRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(200);
        });
        cy.url().should('match', <%= entityInstance %>PageUrlPattern);
      });

      it<% if (jpaMetamodelFiltering && (clientFrameworkAngular || clientFrameworkVue)) { %>.skip<% } %>('edit button click should load edit <%= entityClass %> page and save', () => {
        cy.get(entityEditButtonSelector).first().click({force: true});
        cy.getEntityCreateUpdateHeading('<%= entityClass %>');
        cy.get(entityCreateSaveButtonSelector).click();
        cy.wait('@entitiesRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(200);
        });
        cy.url().should('match', <%= entityInstance %>PageUrlPattern);
      });

<%_ } _%>
<%_ if (!readOnly) { _%>
      it<%= skipCreateTest %>('last delete button click should delete instance of <%= entityClass %>', () => {
  <%_ if (clientFrameworkReact) { _%>
        cy.intercept('GET', '/<%= baseApi + entityApiUrl %>/*').as('dialogDeleteRequest');
  <%_ } _%>
        cy.get(entityDeleteButtonSelector).last().click({force: true});
  <%_ if (clientFrameworkReact) { _%>
        cy.wait('@dialogDeleteRequest');
  <%_ } _%>
        cy.getEntityDeleteDialogHeading('<%= entityInstance %>').should('exist');
        cy.get(entityConfirmDeleteButtonSelector).click();
        cy.wait('@deleteEntityRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(204);
        });
        cy.wait('@entitiesRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(200);
        });
        cy.url().should('match', <%= entityInstance %>PageUrlPattern);
  <% if (cypressBootstrapEntities) { %>
        <%= entityInstance %> = undefined;
  <%_ } _%>
      });
<%_ } _%>
    });
  });
<%_ if (!readOnly) { _%>

  describe('new <%= entityClass %> page', () => {
    beforeEach(() => {
      cy.visit(`${<%= entityInstance %>PageUrl}`);
      cy.get(entityCreateButtonSelector).click();
      cy.getEntityCreateUpdateHeading('<%= entityClass %>');
    });

    it<%= skipCreateTest %>('should create an instance of <%= entityClass %>', () => {
    cy.wait(3000)
  <%_ fields.filter(field => {
    const hideInForm = field.options?.fieldConfig?.includes('hideInForm');
    return (!field.id || !field.autoGenerate) && !field.hidden && !field.readonly && !hideInForm;
  }).forEach((field, fieldIndex) => {
    const fieldName = field.fieldName;
    const fieldIsEnum = field.fieldIsEnum;
    let fieldValue = !entityFakeData ? field.generateFakeData('cypress') : entityFakeData[field.fieldName];
    if (fieldValue === undefined) {
        return;
    }
    fieldValue = typeof fieldValue === 'string' ? fieldValue.replaceAll("'", "\\'") : fieldValue;
  _%>

    <%_ if (field.fieldTypeBoolean) { _%>
      cy.get(`[id="form_item_<%= fieldName %>"]`).invoke("attr", 'aria-checked').should('eq', 'false');
      cy.get(`[id="form_item_<%= fieldName %>"]`).click();
      cy.get(`[id="form_item_<%= fieldName %>"]`).invoke("attr", 'aria-checked').should('eq', 'true');

    <%_ } else if (field.fieldTypeBinary && !field.blobContentTypeText) { _%>
      cy.setFieldImageAsBytesOfEntity('<%= fieldName %>', 'integration-test.png', 'image/png');

    <%_ } else if (fieldIsEnum) { _%>
      cy.get(`[id="form_item_<%= fieldName %>"]`).click().wait(100).type('<%- fieldValue %>{enter}', { force: true });

    <%_ } else if (field.fieldTypeString || field.blobContentTypeText) { _%>
        <%_ if (field.options?.endUsed === 'editor' || !field.options?.endUsed && field.blobContentTypeText) { _%>
      cy.setTinyMceContent('form_item_<%= fieldName %>_editor', 'fake-data/blob/hipster.txt');
        <%_ } else if (field.options?.endUsed === 'selectModal') { _%>
      cy.get(`[id="form_item_<%= fieldName %>"]`).type('<%- fieldValue %>', {  force: true, delay: 100 });
      cy.wait(200);
      cy.get(`[data-cy="selectModalCancelButton"]`).click();
        <%_ } else { _%>
      cy.get(`[id="form_item_<%= fieldName %>"]`).type('<%- fieldValue %>', { delay: 100 });
      cy.get(`[id="form_item_<%= fieldName %>"]`).should('have.value', '<%- fieldValue %>');
        <%_ } _%>
    <%_ } else if (field.fieldTypeNumeric) { _%>
      cy.get(`[id="form_item_<%= fieldName %>"]`).type('<%- fieldValue %>', { delay: 100 });
      cy.get(`[id="form_item_<%= fieldName %>"]`).should('have.value', '<%- fieldValue %>');
    <%_ } else if (field.fieldTypeLocalDate || field.fieldTypeTimed || field.fieldTypeDuration) { %>
     cy.get(`[id="form_item_<%= fieldName %>"]`).click({force: true}).wait(50).type('<%- fieldValue %>', { force: true, delay: 100 });
     cy.get(`[id="form_item_<%= fieldName %>"]`).invoke('attr', 'title').should('eq', '<%- fieldValue %>');
    <%_ } else { _%>
      cy.get(`[id="form_item_<%= fieldName %>"]`).type('<%- fieldValue %>');
      cy.get(`[id="form_item_<%= fieldName %>"]`).invoke('val').should('match', new RegExp('<%- fieldValue %>'));

    <%_ } _%>
    <%_ if (fieldIndex > 0 && fieldIndex % 5 === 0) { %>
      cy.get('.vben-layout-content.full').first().scrollTo('center', { ensureScrollable: false });
    <%_ } _%>
  <%_ }); _%>
  <%_ for (relationship of requiredRelationships) {
    const relationshipName = relationship.relationshipName;
  _%>
       cy.get(`[id="form_item_<%= relationship.relationshipFieldName %>"]`).click().wait(100).type('<%= relationship.collection ? '[0]{enter}' : '1{enter}' %>');
  <%_ } _%>

  <%_ if (anyFieldHasFileBasedContentType) { _%>
      // since cypress clicks submit too fast before the blob fields are validated
      cy.wait(200); // eslint-disable-line cypress/no-unnecessary-waiting
  <%_ } _%>
      cy.get(entityCreateSaveButtonSelector).click();

      cy.wait('@postEntityRequest').then(({ response }) => {
        expect(response?.statusCode).to.equal(201);
        <%= entityInstance %> = response?.body;
      });
      cy.wait('@entitiesRequest').then(({ response }) => {
        expect(response?.statusCode).to.equal(200);
        cy.get(entityCreateSaveButtonSelector).contains('更新');
        cy.get(entityCreateCancelButtonSelector).click();
        cy.wait(200);
        cy.get(listSearchInputSelector).clear().type('nectarine');
        cy.get(listSearchButtonSelector).click();
        cy.wait(500);
        cy.get(entityTableSelector).should('exist');
        cy.get(`[rowid="${<%= entityInstance %>.<%= primaryKey.name %>}"]`).should('exist');
        cy.get(listSearchInputSelector).clear();
      <%_ const stringFields = fields.filter(field => field.fieldTypeString && !field.options?.fieldConfig?.includes('hideInForm')); _%>
      <%_ if (stringFields.length > 0) {
          const fieldName = stringFields[0].fieldName;
          const fieldValue = !entityFakeData ? stringFields[0].generateFakeData('cypress') : entityFakeData[stringFields[0].fieldName];
      _%>
        cy.get(listSearchMoreSelector).click();
        cy.get(listSearchFormSelector).should('exist');
        cy.get('[id="form_item_<%= fieldName %>"]').type('<%= fieldValue %>');
        cy.get(searchFormSubmitSelector).click();
        cy.get(entityTableSelector).should('exist');
        cy.get(`[rowid="${<%= entityInstance %>.<%= primaryKey.name %>}"]`).should('exist');
        cy.wait(300);
      <%_ } _%>
        cy.get(searchFormResetSelector).click();
        cy.wait(300);
        cy.get(formAdvanceToggleSelector).click();
        cy.get(`[rowid="${<%= entityInstance %>.<%= primaryKey.name %>}"]`).should('exist');
      });
      cy.url().should('match', <%= entityInstance %>PageUrlPattern);
    });
  });
<%_ } _%>
});
