import {
  Component,
  OnInit,
  ViewEncapsulation,
  AfterViewInit,
  signal
} from '@angular/core'
import { SasStoreService } from '../services/sas-store.service'
import { Router } from '@angular/router'
import { ActivatedRoute } from '@angular/router'
import { SasService } from '../services/sas.service'
import { EventService } from '../services/event.service'
import { HotTableInterface } from '../models/HotTable.interface'
import Handsontable from 'handsontable'
import { LicenceService } from '../services/licence.service'
import { globals } from '../_globals'
import { EditorsRestoreServiceResponse } from '../models/sas/editors-restore.model'
import { RequestWrapperResponse } from '../models/request-wrapper/RequestWrapperResponse'

@Component({
  selector: 'app-stage',
  templateUrl: './stage.component.html',
  styleUrls: ['./stage.component.scss'],
  host: {
    class: 'content-container'
  },
  encapsulation: ViewEncapsulation.None,
  standalone: false
})
export class StageComponent implements OnInit, AfterViewInit {
  public table_id: any
  public jsParams: any
  public keysArray: any
  public tableDetails: any
  public loaded: boolean = false
  public revertingChanges: boolean = false
  public licenceState = this.licenceService.licenceState
  public hotTable: HotTableInterface = {
    data: [],
    colHeaders: [],
    columns: [],
    height: 500,
    settings: {
      // Disable problematic ARIA attributes that cause accessibility issues
      ariaTags: false,
      // Use grid role instead of treegrid for better accessibility
      tableClassName: 'htCenter',
      // Disable focus management to avoid focus catcher issues
      outsideClickDeselects: false,
      // Use simpler accessibility mode
      autoWrapRow: false,
      autoWrapCol: false
    },
    licenseKey: undefined,
    maxRows: this.licenceState.value.stage_rows_allowed || Infinity,
    afterGetColHeader: (column, th, headerLevel) => {
      // Dark mode
      th.classList.add(globals.handsontable.darkTableHeaderClass)
    },
    afterInit: () => {
      // Fix accessibility issues with focus catcher inputs
      this.fixFocusCatcherAccessibility()
    }
  }

  // Stable settings reference so the HOT v17 wrapper doesn't re-run
  // updateSettings on every change-detection tick. Updated only when the data/
  // columns or license change.
  hotTableSettings = signal<Handsontable.GridSettings>(this.buildHotSettings())

  private buildHotSettings(): Handsontable.GridSettings {
    return {
      ...this.hotTable.settings,
      colHeaders: this.hotTable.colHeaders,
      columns: this.hotTable.columns,
      maxRows: this.hotTable.maxRows,
      height: this.hotTable.height,
      licenseKey: this.hotTable.licenseKey,
      afterGetColHeader: this.hotTable.afterGetColHeader,
      afterInit: this.hotTable.afterInit,
      stretchH: 'all',
      cells: this.hotTable.cells,
      className: 'htDark',
      theme: 'ht-theme-classic'
    }
  }

  constructor(
    private licenceService: LicenceService,
    private sasStoreService: SasStoreService,
    private eventService: EventService,
    private route: Router,
    private router: ActivatedRoute,
    private sasService: SasService
  ) {}

  public submittedTableScreen() {
    this.route.navigateByUrl('/stage/' + this.table_id)
  }

  public approveTableScreen() {
    this.route.navigateByUrl('/review/approveDet/' + this.table_id)
  }

  public viewerTableScreen() {
    this.route.navigateByUrl('/view/data/' + this.tableDetails.BASE_TABLE)
  }

  public goBack() {
    const xlmap = globals.xlmaps.find(
      (xlmap) => xlmap.targetDS === this.tableDetails.BASE_TABLE
    )
    if (xlmap) {
      const id = this.hotTable.data[0].XLMAP_ID
      this.route.navigateByUrl('/home/excel-maps/' + id)
    } else {
      this.route.navigateByUrl('/editor/' + this.tableDetails.BASE_TABLE)
    }
  }

