import { Router } from '@angular/router';
import { NgClass } from '@angular/common';
import { Component, inject, OnInit } from '@angular/core';
import { NgxSpinnerService, NgxSpinnerComponent } from "ngx-spinner"
import { KENDO_DROPDOWNLIST } from '@progress/kendo-angular-dropdowns';
import { NumericTextBoxComponent } from '@progress/kendo-angular-inputs';
import { FormBuilder, FormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';

import { AlertService } from '../components/alert';
import { BreadcrumbService } from '../breadcrumb.service';
import { FunctionService } from '../components/models/function.service';
import { SettingsModuleEnum } from '../components/models/named-parameters.model';
import { ThisSystemService } from '../../providers/thissystem/thissystem.service';

@Component({
  standalone: true,
  selector: 'this-system',
  templateUrl: './thissystem.component.html',
  imports: [FormsModule, ReactiveFormsModule, NgClass, NumericTextBoxComponent, KENDO_DROPDOWNLIST, NgxSpinnerComponent]
})
export class ThisSystemComponent implements OnInit
{
  private readonly router = inject(Router);
  private readonly fnSvc = inject(FunctionService);
  private readonly formBuilder = inject(FormBuilder);
  private readonly alertService = inject(AlertService);
  private readonly service = inject(ThisSystemService);
  private readonly bcService = inject( BreadcrumbService);
  private readonly spinnerService = inject(NgxSpinnerService);

  public setting: any;
  public required: string = '';
  public loading: boolean = false;
  public canEdit: boolean = false;
  public thisSystemForm: FormGroup;
  public submitted: boolean = false;
  public settingApplied: boolean = false;
  public prProcesses: any = [{ id: 0, value: 'Manual' }, { id: 1, value: 'Earliest Invoice' }, { id: 2, value: 'Newest Invoice' }];
  public bmProcesses: any = [{ id: 0, value: 'None' }, { id: 1, value: 'Manual' }, { id: 2, value: 'FIFO (First in First out)' }, { id: 3, value: 'LIFO (Last in First out)' }];
  
  private canEditBMProcess: boolean = true;
  private readonly cantEditCode: boolean = false;

  constructor()
  {
    this.bcService.setItems([{ label: 'System Setup' }, { label: 'System Information', routerLink: ['/thissystem'] }]);
    if (!this.service.currentUserValue)
    {
      this.router.navigate(['/login']);
      return;
    }

    this.canEdit = this.service.currentUserValue?.moduleIds?.includes('ELIT.1.1_2');
    this.cantEditCode = !this.service.currentUserValue?.moduleIds?.includes('ELIT.1.5.15_2');

    this.loadSetting();
  }

  private loadSetting(): void
  {
    this.loading = true;
    this.service.getLabelSetting(SettingsModuleEnum.This_System).subscribe(
      {
        next: (resp: any) =>
        {
          this.loading = false;
          if (resp.returnStatus === 200)
          {
            this.setting = resp;
            this.setValidatorsToControls();
          }
        },
        error: (errorMessage: string) =>
        {
          this.loading = false;
          this.alertService.error(errorMessage);
        }
      });
  }

  ngOnInit(): void
  {
    const cantSave: boolean = !this.canEdit;

    this.thisSystemForm = this.formBuilder.group(
      {
        code: { value: '', disabled: (cantSave || this.cantEditCode) },
        name: { value: '', disabled: cantSave },
        banglaName: { value: '', disabled: cantSave },
        address: { value: '', disabled: cantSave },
        banglaAddress: { value: '', disabled: cantSave },
        phoneNo: { value: '', disabled: cantSave },
        mobileNo: { value: '', disabled: cantSave },
        emailAddress: { value: '', disabled: cantSave },
        website: { value: '', disabled: cantSave },
        vatRegNo: { value: '', disabled: cantSave },
        vatRate: { value: 0, disabled: cantSave },
        enfStgPwd: { value: false, disabled: cantSave },
        pwdMinLen: { value: 1, disabled: cantSave },
        pwdMaxLen: { value: 30, disabled: cantSave },
        pwdRsvdWords: { value: '', disabled: cantSave },
        loginIdCantPwd: { value: false, disabled: cantSave },
        daLastPwds: { value: 0, disabled: cantSave },
        expiryDays: { value: 30, disabled: cantSave },
        prvntAtckPwdReuse: { value: false, disabled: cantSave },
        maxTryCount: { value: 0, disabled: cantSave },
        lockTime: { value: 0, disabled: cantSave },
        appVersion: { value: 0, disabled: cantSave },
        alParams: { value: '', disabled: cantSave },
        batchEnabled: { value: false, disabled: cantSave },
        bmProcessId: { value: 0, disabled: cantSave },
        prProcessId: { value: 0, disabled: cantSave }
      });

    this.setValidatorsToControls();
    this.loadThisSystem();
  }

  private setValidatorsToControls(): void
  {
    if (!this.settingApplied && this.setting && this.thisSystemForm?.controls)
    {
      this.settingApplied = true;

      this.fnSvc.setValidatorsToToControl({ control: this.f.code, required: this.setting.label01Req, regExp: this.setting.label01RegExp, minLen: 2, maxLen: 15 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.name, required: this.setting.label02Req, regExp: this.setting.label02RegExp, minLen: 2, maxLen: 100 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.banglaName, required: this.setting.label03Req, regExp: this.setting.label03RegExp, minLen: 2, maxLen: 100 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.address, required: this.setting.label04Req, regExp: this.setting.label04RegExp, minLen: 0, maxLen: 300 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.banglaAddress, required: this.setting.label05Req, regExp: this.setting.label05RegExp, minLen: 0, maxLen: 300 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.phoneNo, required: this.setting.label06Req, regExp: this.setting.label06RegExp, minLen: 0, maxLen: 50 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.mobileNo, required: this.setting.label07Req, regExp: this.setting.label07RegExp, minLen: 0, maxLen: 50 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.emailAddress, required: this.setting.label08Req, regExp: this.setting.label08RegExp, minLen: 0, maxLen: 50 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.website, required: this.setting.label09Req, regExp: this.setting.label09RegExp, minLen: 0, maxLen: 50 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.vatRegNo, required: this.setting.label10Req, regExp: this.setting.label10RegExp, minLen: 0, maxLen: 50 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.vatRate, required: this.setting.label11Req, regExp: this.setting.label11RegExp, minValue: 0, maxValue: 100 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.pwdMinLen, required: this.setting.label13Req, regExp: this.setting.label13RegExp, minValue: 1, maxValue: 30 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.pwdMaxLen, required: this.setting.label14Req, regExp: this.setting.label14RegExp, minValue: 1, maxValue: 30 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.pwdRsvdWords, required: this.setting.label15Req, regExp: this.setting.label15RegExp, minLen: 0, maxLen: 150 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.daLastPwds, required: this.setting.label17Req, regExp: this.setting.label17RegExp, minValue: 0, maxValue: 10 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.expiryDays, required: this.setting.label18Req, regExp: this.setting.label18RegExp, minValue: 0, maxValue: 365 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.maxTryCount, required: this.setting.label20Req, regExp: this.setting.label20RegExp, minValue: 0, maxValue: 20 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.lockTime, required: this.setting.label21Req, regExp: this.setting.label21RegExp, minValue: 0, maxValue: 1440 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.appVersion, required: this.setting.label22Req, regExp: this.setting.label22RegExp, minLen: 5, maxLen: 11 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.alParams, required: this.setting.label23Req, regExp: this.setting.label23RegExp, minLen: 5, maxLen: 15 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.bmProcessId, required: this.setting.label25Req, regExp: this.setting.label25RegExp, minValue: 0, maxValue: 5 });
      this.fnSvc.setValidatorsToToControl({ control: this.f.prProcessId, required: this.setting.label26Req, regExp: this.setting.label26RegExp, minValue: 0, maxValue: 5 });
    }
  }

  private loadThisSystem(): void
  {
    this.loading = true;
    this.service.getThisSystem().subscribe(
      {
        next: (resp: any) =>
        {
          this.loading = false;
          if (resp.returnStatus === 200)
          {
            this.thisSystemForm.patchValue(
              {
                code: resp.code,
                name: resp.name,
                banglaName: resp.banglaName,
                address: resp.address,
                banglaAddress: resp.banglaAddress,
                phoneNo: resp.phoneNo,
                mobileNo: resp.mobileNo,
                emailAddress: resp.emailAddress,
                website: resp.website,
                vatRegNo: resp.vatRegNo,
                vatRate: resp.vatRate,
                enfStgPwd: resp.enfStgPwd,
                pwdMinLen: resp.pwdMinLen,
                pwdMaxLen: resp.pwdMaxLen,
                pwdRsvdWords: resp.pwdReserveWords,
                loginIdCantPwd: resp.loginIdCantBePassword,
                daLastPwds: resp.disallowLastPwds,
                expiryDays: resp.expiryDays,
                prvntAtckPwdReuse: resp.preventAttackPasswordReuse,
                maxTryCount: resp.maxTryCount,
                lockTime: resp.lockTime,
                appVersion: resp.appVersion,
                alParams: resp.autoLogoutParams,
                batchEnabled: resp.batchEnabled,
                bmProcessId: resp.bmProcessId,
                prProcessId: resp.prProcessId
              });

            this.canEditBMProcess = resp.canEditBatch;
            this.batchEnabledCheckEvent(resp.batchEnabled);
            if (resp.canEditPRProcess && this.f.prProcessId.enabled)
              this.f.prProcessId.enable();
            else
              this.f.prProcessId.disable();
          }
          else
          {
            this.alertService.error(resp.returnMessage);
          }
        },
        error: (errorMessage: string) =>
        {
          this.loading = false;
          this.alertService.error(errorMessage);
        }
      });
  }

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

  public unicodeBangla(event: any, includeCrLf: boolean = false): boolean
  {
    return this.fnSvc.unicodeBangla({ event: event, includeNewline: includeCrLf });
  }

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

  public enfStgPwdCheckEvent(): void
  {
    this.f.pwdMinLen.clearValidators();
    this.f.pwdMaxLen.clearValidators();
    if (this.f.enfStgPwd.value)
    {
      this.f.pwdMinLen.setValue(6);
      this.f.pwdMinLen.setValidators([Validators.required, Validators.min(6), Validators.max(30)]);
      this.f.pwdMaxLen.setValidators([Validators.required, Validators.min(6), Validators.max(30)]);
    }
    else
    {
      this.f.pwdMinLen.setValue(1);
      this.f.pwdMinLen.setValidators([Validators.required, Validators.min(1), Validators.max(30)]);
      this.f.pwdMaxLen.setValidators([Validators.required, Validators.min(1), Validators.max(30)]);
    }
    this.f.pwdMinLen.updateValueAndValidity();
    this.f.pwdMaxLen.updateValueAndValidity();
  }

  public batchEnabledCheckEvent(event: any): void
  {
    if (this.canEditBMProcess === false)
    {
      this.f.bmProcessId.disable();
      this.f.batchEnabled.disable();
    }
    else if (event === true || event?.target?.checked)
    {
      this.required = 'required';
      this.fnSvc.setValidatorsToToControl({ control: this.f.bmProcessId, required: 1, regExp: '', minValue: 1, maxValue: 5 });
      if (this.canEdit)
        this.f.bmProcessId.enable();
      else
        this.f.bmProcessId.disable();
    }
    else
    {
      this.required = '';
      this.f.bmProcessId.disable();
      this.f.bmProcessId.setValue(0);
      this.fnSvc.setValidatorsToToControl({ control: this.f.bmProcessId, required: 0, regExp: '', minValue: 0, maxValue: 5 });
    }
  }

  public onMaxTryCountChange(value: number)
  {
    if (value > 0)
    {
      this.f.lockTime.enable();
    }
    else
    {
      this.f.lockTime.setValue(0);
      this.f.lockTime.disable();
    }
  }

  public onSubmit(): void
  {
    this.submitted = true;
    this.alertService.clear();
    if (this.thisSystemForm.invalid)
      return;

    this.loading = true;
    this.spinnerService.show();
    const params: any =
    {
      code: this.f.code.value,
      name: this.f.name.value,
      banglaName: this.f.banglaName.value,
      address: this.f.address.value,
      banglaAddress: this.f.banglaAddress.value,
      phoneNo: this.f.phoneNo.value,
      mobileNo: this.f.mobileNo.value,
      emailAddress: (this.f.emailAddress.value || '').length <= 0 ? null : this.f.emailAddress.value,
      website: this.f.website.value,
      vatRegNo: this.f.vatRegNo.value,
      vatRate: this.f.vatRate.value,
      enfStgPwd: this.f.enfStgPwd.value,
      pwdMinLen: +(this.f.pwdMinLen.value || '1'),
      pwdMaxLen: +(this.f.pwdMaxLen.value || '30'),
      pwdReserveWords: (this.f.pwdRsvdWords.value || ''),
      loginIdCantBePassword: this.f.loginIdCantPwd.value,
      disallowLastPwds: +(this.f.daLastPwds.value || '0'),
      expiryDays: +(this.f.expiryDays.value || '0'),
      preventAttackPasswordReuse: this.f.prvntAtckPwdReuse.value,
      maxTryCount: +(this.f.maxTryCount.value || '0'),
      lockTime: +(this.f.lockTime.value || '0'),
      appVersion: (this.f.appVersion.value || ''),
      autoLogoutParams: this.f.alParams.value,
      batchEnabled: this.f.batchEnabled.value,
      bmProcessId: +(this.f.bmProcessId.value || '0'),
      prProcessId: +(this.f.prProcessId.value || '0')
    };

    this.service.saveThisSystem(params).subscribe(
      {
        next: (resp: any) =>
        {
          this.loading = false;
          this.spinnerService.hide();
          if (resp.returnStatus === 200)
          {
            this.alertService.success(resp.returnMessage);

            this.loadThisSystem();
          }
          else
          {
            this.alertService.error(resp.returnMessage);
          }
        },
        error: (errorMessage: string) =>
        {
          this.loading = false;
          this.spinnerService.hide();
          this.alertService.error(errorMessage);
        }
      });
  }
}
