/// <reference types="cypress" />

import makeFakeUser from '../../factories/user';

describe('Change Current Email/Password Feature', () => {
  beforeEach(() => {
    // Log in to the application or navigate to the account page
    // where the change email feature is available
    const currentUser = makeFakeUser({
      email: 'sam@example.com'
    });
    cy.stubAuthenticate({ ...currentUser });
    cy.visit('/account/identity');
  });

  describe('Email update', () => {
    it('should display the current email address', () => {
      // Assert that the current email address is displayed
      cy.get('[data-testid=edit_email_form]').within($form => {
        cy.get('input#new_email[placeholder="sam@example.com"]');
      });
    });

    it('shows validation error if no data is entered', () => {
      // Assert that an error message is displayed
      cy.get('[data-testid=edit_email_form]').within($form => {
        cy.get('[data-testid=email_submit]').click();
        cy.contains('Current password is required');
        cy.contains('New Email is required');
      });
    });

    it('shows validation error if new email is invalid', () => {
      cy.get('[data-testid=edit_email_form]').within($form => {
        // Enter the current password
        cy.get('input#current_password').type('password');
        // Enter an invalid email address in the input field
        cy.get('input#new_email').type('invalidemail');

        cy.get('[data-testid=email_submit]').click();
        // Assert that an error message is displayed
        cy.contains('Email is invalid');
      });
    });

    it('reveal password', () => {
      cy.get('[data-testid=edit_email_form]').within($form => {
        // Click on the reveal password button
        cy.get('.input-group-append').click();
        // Assert that the password is revealed
        cy.get('input#current_password').should('have.attr', 'type', 'text');
      });
    });

    describe('when the user submits the form', () => {
      beforeEach(() => {
        cy.intercept('POST', /\S+\/users\S+/, {
          statusCode: 200
        }).as('updateEmail');
      });

      it('should update the email address', () => {
        cy.get('[data-testid=edit_email_form]').within($form => {
          // Enter the current password
          cy.get('input#current_password').type('password');
          // Enter the new email address
          cy.get('input#new_email').type('samsam@example.com');

          // Submit the form
          cy.get('[data-testid=email_submit]').click();
        });

        // Assert that the email address is updated
        cy.contains('A confirmation email has been sent to your email address');
      });
    });
  });

  describe('Password update', () => {
    it('shows validation error if no data is entered', () => {
      // Assert that an error message is displayed
      cy.get('[data-testid=edit_password_form]').within($form => {
        cy.get('[data-testid=password_submit]').click();
        cy.contains('Current password is required');
        cy.contains('New password is required');
      });
    });
    
    it('reveal password', () => {
      cy.get('[data-testid=edit_password_form]').within($form => {
        // Click on the reveal password button
        cy.get('.current-password-reveal').click();
        // Assert that the password is revealed
        cy.get('input#current_password').should('have.attr', 'type', 'text');

        // Click on the reveal password button
        cy.get('.new-password-reveal').click();
        // Assert that the password is revealed
        cy.get('input#new_password').should('have.attr', 'type', 'text');
      });
    });

    describe('Submit form with errors', () => {
      beforeEach(() => {
        cy.intercept('POST', /\S+\/users\S+\/set_password/, {
          statusCode: 422,
          body: {
            errors: {
              password: ['is too short']
            }
          }
        }).as('updatePassword');
      });

      it('shows validation error if new password is invalid', () => {
        cy.get('[data-testid=edit_password_form]').within($form => {
          // Enter the current password
          cy.get('input#current_password').type('password');
          // Enter an invalid new password
          cy.get('input#new_password').type('short');
  
          cy.get('[data-testid=password_submit]').click();
          // Assert that an error message is displayed
          cy.contains('New Password is too short');
        });
      });
    });
    
    describe('Submit with valid data', () => {
      beforeEach(() => {
        cy.intercept('POST', /\S+\/users\S+\/set_password/, {
          statusCode: 200
        }).as('updatePassword');
      });

      it('should update the password', () => {
        cy.get('[data-testid=edit_password_form]').within($form => {
          // Enter the current password
          cy.get('input#current_password').type('password');
          // Enter the new password
          cy.get('input#new_password').type('newpassword');

          // Submit the form
          cy.get('[data-testid=password_submit]').click();
        });

        // Assert that the password is updated
        cy.contains('password has been successfully updated');
      });
    })
    
    describe('Forgot password', () => {
      beforeEach(() => {
        cy.intercept('POST', /\S+\/users\S+\/request_reset_password/, {
          statusCode: 200
        }).as('forgotPassword');
      });

      it('sends forgot password email', () => {
        cy.get('[data-testid=forgot_password]').click();
        cy.contains('A password reset email has been sent to your email');
      });
    })
    
  });
});
