import { Callbacks } from 'cypress/types/jquery/index'

const username = Cypress.env('username')
const password = Cypress.env('password')
const hostUrl = Cypress.env('hosturl')
const appLocation = Cypress.env('appLocation')
const longerCommandTimeout = Cypress.env('longerCommandTimeout')
const serverType = Cypress.env('serverType')
const libraryToOpenIncludes = Cypress.env(`libraryToOpenIncludes_${serverType}`)
const fixturePath = 'excels/'

context('excel tests: ', function () {
  this.beforeAll(() => {
    cy.visit(`${hostUrl}/SASLogon/logout`)
    cy.loginAndUpdateValidKey(true)
  })

  this.beforeEach(() => {
    cy.visit(hostUrl + appLocation)

    visitPage('home')

    colorLog(
      `TEST START ---> ${
        Cypress.mocha.getRunner().suite.ctx.currentTest.title
      }`,
      '#3498DB'
    )
  })

  it('1 | Uploads regular Excel file', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('regular_excel.xlsx', () => {
      submitExcel()
      rejectExcel(done)
    })
  })

  it('2 | Uploads Excel with data on the 7th tab', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('7th_tab_excel.xlsx', () => {
      submitExcel()
      rejectExcel(done)
    })
  })

  it('3 | Uploads Excel with missing columns (should fail)', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('missing_columns_excel.xlsx', () => {
      cy.get('.abortMsg', { timeout: longerCommandTimeout })
        .should('exist')
        .then((elements: any) => {
          if (elements[0]) {
            if (elements[0].innerText.toLowerCase().includes('missing')) done()
          }
        })
    })
  })

  it('4 | Uploads Excel with formulas', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_datadictionary')

    attachExcelFile('formulas_excel.xlsx', () => {
      checkResultOfFormulaUpload(done)
    })
  })

  it('5 | Uploads Excel with no data rows', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('nodata_rows_excel.xlsx', () => {
      cy.get('.abortMsg', { timeout: longerCommandTimeout })
        .should('exist')
        .then((elements: any) => {
          if (elements[0]) {
            if (
              elements[0].innerText
                .toLowerCase()
                .includes('no relevant data found')
            )
              done()
          }
        })
    })
  })

  it('6 | Uploads Excel with a table that is surrounded by other data', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('surrounded_data_excel.xlsx', () => {
      submitExcel()
      rejectExcel(done)
    })
  })

  it('7 | Uploads Excel with a extra columns in the middle', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('extra_column_excel.xlsx', () => {
      submitExcel()
      rejectExcel(done)
    })
  })

  it('8 | Uploads Excel with a duplicate column', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('duplicate_column_excel.xlsx', () => {
      submitExcel()
      rejectExcel(done)
    })
  })

  it('9 | Uploads Excel with a duplicate row', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('duplicate_row_excel.xlsx', () => {
      submitExcel(() => {
        cy.get('.duplicate-keys-modal', { timeout: longerCommandTimeout })
          .should('exist')
          .then((elements: any) => {
            if (elements[0]) {
              if (elements[0].innerText.toLowerCase().includes('duplicates'))
                done()
            }
          })
      })
    })
  })

  it('10 | Uploads Excel with a mixed content', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('mixed_content_excel.xlsx', () => {
      submitExcel(() => {
        cy.get('.modal-body').then((modalBody: any) => {
          if (
            modalBody[0].innerHTML
              .toLowerCase()
              .includes(`invalid values are present`)
          ) {
            done()
          }
        })
      })
    })
  })

  it('11 | Uploads Excel with a blank columns', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('blank_columns_excel.xlsx', () => {
      cy.get('.abortMsg', { timeout: longerCommandTimeout })
        .should('exist')
        .then((elements: any) => {
          if (elements[0]) {
            if (elements[0].innerText.toLowerCase().includes('missing')) done()
          }
        })
    })
  })

  it('12 | Uploads Excel xls extension', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('regular_excel_xls.xls', () => {
      submitExcel()
      rejectExcel(done)
    })
  })

  // For some strange reason this file breaks cypress. When uploaded manually in DC it is working.
  // it('13 | Uploads Excel xlsm extension', (done) => {
  //   openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

  //   attachExcelFile('regular_excel_macro.xlsm', () => {
  //     submitExcel()
  //     rejectExcel(done)
  //   })
  // })

  it('14 | Uploads Excel with composite primary key', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_datadictionary')

    attachExcelFile('MPE_DATADICTIONARY_composite_keys.xlsx', () => {
      submitExcel()
      rejectExcel(done)
    })
  })

  it('15 | Uploads Excel with missing row (empty table)', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_datadictionary')

    attachExcelFile('MPE_DATADICTIONARY_missing_row.xlsx', () => {
      cy.get('.abortMsg', { timeout: longerCommandTimeout })
        .should('exist')
        .then((elements: any) => {
          if (elements[0]) {
            if (
              elements[0].innerText
                .toLowerCase()
                .includes('no relevant data found')
            )
              done()
          }
        })
    })
  })

  it('16 | Uploads Excel with merged cells', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_datadictionary')

    attachExcelFile('MPE_DATADICTIONARY_merged_cells.xlsx', () => {
      submitExcel()
      rejectExcel(done)
    })
  })

  it('17 | Check uploaded values from excel with xls extension', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('regular_excel_xls.xls', () => {
      checkResultOfXLSUpload(done)
    })
  })

  it('18 | Uploads Excel with missing row (empty table)', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('blank_column_with_header.xlsx', () => {
      cy.get('.btn-upload-preview', { timeout: 60000 })
        .should('be.visible')
        .then(() => {
          cy.get('#hotTable', { timeout: 30000 })
            .find('div.ht_master.handsontable')
            .find('div.wtHolder')
            .find('div.wtHider')
            .find('div.wtSpreader')
            .find('table.htCore')
            .find('tbody')
            .then((data) => {
              let allEmpty = true

              for (let col = 0; col < data[0].children.length; col++) {
                const cell: any = data[0].children[col].children[5]

                if (cell.innerText !== '') {
                  allEmpty = false

                  break
                }
              }

              if (allEmpty) done()
            })
        })
    })
  })

  it('19 | Uploads Excel with data on random sheet surrounded with all empty cells', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('surrounded_data_all_cells_empty_excel.xlsx', () => {
      checkResultOfXLSUpload(done)
    })
  })

  it('20 | Uploads Excel with data surrounded with empty cells ', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('surrounded_data_empty_cells_excel.xlsx', () => {
      checkResultOfXLSUpload(done)
    })
  })

  it('21 | Uploads regular Excel file with first row marked for Delete (yes)', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    attachExcelFile('regular_excel_with_delete.xlsx', () => {
      cy.get('.btn-upload-preview', { timeout: 60000 })
        .should('be.visible')
        .then(() => {
          cy.get('#hotTable', { timeout: 30000 })
            .find('div.ht_master.handsontable')
            .find('div.wtHolder')
            .find('div.wtHider')
            .find('div.wtSpreader')
            .find('table.htCore')
            .find('tbody')
            .then((data: JQuery<HTMLTableSectionElement>) => {
              const firstRowFirstCol: Partial<HTMLElement> =
                data[0].children[0].children[1]

              if (
                firstRowFirstCol.innerText &&
                !firstRowFirstCol.innerText.toLowerCase().includes('yes')
              ) {
                done('Delete? column from file not applied')
              }
            })
            .then(() => {
              submitExcel()
              rejectExcel(done)
            })
        })
    })
  })

  it('22 | Uploads password protected Excel and unlocks with correct password', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    cy.get('.buttonBar button:last-child')
      .should('exist')
      .click()
      .then(() => {
        cy.get('input[type="file"]#file-upload')
          .attachFile(`/${fixturePath}/regular_excel_password.xlsx`)
          .then(() => {
            // Wait for password modal to appear
            cy.get('#filePasswordInput', { timeout: 10000 })
              .should('be.visible')
              .type('123123')

            // Click Unlock button
            cy.get('.btn.btn-success-outline').should('not.be.disabled').click()

            // Click away the overlay
            cy.get('.modal-footer .btn.btn-primary', { timeout: 5000 }).click()

            // Verify file loads successfully
            cy.get('.btn-upload-preview', { timeout: 60000 })
              .should('be.visible')
              .then(() => {
                submitExcel()
                rejectExcel(done)
              })
          })
      })
  })

  it('23 | Uploads password protected Excel and handles wrong password', (done) => {
    openTableFromTree(libraryToOpenIncludes, 'mpe_x_test')

    cy.get('.buttonBar button:last-child')
      .should('exist')
      .click()
      .then(() => {
        cy.get('input[type="file"]#file-upload')
          .attachFile(`/${fixturePath}/regular_excel_password.xlsx`)
          .then(() => {
            // First attempt: Enter wrong password
            cy.get('#filePasswordInput', { timeout: 10000 })
              .should('be.visible')
              .type('wrongpassword')

            cy.get('.btn.btn-success-outline').should('not.be.disabled').click()

            // Verify error message appears
            cy.get('.modal-footer .color-red', { timeout: 10000 })
              .should('be.visible')
              .should('contain', "Sorry that didn't work, try again.")

            // Modal should still be open for retry
            cy.get('#filePasswordInput')
              .should('be.visible')
              .clear()
              .type('123123')

            // Second attempt: Enter correct password
            cy.get('.btn.btn-success-outline').should('not.be.disabled').click()

            // Click away the overlay
            cy.get('.modal-footer .btn.btn-primary', { timeout: 5000 }).click()

            // Verify file loads successfully
            cy.get('.btn-upload-preview', { timeout: 60000 })
              .should('be.visible')
              .then(() => {
                submitExcel()
                rejectExcel(done)
              })
          })
      })
  })

  // Large files break Cypress

  // it ('? | Uploads Excel with size of 5MB', (done) => {
  //     attachExcelFile('5mb_excel.xlsx', () => {
  //         submitExcel();
  //         rejectExcel(done);
  //     });
  // })

  // it ('? | Uploads Excel with size of 15MB', (done) => {
  //     attachExcelFile('15mb_excel.xlsx', () => {
  //         submitExcel();
  //         rejectExcel(done);
  //     });
  // })

  //Large files tests end

  this.afterEach(() => {
    colorLog(`TEST END -------------`, '#3498DB')
  })
})

