import { first } from 'rxjs/operators';
import { NgClass } from '@angular/common';
import { ActivatedRoute, Router } from '@angular/router';
import { NgxSpinnerService, NgxSpinnerComponent } from "ngx-spinner";
import { NgbModal, NgbModalOptions } from '@ng-bootstrap/ng-bootstrap';
import { Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core';
import { DropDownFilterSettings, KENDO_DROPDOWNS } from '@progress/kendo-angular-dropdowns';
import { FormBuilder, FormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';

import { Api } from '../../providers/api/api';
import packageJson from '../../../package.json';
import { AlertService } from '../components/alert';
import { BreadcrumbService } from '../breadcrumb.service';
import { ChangePwdComponent } from './changepwd.component';
import { IdleMonitorService } from '../idleMonitor.service';
import { ConfigurationService } from '../app.config.service';
import { OtpComponent } from '../components/otp/otp.component';
import { FunctionService } from '../components/models/function.service';
import { AuthenticationService } from '../../providers/user/authentication.service';
import { AppConfig, ComputerConfig } from '../components/models/app.config.model';

@Component({
  standalone: true,
  selector: 'app-login',
  templateUrl: './login.component.html',
  imports: [FormsModule, ReactiveFormsModule, NgClass, NgxSpinnerComponent, KENDO_DROPDOWNS]
})
export class LoginComponent implements OnInit
{
  private readonly router = inject(Router);
  private readonly route = inject(ActivatedRoute);
  private readonly modalService = inject(NgbModal);
  private readonly fnSvc = inject(FunctionService);
  private readonly formBuilder = inject(FormBuilder);
  private readonly alertService = inject(AlertService);
  private readonly idleSvc = inject(IdleMonitorService);
  private readonly spinnerService = inject(NgxSpinnerService);
  private readonly authService = inject(AuthenticationService);

  public loginForm: FormGroup;
  public loading: boolean = false;
  public submitted: boolean = false;
  public lateLoginRemarks: any[] = [];
  public fieldTextType: boolean = false;
  public remarksRequired: boolean = false;
  public attendanceEnabled: boolean = false;
  public filterSettings: DropDownFilterSettings = { caseSensitive: false, operator: "contains" };

  private hostName: string = '';
  private ipAddress: string = '';
  private appVersion: string = '';
  private macAddress: string = '';
  private readonly appConfig: AppConfig;
  private readonly compConfig: ComputerConfig;
  private enableBrowserPassword: boolean = false;
  @ViewChild('loginId') private readonly loginId: ElementRef;
  @ViewChild('password') private readonly password: ElementRef;

  constructor()
  {
    this.alertService.clear();
    const configSvc = inject(ConfigurationService);
    this.appConfig = configSvc.configuration?.appConfig;
    this.compConfig = configSvc.configuration?.computerConfig;

    if (this.authService.currentUserValue?.id)
    {
      if (this.authService.currentUserValue.dbOnStartup)
        this.router.navigate(['/dashboard']);
      else
        this.router.navigate(['/home']);
    }
    else
    {
      const breadcrumbService = inject(BreadcrumbService);
      breadcrumbService.setItems([{ label: 'Login', routerLink: ['/login'] }]);
    }
  }

  ngOnInit(): void
  {
    this.alertService.clear();
    this.spinnerService.hide();
    this.appVersion = packageJson.version;
    this.loginForm = this.formBuilder.group(
      {
        loginId: ['', Validators.required],
        password: ['', Validators.required],
        remberMe: false,
        atndnceLogin: false,
        loginRemarks: ''
      });

    let maxLoginTime: number = 570;
    

    if (this.compConfig)
    {
      if (this.appConfig.secretKey)
      {
        maxLoginTime = +(this.appConfig.maxLoginTime || 570);
        this.enableBrowserPassword = this.appConfig.enableBrowserPassword || false;
      }

      if (this.compConfig.status === 998)
      {
        this.attendanceEnabled = false;
        this.alertService.error(`It's seems, You are using AnyDesk (${this.compConfig.remoteHost}).`);
      }
      else if (this.compConfig.status === 999)
      {
        this.attendanceEnabled = false;
        this.alertService.error(`It's seems, You are using Remote Desktop (${this.compConfig.remoteHost}).`);
      }
      else
      {
        this.hostName = this.compConfig.hostName ?? '';
        this.ipAddress = this.compConfig.ipAddress ?? '';
        this.macAddress = this.compConfig.macAddress ?? '';
        this.attendanceEnabled = this.ipAddress?.length > 0;

        const currentTime: Date = new Date();
        const maxTime: Date = new Date(currentTime.getFullYear(), currentTime.getMonth(), currentTime.getDate(), 0, maxLoginTime);
        this.remarksRequired = this.ipAddress?.length > 0 && currentTime > maxTime;
      }

      this.loadLoginRemarks();
    }

    this.initControls();
  }

  private loadLoginRemarks(): void
  {
    const autId = this.fnSvc.cipherData(Api.cipherSecretKey ?? '');
    this.authService.getLoginRemarks(autId).subscribe(
      {
        next: (resp: any) =>
        {
          if (resp.returnStatus === 200)
          {
            this.lateLoginRemarks = resp.value ?? [];
          }
          else
          {
            this.lateLoginRemarks = [];
          }
        },
        error: () =>
        {
          this.lateLoginRemarks = [];
        }
      });
  }

  private initControls(): void
  {
    let loginId: string = '';
    let remberMe: boolean = false;
    let sysDate = this.fnSvc.getDate(new Date());
    let savedSysDate = localStorage.getItem('OnlineSalesAutoCrop.sysdate');

    let savedData: string = localStorage.getItem('OnlineSalesAutoCrop.rlap');
    if (savedData != undefined && savedData != null)
    {
      let splitted = savedData.split('~');
      if (splitted.length == 2 && this.fnSvc.decrypt(splitted[1]) === '1')
      {
        remberMe = true;
        loginId = this.fnSvc.decrypt(splitted[0]);
      }
    }

    this.loginForm.patchValue(
      {
        loginId: loginId,
        password: '',
        remberMe: remberMe,
        atndnceLogin: this.attendanceEnabled && (!savedSysDate || sysDate !== savedSysDate)
      });

    if (this.loginId?.nativeElement && !this.f.loginId.value)
      this.loginId.nativeElement.focus();
    else if (this.password?.nativeElement && !this.f.password.value)
      this.password.nativeElement.focus();
  }

  public toggleFieldTextType(): void
  {
    if (this.f.password?.value)
      this.fieldTextType = !this.fieldTextType;
  }

  public disablePaste(e: any): void
  {
    e.preventDefault();
  }

  public onFocus(): void
  {
    this.fieldTextType = false;
  }

  public onKeyUp(e: any): void
  {
    if (!e.cancelable && !this.enableBrowserPassword)
    {
      this.f.password.setValue('')
      e.target.value = '';
      this.fieldTextType = false;

      e.preventDefault();
    }
  }

  public eventCheck(event: any): void
  {
    if (event?.target?.checked && this.remarksRequired)
    {
      this.fnSvc.setValidatorsToToControl({ control: this.f.loginRemarks, required: 1, regExp: '' });
    }
    else
    {
      this.f.loginRemarks.clearValidators();
      this.f.loginRemarks.updateValueAndValidity();
    }
  }

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

  public onSubmit()
  {
    this.submitted = true;

    //Aeset alerts on submit
    this.alertService.clear();
    if (this.loginForm.invalid)
      return;

    //Encrypted Data for remember me
    let loginInf: string = this.fnSvc.encrypt(this.f.loginId.value) + '~' + this.fnSvc.encrypt(this.f.remberMe.value ? "1" : "0");

    //Do regular operation
    this.loading = true;
    const sysDate = this.fnSvc.getDate(new Date());

    this.spinnerService.show();
    const params: any =
    {
      appVersion: this.appVersion,
      attendanceLogin: this.f.atndnceLogin.value,
      appId: this.fnSvc.cipherData(Api.firebaseToken),
      loginId: this.fnSvc.cipherData(this.f.loginId.value),
      password: this.fnSvc.cipherData(this.f.password.value),
      hostName: this.fnSvc.cipherData(this.hostName),
      ipAddress: this.fnSvc.cipherData(this.ipAddress),
      macAddress: this.fnSvc.cipherData(this.macAddress),
      loginRemarks: this.f.loginRemarks.value ?? ''
    };

    this.authService.login(params)
      .pipe(first())
      .subscribe(
        {
          next: (data) =>
          {
            this.loading = false;
            this.spinnerService.hide();
            if (data.authRequiredAtLogin)
            {
              this.authService.loggedIn(data, false);
              const modalOptions: NgbModalOptions = { backdrop: 'static', keyboard: false, backdropClass: 'customBackdrop', centered: true, windowClass: 'misc-width' };
              const modalRef = this.modalService.open(OtpComponent, modalOptions);

              modalRef.componentInstance.fromParent = { userId: data.id, authMethod: data.authMethod };
              modalRef.result.then((result) =>
              {
                if (result)
                {
                  if (data.pwdChangeRequired)
                  {
                    this.authService.loggedIn(data, false);
                    const modalOptions1: NgbModalOptions = { backdrop: 'static', keyboard: false, backdropClass: 'customBackdrop', centered: true };
                    const modalRef1 = this.modalService.open(ChangePwdComponent, modalOptions1);
                    modalRef1.componentInstance.fromParent = { userId: data.id, loginId: data.loginId, userName: data.userName };

                    modalRef1.result.then(() =>
                    {
                      this.authService.loggedout();
                    });
                  }
                  else
                  {
                    this.authService.refreshToken().subscribe(
                      {
                        next: () =>
                        {
                          localStorage.setItem('OnlineSalesAutoCrop.sysdate', sysDate);
                          if (this.f.remberMe.value)
                            localStorage.setItem('OnlineSalesAutoCrop.rlap', loginInf);
                          else
                            localStorage.removeItem('OnlineSalesAutoCrop.rlap');

                          this.idleSvc.startMonitor();
                          this.authService.raiseLoginEvent(data.id, true);
                          const returnUrl = this.authService.currentUserValue?.dbOnStartup ? this.route.snapshot.queryParams['returnUrl'] ?? '/dashboard' : this.route.snapshot.queryParams['returnUrl'] ?? '/home';
                          this.router.navigate([returnUrl]);
                        },
                        error: () =>
                        {
                          this.authService.loggedout();
                        }
                      });
                  }
                }
                else
                {
                  localStorage.removeItem('OnlineSalesAutoCrop.rlap');
                  localStorage.removeItem('OnlineSalesAutoCrop.sysdate');

                  this.authService.loggedout();
                }
              });
            }
            else if (data.pwdChangeRequired)
            {
              this.authService.loggedIn(data, false);
              const modalOptions: NgbModalOptions = { backdrop: 'static', keyboard: false, backdropClass: 'customBackdrop', centered: true };
              const modalRef = this.modalService.open(ChangePwdComponent, modalOptions);
              modalRef.componentInstance.fromParent = { userId: data.id, loginId: data.loginId, userName: data.userName };;

              modalRef.result.then(() =>
              {
                this.authService.loggedout();
              });
            }
            else
            {
              this.authService.refreshToken().subscribe(
                {
                  next: () =>
                  {
                    localStorage.setItem('OnlineSalesAutoCrop.sysdate', sysDate);
                    if (this.f.remberMe.value)
                      localStorage.setItem('OnlineSalesAutoCrop.rlap', loginInf);
                    else
                      localStorage.removeItem('OnlineSalesAutoCrop.rlap');

                    this.idleSvc.startMonitor();
                    this.authService.raiseLoginEvent(data.id, true);
                    const returnUrl = this.authService.currentUserValue?.dbOnStartup ? this.route.snapshot.queryParams['returnUrl'] ?? '/dashboard' : this.route.snapshot.queryParams['returnUrl'] ?? '/home';
                    this.router.navigate([returnUrl]);
                  },
                  error: () =>
                  {
                    localStorage.removeItem('OnlineSalesAutoCrop.rlap');
                    localStorage.removeItem('OnlineSalesAutoCrop.sysdate');

                    this.authService.loggedout();
                  }
                });
            }
          },
          error: (errorMessage: string) =>
          {
            this.loading = false;
            this.spinnerService.hide();
            localStorage.removeItem('OnlineSalesAutoCrop.rlap');
            localStorage.removeItem('OnlineSalesAutoCrop.sysdate');

            this.alertService.error(errorMessage);
          }
        });
  }
}
