import * as base32 from 'hi-base32';
import { Router } from '@angular/router';
import { NgClass } from '@angular/common';
import { Component, OnInit, computed, inject } from '@angular/core';
import { QRCodeComponent } from '@progress/kendo-angular-barcodes';
import { DropDownListComponent } from '@progress/kendo-angular-dropdowns';
import { NumericTextBoxComponent } from '@progress/kendo-angular-inputs';
import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RowArgs, GridComponent, SelectionDirective, CheckboxColumnComponent, ColumnComponent } from '@progress/kendo-angular-grid';

import { AlertService } from '../components/alert';
import { BreadcrumbService } from '../breadcrumb.service';
import { UserService } from '../../providers/user/user.service.';
import { FunctionService } from '../components/models/function.service';
import { EmployeeControlComponent } from '../components/employeepicker/employeecontrol.component';

@Component({
  standalone: true,
  selector: 'edit-user',
  templateUrl: './edituser.component.html',
  imports: [FormsModule, ReactiveFormsModule, EmployeeControlComponent, NgClass, DropDownListComponent, QRCodeComponent, GridComponent, SelectionDirective, CheckboxColumnComponent, ColumnComponent, NumericTextBoxComponent]
})
export class EditUserComponent implements OnInit
{
  private readonly router = inject(Router);
  private readonly service = inject(UserService);
  private readonly fnSvc = inject(FunctionService);
  private readonly formBuilder = inject(FormBuilder);
  private readonly alertService = inject(AlertService);

  public setting: any;
  public loading = false;
  public canEdit: boolean;
  public items: any[] = [];
  public submitted = false;
  public required: string = '';
  public qrCodeData: string = '';
  public edituserForm: FormGroup;
  public selectedIds: number[] = [];
  public selectedKeys(context: RowArgs): number { return context.dataItem.groupId; };
  public authMethods: any = [{ id: 0, value: 'None' }, { id: 1, value: 'Email' }, { id: 2, value: 'Mobile SMS' }, { id: 3, value: 'Third Party Authenticator' }];

  private userId: number = 0;
  private authKey: string = '';
  private settingApplied: boolean = false;

  constructor()
  {
    const bcService = inject(BreadcrumbService);
    if (!this.service.currentUserValue)
    {
      this.router.navigate(['/login']);
      return;
    }

    const navigated = computed(() => this.router.currentNavigation())();
    this.userId = +navigated?.extras?.state?.id;
    this.setting = navigated?.extras?.state?.setting;

    this.canEdit = this.service.currentUserValue?.moduleIds?.includes('ELIT.1.2.2_2');
    bcService.setItems([{ label: 'System Setup' }, { label: 'User Management' }, { label: 'Users', routerLink: ['/users'] }, { label: (this.canEdit ? 'Edit User' : 'View User'), routerLink: ['/edituser'] }]);
  }