const openTableFromTree = (libNameIncludes: string, tablename: string) => {
  cy.get('.app-loading', { timeout: longerCommandTimeout })
    .should('not.exist')
    .then(() => {
      cy.get('.nav-tree clr-tree > clr-tree-node', {
        timeout: longerCommandTimeout
      }).then((treeNodes: any) => {
        let viyaLib

        for (let node of treeNodes) {
          if (node.innerText.toLowerCase().includes(libNameIncludes)) {
            viyaLib = node
            break
          }
        }

        cy.get(viyaLib).within(() => {
          cy.get('.clr-tree-node-content-container > button').click()

          cy.get('.clr-treenode-link').then((innerNodes: any) => {
            for (let innerNode of innerNodes) {
              if (innerNode.innerText.toLowerCase().includes(tablename)) {
                innerNode.click()
                break
              }
            }
          })
        })
      })
    })
}

const attachExcelFile = (excelFilename: string, callback?: any) => {
  cy.get('.buttonBar button:last-child')
    .should('exist')
    .click()
    .then(() => {
      cy.get('input[type="file"]#file-upload')
        .attachFile(`/${fixturePath}/${excelFilename}`)
        .then(() => {
          cy.get('.clr-abort-modal .modal-title').then((modalTitle) => {
            if (!modalTitle[0].innerHTML.includes('Abort Message')) {
              cy.get('.modal-footer .btn.btn-primary').then((modalBtn) => {
                modalBtn.click()
                if (callback) callback()
              })
            } else {
              if (callback) callback()
            }
          })
        })
    })
}