  public download(id: any) {
    let sasjsConfig = this.sasService.getSasjsConfig()
    let storage = sasjsConfig.serverUrl
    let metaData = sasjsConfig.appLoc
    let path = this.sasService.getExecutionPath()
    let downUrl =
      storage +
      path +
      '/?_program=' +
      metaData +
      '/services/auditors/getauditfile&table=' +
      id
    window.open(downUrl)
  }

  async ngOnInit() {
    this.licenceService.hot_license_key.subscribe(
      (hot_license_key: string | undefined) => {
        this.hotTable.licenseKey = hot_license_key
        this.hotTableSettings.set(this.buildHotSettings())
      }
    )

    if (typeof this.router.snapshot.params['tableId'] !== 'undefined') {
      this.table_id = this.router.snapshot.params['tableId']

      try {
        let res = await this.sasStoreService.getChangeInfo(this.table_id)

        if (!(res && res.jsparams))
          throw new Error('jsparams property is missing from response.')

        this.tableDetails = res.jsparams[0]
      } catch (error: any) {
        let errorObject: any = {}

        if (!error.MESSAGE) {
          errorObject.MESSAGE = error
        } else {
          errorObject = error
        }

        this.eventService.catchResponseError(
          'public/getchangeinfo',
          errorObject
        )
      }

      try {
        let res = await this.sasStoreService.openTable(this.table_id)

        if (!(res && res.stagetable))
          throw new Error('Stagetable property is missing from response.')

        let cols = res.stagetable[0]
        let colHeaders = []
        let columns: any[] = []

        for (let key in cols) {
          if (cols) {
            colHeaders.push(key)
          }
        }

        for (let index = 0; index < colHeaders.length; index++) {
          columns.push({
            data: colHeaders[index]
          })
        }

        let cells = function () {
          let cellProperties = { readOnly: true }
          return cellProperties
        }

        this.hotTable.data = res.stagetable
        this.hotTable.colHeaders = colHeaders
        this.hotTable.columns = columns
        this.hotTable.cells = cells
        this.hotTableSettings.set(this.buildHotSettings())

        this.loaded = true
        this.setFocus()
      } catch (error: any) {
        let errorObject: any = {}

        if (!error.MESSAGE) errorObject.MESSAGE = error

        this.eventService.catchResponseError(
          'auditors/getstagetable',
          errorObject
        )
        this.loaded = false
      }
    }
  }

  ngAfterViewInit() {
    // Additional accessibility fixes after view is initialized
    setTimeout(() => {
      this.fixFocusCatcherAccessibility()
    }, 500)
  }

  revertChanges() {
    this.revertingChanges = true

    const data = {
      restore_in: [
        {
          load_ref: this.table_id
        }
      ]
    }

    this.sasService
      .request('editors/restore', data)
      .then((res: RequestWrapperResponse<EditorsRestoreServiceResponse>) => {
        if (res.adapterResponse.restore_out) {
          this.route.navigate([`/stage`]).then(() => {
            this.route.navigate([
              `/stage/${res.adapterResponse.restore_out[0].LOADREF}`
            ])
          })
        }
      })
      .finally(() => {
        this.revertingChanges = false
      })
  }

  private setFocus() {
    setTimeout(() => {
      let approvalBtn: any = window.document.getElementById('approval-btn')
      if (!!approvalBtn) {
        approvalBtn.focus()
      }
    }, 200)
  }

  private fixFocusCatcherAccessibility() {
    // Add labels to focus catcher inputs to fix accessibility issues
    setTimeout(() => {
      const focusCatchers = document.querySelectorAll('.htFocusCatcher')
      focusCatchers.forEach((input: any, index: number) => {
        if (input) {
          // Add proper accessibility attributes
          input.setAttribute('aria-label', `Table focus catcher ${index + 1}`)
          input.setAttribute('aria-hidden', 'true')
          input.setAttribute('tabindex', '-1')
          input.setAttribute('role', 'presentation')
          // Add a hidden label element
          const label = document.createElement('label')
          label.setAttribute('for', input.id || `htFocusCatcher${index}`)
          label.setAttribute('aria-hidden', 'true')
          label.style.display = 'none'
          label.textContent = `Table focus catcher ${index + 1}`
          input.parentNode?.insertBefore(label, input)
        }
      })
    }, 100)
  }
}