  ngOnInit()
  {
    this.edituserForm = this.formBuilder.group(
      {
        loginId: '',
        isEmployee: { value: false, disabled: true },
        employeeId: { value: null, disabled: true },
        username: { value: '', disabled: !this.canEdit },
        designation: { value: '', disabled: !this.canEdit },
        mobileNo: { value: '', disabled: !this.canEdit },
        seqId: { value: 1, disabled: !this.canEdit },
        canUseAtnSys: { value: true, disabled: !this.canEdit },
        emailAddress: { value: '', disabled: !this.canEdit },
        dbOnStartup: { value: false, disabled: !this.canEdit },
        daMultiLogin: { value: false, disabled: !this.canEdit },
        status: { value: false, disabled: !this.canEdit },
        neverExpire: { value: false, disabled: !this.canEdit },
        accessStatus: { value: false, disabled: !this.canEdit },
        authReqAtlogin: { value: false, disabled: !this.canEdit },
        authMethod: { value: { id: 0 }, disabled: true },
        viewToAll: { value: false, disabled: !this.canEdit }
      }
    );

    this.setValidatorsToControls();
    if (this.userId)
    {
      this.service.getUser(this.userId).subscribe(
        {
          next: (resp: any) =>
          {
            if (resp.returnStatus === 200)
            {
              this.userId = resp.userId;
              this.selectedIds = resp.groupIds ?? [];

              this.edituserForm.reset(
                {
                  loginId: resp.loginId,
                  isEmployee: (resp.employeeCode?.length >= 3),
                  employeeId: { code: resp.employeeCode },
                  username: resp.userName,
                  designation: resp.designation,
                  mobileNo: resp.mobileNo,
                  emailAddress: resp.emailAddress,
                  seqId: resp.seqId,
                  dbOnStartup: resp.dbOnStartup,
                  daMultiLogin: resp.disallowMultiLogin,
                  status: (resp.status === 8),
                  viewToAll: resp.viewToAll,
                  canUseAtnSys: resp.canUseAttendanceSystem,
                  neverExpire: { value: resp.neverExpire, disabled: (resp.accessStatus === 1 || !this.canEdit) },
                  accessStatus: { value: (resp.accessStatus === 1), disabled: (resp.neverExpire || !this.canEdit) },
                  authReqAtlogin: resp.authRequiredAtLogin,
                  authMethod: { value: { id: resp.authMethod }, disabled: (resp.authMethod <= 0 || !this.canEdit) },
                });

              if (this.f.isEmployee.value)
              {
                this.f.username.disable();
                this.f.designation.disable();
                this.f.mobileNo.disable();
                this.f.emailAddress.disable();
              }
              else
              {
                this.f.username.enable();
                this.f.designation.enable();
                this.f.mobileNo.enable();
                this.f.emailAddress.enable();
              }
              this.authKey = resp.authKey ?? "";
              this.generate({ id: resp.authMethod });

              this.loadGroups();
            }
            else
            {
              this.alertService.error(resp.returnMessage);
            }
          },
          error: (errorMessage: string) =>
          {
            this.alertService.error(errorMessage);
          }
        });
    }
  }

  private setValidatorsToControls(): void
  {
    if (!this.settingApplied && this.setting && this.edituserForm?.controls)
    {
      this.settingApplied = true;
      this.fnSvc.setValidatorsToToControl({ control: this.f.loginId, required: this.setting.label01Req, regExp: this.setting.label01RegExp, minLen: 3, maxLen: 30 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.username, required: this.setting.label02Req, regExp: this.setting.label02RegExp, minLen: 3, maxLen: 75 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.mobileNo, required: this.setting.label03Req, regExp: this.setting.label03RegExp, minLen: 0, maxLen: 15 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.emailAddress, required: this.setting.label04Req, regExp: this.setting.label04RegExp, minLen: 0, maxLen: 100 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.designation, required: this.setting.label19Req, regExp: this.setting.label19RegExp, minLen: 0, maxLen: 50 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.seqId, required: this.setting.label26Req, regExp: this.setting.label26RegExp, minValue: 1, maxValue: 999999 });
    }
  }

  private loadGroups(): void
  {
    const params = { criteria: '', status: 8 };
   
  }

  public generate(value: any): void
  {
    if (value?.id === 3)
    {
      if (this.authKey == undefined || this.authKey.length <= 0)
      {
        let base32EncString = base32.encode(this.userId + '~' + this.f.loginId.value);
        let re = /=/g;
        base32EncString = base32EncString.replace(re, '');
        this.authKey = base32EncString;
      }
      this.qrCodeData = 'otpauth://totp/' + this.f.loginId.value + '?secret=' + this.authKey;
    }
  }

  public eventCheck(event: any, controlId: number): void
  {
    if (controlId === 1)
    {
      if (event?.target?.checked)
      {
        this.edituserForm.get('accessStatus').disable();
        this.edituserForm.get('accessStatus').setValue(false);
      }
      else
      {
        this.edituserForm.get('accessStatus').enable();
      }
    }
    else if (controlId === 2)
    {
      if (event?.target?.checked)
      {
        this.edituserForm.get('neverExpire').disable();
        this.edituserForm.get('neverExpire').setValue(false);
      }
      else
      {
        this.edituserForm.get('neverExpire').enable();
      }
    }
    else if (controlId === 3)
    {
      this.required = '';
      if (event?.target?.checked)
      {
        this.required = 'required';
        this.edituserForm.get('authMethod').enable();
      }
      else
      {
        this.edituserForm.get('authMethod').setValue({ id: 0 });
        this.edituserForm.get('authMethod').disable();
      }
    }
  }