const submitExcel = (callback?: any) => {
  cy.get('.buttonBar button.preview-submit', { timeout: longerCommandTimeout })
    .click()
    .then(() => {
      if (callback) callback()
    })
}

const rejectExcel = (callback?: any) => {
  cy.get('button', { timeout: longerCommandTimeout })
    .should('contain', 'Approve')
    .then((allButtons: any) => {
      for (let approvalButton of allButtons) {
        if (approvalButton.innerText.toLowerCase().includes('approve')) {
          approvalButton.click()
          break
        }
      }

      cy.get('button.btn-danger')
        .should('exist')
        .should('not.be.disabled')
        .click()
        .then(() => {
          cy.get('.modal-footer button.btn-success-outline')
            .click()
            .then(() => {
              cy.get('app-history')
                .should('exist')
                .then(() => {
                  if (callback) callback()
                })
            })
        })
    })
}

const acceptExcel = (callback?: any) => {
  cy.get('button', { timeout: longerCommandTimeout })
    .should('contain', 'Approve')
    .then((allButtons: any) => {
      for (let approvalButton of allButtons) {
        if (approvalButton.innerText.toLowerCase().includes('approve')) {
          approvalButton.click()
          break
        }
      }

      cy.get('#acceptBtn')
        .should('exist')
        .should('not.be.disabled')
        .click()
        .then(() => {
          if (callback) {
            callback()
          }
        })
    })
}

