import { ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from "@angular/core";
import { DialogService } from "src/app/shared/services/dialog.service";
import {
  searchRecoveryKeyFromFile, selectLocalFile
} from "src/app/shared/file-reader";
import { base64 } from "rfc4648";
import { marker } from "@biesbjerg/ngx-translate-extract-marker";
import { ServerRestApiService } from "src/app/shared/services/server-rest-api.service";
import { RouterHandler } from "src/app/shared/services/router-handler.service";
import { create_account_recovery_confirm_request } from "src/app/shared/crypto/auth/recovery";
import { PrivateKeyringV1 } from "src/app/shared/crypto/keyring/private";
import { USE_PASSWORD_NORMALIZATION } from "src/app/shared/consts/upgrade";
import { FormBuilder, Validators } from "@angular/forms";
import { NanoValidators } from "src/app/shared/nano-validators";

@Component({
  selector: "app-account-recovery-confirm",
  templateUrl: "./account-recovery-confirm.component.html",
  styleUrls: ["./account-recovery-confirm.component.scss"],
})
export class AccountRecoveryConfirmComponent implements OnInit {
  public isOperationSuccess: boolean = false;
  public masterKey: Uint8Array;
  public currStep = 1;
  public stepRecovery = 1;
  public stepPassword = 2;
  public isPending: boolean = false;
  public passwordScore: number;
  public urlToken: string;
  public accountId: string;
  public signingSecretEc: Uint8Array;

  public recoveryKeyGroup = this.fb.group({
    recoveryKey: ['', [Validators.required]]
  });

  public passwordGroup = this.fb.group({
    password: ['', [Validators.required]],
    password2:  ['', [Validators.required]]
  });

  @ViewChild('recoveryKeyInput') recoveryKeyInput: ElementRef;

  constructor(
    private routerHandler: RouterHandler,
    private dialogService: DialogService,
    private serverApiService: ServerRestApiService,
    private fb: FormBuilder
  ) {
    this.isPending = true;
    let fragment = this.routerHandler.getRoute().fragment["recover-account"];
    if (fragment) {
      this.urlToken = fragment;
      this.serverApiService
        .accountRecoveryChallenge(this.urlToken)
        .then((response) => {
          this.accountId = response.account_id;
          this.signingSecretEc = base64.parse(response.signing_secret_ec);
          this.isPending = false;
        })
        .catch((err) => {
          console.log("wrong url fragment", err);
          this.dialogService.openAlertDialog(
            marker("Error"),
            marker("Wrong or broken url token.")
          );
          this.routerHandler.navigate(["/"]);
        });
    } else {
      this.dialogService.openAlertDialog(
        marker("Error"),
        marker("Missing url token.")
      );
      this.routerHandler.navigate(["/"]);
    }
  }

  ngOnInit(): void {
    this.passwordGroup.get("password2").addValidators([NanoValidators.controlEquals(this.passwordGroup.get("password"))]);
    this.passwordGroup.get("password").addValidators([NanoValidators.passwordStrengthLow(() => this.passwordScore)]);

    this.passwordGroup.get("password").valueChanges.subscribe(e => {
      if(this.passwordGroup.get("password2").touched){
        this.passwordGroup.get("password2").updateValueAndValidity();
      }
    });
  }

  public uploadKey(event) {
    let files = event?.target?.files;
    if (files){
      let file = files[0];
      searchRecoveryKeyFromFile(file)
        .then((key) => {
          this.recoveryKeyGroup.get("recoveryKey").setValue(base64.stringify(key));
          this.masterKey = key;
          this.recoveryKeyInput.nativeElement.focus();
        })
        .catch((err) => {
          console.error("can not find recovery key in the file", err);
          this.dialogService.openAlertDialog(
            marker("Error"),
            marker("Can not find recovery key in the file")
          );
        });
    }
    
  }

  public parseRecoveryKey() {
    try {
      this.masterKey = base64.parse(this.recoveryKeyGroup.get("recoveryKey").value);
      this.currStep = this.stepPassword;
    } catch (e) {
      this.dialogService.openAlertDialog(
        marker("Error"),
        marker("Code is invalid or broken.")
      );
    }
  }

  public backToRecoverytStep() {
    this.currStep = this.stepRecovery;
  }

  public passwordStrength(score) {
    this.passwordScore = score;
    this.passwordGroup.get("password").updateValueAndValidity();
  }

  public submit() {
    this.isPending = true;

    create_account_recovery_confirm_request(
      PrivateKeyringV1,
      this.urlToken,
      this.accountId,
      this.signingSecretEc,
      this.masterKey,
      this.passwordGroup.get("password").value,
      USE_PASSWORD_NORMALIZATION
    )
      .then((result) => {
        this.serverApiService
          .accountRecoverConfirm(result)
          .then(() => {
            this.dialogService.openAlertDialog(
              marker("Success"),
              marker("Password change was succesful")
            );
            this.routerHandler.navigate(["/login"]);
          })
          .catch((err) => {
            console.log("acc confirm err", err);
            this.dialogService.openAlertDialog(
              marker("Error"),
              marker("Error happened during the operation")
            );
          });
      })
      .catch((err) => {
        console.error("recovery confirm error", err);
        this.dialogService.openAlertDialog(
          marker("Error"),
          marker("Error happened during the operation")
        );
      })
      .finally(() => {
        this.isPending = false;
      });
  }
}