  private convertBase64ToBlob(Base64Image: string)
  {
    //Split into two parts
    const parts = Base64Image.split(";base64,")

    //Hold the content type
    const imageType = parts[0].split(":")[1]

    //Decode base64 string
    const decodedData = atob(parts[1])

    //Create unit8array of size same as row data length
    const uInt8Array = new Uint8Array(decodedData.length)

    //Insert all character code into uint8array
    for (let i = 0; i < decodedData.length; ++i)
    {
      uInt8Array[i] = decodedData.charCodeAt(i)
    }

    //Return blob image after conversion
    return new Blob([uInt8Array], { type: imageType })
  }

  public sendmail(parent: any): void
  {
    let email = this.f.emailAddress.value || '';
    if (email.length > 0)
    {
      this.alertService.clear();
      parent.exportImage().then((dataURI: any) =>
      {
        const blobData = this.convertBase64ToBlob(dataURI);
        const blob = new Blob([blobData], { type: "image/png" });
        const qrImage = new File([blob], "qrCode.png");

        const formData = new FormData();
        formData.append('emailAddress', this.f.emailAddress.value);
        formData.append('fileName', 'qrCode.png');
        formData.append('fileData', qrImage);

        this.service.sendQrCodeViaEmail(formData).subscribe(
          {
            next: (resp: any) =>
            {
              if (resp.returnStatus === 200)
              {
                this.alertService.info(resp.returnMessage);
              }
              else
              {
                this.alertService.error(resp.returnMessage);
              }
            },
            error: (errorMessage: string) =>
            {
              this.alertService.error(errorMessage);
            }
          });
      });
    }
  }

  public keyPressEvent(event: any): boolean
  {
    return this.fnSvc.validateNumbers({ event: event, includePlus: true });
  }

  get f() { return this.edituserForm.controls; }

  public onSubmit(): void
  {
    this.submitted = true;
    this.alertService.clear();

    if (this.f.authReqAtlogin.value && +(this.f.authMethod.value.id ?? '0') <= 0)
    {
      this.alertService.error('Authentication method is required');
      return;
    }

    if (this.edituserForm.invalid)
      return;

    let authMethod = this.f.authReqAtlogin.value ? +(this.f.authMethod.value.id ?? '0') : 0;
    const params: any =
    {
      userId: this.userId,
      loginId: this.f.loginId.value,
      employeeId: this.f.employeeId.value?.employeeId,
      employeeCode: this.f.employeeId.value?.employeeCode,
      userName: this.f.username.value,
      designation: this.f.designation.value,
      mobileNo: this.f.mobileNo.value,
      emailAddress: this.f.emailAddress.value,
      seqId: +(this.f.seqId.value ?? '1'),
      viewToAll: this.f.viewToAll.value,
      canUseAttendanceSystem: this.f.canUseAtnSys.value,
      dbOnStartup: this.f.dbOnStartup.value,
      disallowMultiLogin: this.f.daMultiLogin.value,
      status: (this.f.status.value ? 8 : 16),
      neverExpire: this.f.neverExpire.value,
      accessStatus: this.f.accessStatus.value ? 1 : 3,
      authReqAtlogin: this.f.authReqAtlogin.value,
      authMethod: authMethod,
      authKey: (authMethod === 3) ? this.authKey : '',
      groupIds: this.selectedIds
    };

    this.loading = true;
    this.service.editUser(params).subscribe(
      {
        next: (resp: any) =>
        {
          this.loading = false;
          if (resp.returnStatus === 200)
          {
            this.alertService.info(resp.returnMessage);
          }
          else
          {
            this.alertService.error(resp.returnMessage);
          }
        },
        error: (errorMessage: string) =>
        {
          this.loading = false;
          this.alertService.error(errorMessage);
        }
      });
  }
}
