import {
  Component,
  Input,
  OnInit,
  Output,
  EventEmitter,
  ViewEncapsulation
} from '@angular/core'
import SASjs, { SASjsConfig } from '@sasjs/adapter'
import { DcAdapterSettings } from 'src/app/models/DcAdapterSettings'
import { RequestWrapperResponse } from 'src/app/models/request-wrapper/RequestWrapperResponse'
import { DeployService } from 'src/app/services/deploy.service'
import { EventService } from 'src/app/services/event.service'
import { LoggerService } from 'src/app/services/logger.service'
import { SasService } from 'src/app/services/sas.service'

@Component({
  selector: 'app-manual-deploy',
  templateUrl: './manual.component.html',
  styleUrls: ['./manual.component.scss'],
  encapsulation: ViewEncapsulation.None,
  standalone: false
})
export class ManualComponent implements OnInit {
  @Input() sasJs!: SASjs
  @Input() sasJsConfig: SASjsConfig = new SASjsConfig()
  @Input() dcAdapterSettings: DcAdapterSettings | undefined

  @Output() onNavigateToHome: EventEmitter<any> = new EventEmitter<any>()

  public needsLogin: boolean = false
  public adminGroups: any = []
  public allContexts: any = []

  public appLoc: string = ''
  public dcPath: string = ''
  public selectedAdminGroup: string = ''
  public selectedContext: string = ''
  public jobLog: string = ''
  public makeDataResponse: string = ''
  public linesOfCode: any = []
  public fileName: string = ''
  public preloadedFile: boolean = true
  public executeSASEnabled: boolean = false

  public contextsLoading: boolean = false
  public createDatabaseLoading: boolean = false
  public executingScript: boolean = false
  public downloadFileBtn: boolean = false
  public isValidating: boolean = false
  public jsonFile: any = null
  public isSubmittingJson: boolean = false
  public isJsonSubmitted: boolean = false
  public validationState: string = 'none'

  constructor(
    private sasService: SasService,
    private eventService: EventService,
    private loggerService: LoggerService,
    private deployService: DeployService
  ) {}

  ngOnInit(): void {}

  /**
   * FIXME: Remove
   */
  public async executableContext() {
    // getExecutableContexts now need AuthConfig parameter which we don't have on web
    // this.contextsLoading = true
    // let contexts = await this.sasJs.getExecutableContexts()
    // this.allContexts = contexts
    // if (contexts.length === 0) {
    //   this.selectedContext = ''
    // } else {
    //   this.selectedContext = this.allContexts[0].name
    // }
    // this.contextsLoading = false
  }

  /**
   * Removes sas.json file attached to the input
   */
  public clearUploadInput(event: Event) {
    this.deployService.clearUploadInput(event)
  }

  /**
   * Reads attached SAS file to be sent to sas for execution (backend deploy)
   */
  public onSasFileChange(event: any) {
    this.preloadedFile = false

    let file = event.target.files[0]
    this.fileName = file.name

    let fileReader = new FileReader()

    fileReader.onload = () => {
      if (fileReader.result) {
        this.linesOfCode = (fileReader.result as string).split('\n')
        this.linesOfCode = this.linesOfCode.filter((el: string) => {
          return el !== '' && el !== null
        })

        this.executeSASEnabled = true

        this.addPrecodeLines()
      }
    }

    fileReader.readAsText(file)
  }

  /**
   * Reads attached JSON file to be sent to sas for execution (backend deploy)
   */
  public async onJsonFileChange(event: any) {
    let file = event.target.files[0]

    this.jsonFile = await this.deployService.readFile(file)
  }

  /**
   * Appending precode lines to the attached sas or json file for backend deploy
   */
  public addPrecodeLines() {
    let headerLines = [
      `%let context=${this.selectedContext};`,
      `%let appLoc=${this.appLoc};`,
      `%let admin=${this.selectedAdminGroup};`,
      `%let dcpath=${this.dcPath};`
    ]

    this.linesOfCode.unshift(...headerLines)
  }

  /**
   * Downloadng file with precode included
   */
  public downloadSasPrecodeFile() {
    let linesAsText = this.linesOfCode.join('\n')
    let filename = this.fileName.split('.')[0]

    this.downloadFile(linesAsText, filename, 'sas')
  }