const checkResultOfFormulaUpload = (callback?: any) => {
  cy.get('#hotTable', { timeout: longerCommandTimeout })
    .find('div.ht_master.handsontable')
    .find('div.wtHolder')
    .find('div.wtHider')
    .find('div.wtSpreader')
    .find('table.htCore')
    .find('tbody')
    .then((data) => {
      const cell: any = data[0].children[0].children[5]
      expect(cell.innerText).to.equal('=1+1')
      if (callback) callback()
    })
}

const checkResultOfXLSUpload = (callback?: any) => {
  // Config-default width — wide enough that the date/datetime/time columns are
  // not virtualized away (the old 1280 width hid the trailing time columns).
  cy.viewport(1600, 900)
  cy.get('#hotTable', { timeout: 30000 })
    .find('div.ht_master.handsontable')
    .find('div.wtHolder')
    .find('div.wtHider')
    .find('div.wtSpreader')
    .find('table.htCore')
    .find('tbody')
    .then((data) => {
      let cell: any = data[0].children[0].children[2]

      expect(cell.innerText).to.equal('0')
      cell = data[0].children[0].children[3]
      expect(cell.innerText).to.equal('this is dummy data changed in excel')
      cell = data[0].children[0].children[4]
      expect(cell.innerText).to.equal('▼\nOption 1')
      cell = data[0].children[0].children[5]
      expect(cell.innerText).to.equal('42')
      // Cells render the raw stored ISO string verbatim (locale-independent;
      // see registerIntlCellTypes). date -> YYYY-MM-DD, datetime ->
      // YYYY-MM-DD HH:mm:ss, time -> HH:mm:ss.
      cell = data[0].children[0].children[6]
      expect(cell.innerText).to.equal('1960-02-12')
      cell = data[0].children[0].children[7]
      expect(cell.innerText).to.equal('1960-01-01 00:00:42')
      cell = data[0].children[0].children[8]
      expect(cell.innerText).to.equal('00:00:42')

      if (callback) callback()
    })

  cy.get('#hotTable', { timeout: 30000 })
    .find('div.ht_master.handsontable')
    .find('div.wtHolder')
    .scrollTo('right')
    .find('div.wtHider')
    .find('div.wtSpreader')
    .find('table.htCore')
    .find('tbody')
    .then((data) => {
      let cell: any = data[0].children[0].children[1]

      cell = data[0].children[0].children[9]

      expect(cell.innerText).to.equal('44')

      if (callback) callback()
    })
}

const visitPage = (url: string) => {
  cy.visit(`${hostUrl}${appLocation}/#/${url}`)
}

const colorLog = (msg: string, color: string) => {
  console.log('%c' + msg, 'color:' + color + ';font-weight:bold;')
}