  /**
   * Used for downloading log and repsonse as a file
   */
  public downloadFile(
    content: any,
    filename: string,
    extension: string = 'txt'
  ) {
    this.deployService.downloadFile(content, filename, extension)
  }

  /**
   * Saving dcpath to localstorage
   * FIXME: maybe it'snot necessary
   */
  public saveDcPath() {
    localStorage.setItem('deploy_dc_loc', this.dcPath)
  }

  /**
   * Send sas.json to be executed (deploying backend)
   */
  public async executeJson() {
    this.isSubmittingJson = true

    try {
      let uploadJsonFile = await this.sasJs.deployServicePack(
        this.jsonFile,
        this.dcAdapterSettings?.appLoc || '',
        undefined,
        undefined,
        true
      )

      this.isJsonSubmitted = true
    } catch (ex: any) {
      let textEx = ''

      if (typeof ex.message !== 'string') {
        textEx = JSON.stringify(ex).replace(/\\/gm, '')
      } else {
        textEx = ex.message
      }

      this.eventService.showInfoModal(
        'Deploy error',
        `Exception: \n ${textEx !== '' ? textEx : ex}`
      )

      return
    }

    this.isSubmittingJson = false
  }

  /**
   * Send sas file to be executed (deploying backend)
   */
  public async executeSAS() {
    this.executingScript = true
    this.jobLog = ''
    this.makeDataResponse = ''

    try {
      let executeResponse = await this.sasJs.executeScript({
        fileName: this.fileName,
        linesOfCode: this.linesOfCode,
        contextName: this.selectedContext
      })

      this.loggerService.log(executeResponse)

      if (typeof executeResponse.log === 'string') {
        executeResponse.log = JSON.parse(executeResponse.log)
      }

      if (executeResponse.jobStatus === 'error') {
        alert('Error!')
      } else {
        this.jobLog = executeResponse.log.items
          ? executeResponse.log.items.map((i: any) => i.line).join('\n')
          : JSON.stringify(executeResponse.log)
      }

      this.executingScript = false
    } catch (err) {
      this.executingScript = false
    }
  }

  /**
   * Running makedata service
   * @param newTab open and run in new tab
   */
  public createDatabase(newTab: boolean = true) {
    if (newTab) {
      let url =
        this.sasService.getSasjsConfig().serverUrl +
          '/SASJobExecution/?_program=' +
          this.dcAdapterSettings?.appLoc ||
        '' +
          '/admin/makedata' +
          '&ADMIN=' +
          this.selectedAdminGroup +
          '&DCPATH=' +
          this.dcPath +
          this.sasService.getDebugUrlParam()

      window.open(url, '_blank')

      return
    }

    this.createDatabaseLoading = true

    let data = {
      fromjs: [
        {
          ADMIN: this.selectedAdminGroup,
          DCPATH: this.dcPath
        }
      ]
    }

    /**
     * We are overriding default `sasjsConfig` object fields with this object fields.
     * Here we want to run this request using original WEB method.
     * contextName: null is the MUST field for it.
     */
    let overrideConfig = {
      useComputeApi: null,
      contextName: this.sasJsConfig.contextName,
      debug: true
    }

    this.sasJs
      .request(`services/admin/makedata`, data, overrideConfig, () => {
        this.sasService.shouldLogin.next(true)
      })
      .then((res: any) => {
        try {
          this.makeDataResponse = JSON.stringify(res)
        } catch {
          this.makeDataResponse = res
        }

        this.createDatabaseLoading = false
      })
      .catch((err: any) => {
        this.createDatabaseLoading = false

        try {
          this.makeDataResponse = JSON.stringify(err)
        } catch {
          this.makeDataResponse = err
        }
      })
  }

  public navigateToHome() {
    this.onNavigateToHome.emit()
  }

  public validateDeploy() {
    this.isValidating = true

    this.sasService
      .request('public/startupservice', null)
      .then((res: RequestWrapperResponse) => {
        this.loggerService.log(res.adapterResponse)

        if (res.adapterResponse.saslibs) {
          this.validationState = 'success'
        } else {
          this.validationState = 'error'
        }

        this.isValidating = false
      })
      .catch((err: any) => {
        this.isValidating = false
        this.validationState = 'error'
      })
  }

  public deleteKeys() {
    localStorage.removeItem('deploy_dc_loc')
  }
}
