import { HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormBuilder, FormGroup, ValidatorFn } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { NgCortexService } from '@ng-cortex/core';
import { getEntityUpdate, validateForm, Validators } from '@ng-cortex/utils';
import { NzNotificationService } from 'ng-zorro-antd/notification';
import { NzUploadFile } from 'ng-zorro-antd/upload';
import { of } from 'rxjs';
import { catchError, mergeMap, tap } from 'rxjs/operators';

/** 个人中心页面 */
@Component({
  selector: 'nc-passport',
  templateUrl: './nc-passport.page.html',
  styleUrls: ['./nc-passport.page.scss']
})
export class NcPassportPage implements OnInit, OnDestroy {

  /** 内容列表 */
  _contentList = ['基本设置', '修改密码'];
  /** 显示内容 */
  _showContent: string = this._contentList[0];
  /** 用户表单 */
  _userForm!: FormGroup;
  /** 用户提交加载状态 */
  _userSubmitLoading: boolean = false;
  /** 用户头像 */
  _avatars: any[] = [];
  /** 密码表单 */
  _passwordForm!: FormGroup;
  /** 密码提交加载状态 */
  _passwordSubmitLoading: boolean = false;

  /** 取消查询参数 */
  private _cancelQueryParamsFn = () => { };
  /** 取消提交用户 */
  private _cancelSubmitUserFn = () => { };
  /** 取消提交密码 */
  private _cancelSubmitPasswordFn = () => { };

  constructor(
    private _router: Router,
    private _activatedRoute: ActivatedRoute,
    private _formBuilder: FormBuilder,
    private _nzNotificationService: NzNotificationService,
    private _ngCortexService: NgCortexService) { }

  /** 初始化后 */
  ngOnInit(): void {
    const route = this._router.url.replace(/\?.*$/, '');
    const queryParamsSubscription = this._activatedRoute.queryParams.subscribe(queryParams => {
      const showContent = queryParams.showContent;
      if (this._contentList.includes(showContent)) {
        this._showContent = showContent;
      }
      this._router.navigateByUrl(route);
    });
    this._cancelQueryParamsFn = () => {
      queryParamsSubscription.unsubscribe();
      this._cancelQueryParamsFn = () => { };
    };
    this._userForm = this._formBuilder.group({
      account: [null],
      name: [null, [Validators.required, Validators.maxLength(30)]],
      mobileNumber: [null, [Validators.maxLength(20)]],
      email: [null, [Validators.maxLength(50), Validators.email]]
    });
    const { passport } = this._ngCortexService.data;
    const userFormPatch = { ...passport! };
    this._userForm.patchValue(userFormPatch);
    const { account } = this._userForm.controls;
    account.disable();
    if (userFormPatch.avatar) {
      this._avatars = [{ url: userFormPatch.avatar }];
    }
    this._passwordForm = this._formBuilder.group({
      currentPassword: [null, [Validators.required]],
      newPassword: [null, [Validators.required, Validators.minLength(6), Validators.maxLength(16)]],
      confirmPassword: [null, [Validators.required, this._checkConfirmPassword()]]
    });
    const { newPassword, confirmPassword } = this._passwordForm.controls;
    newPassword.valueChanges.subscribe(() => {
      confirmPassword.updateValueAndValidity();
    });
  }

  /** 注销后 */
  ngOnDestroy(): void {
    this._cancelQueryParamsFn();
    this._cancelSubmitUserFn();
    this._cancelSubmitPasswordFn();
  }

  /**
   * 添加头像
   * @param file 文件
   */
  _addAvatar = (file: NzUploadFile, fileList: NzUploadFile[]) => {
    const fileReader = new FileReader();
    fileReader.onload = () => this._avatars = [{ url: fileReader.result }];
    fileReader.readAsDataURL(file as any);
    return false;
  }

  /** 移除头像 */
  _removeAvatar = () => {
    this._avatars = [];
    return true;
  }

  /** 提交用户 */
  _submitUser(): void {
    this._userSubmitLoading = true;
    const completeSubmitUserFn = () => {
      this._cancelSubmitUserFn = () => { };
      this._userSubmitLoading = false;
    };
    const submitUserSubscription = validateForm(this._userForm)
      .pipe(mergeMap(valid => {
        if (valid) {
          const userUpdate = this._getUserUpdate();
          if (userUpdate) {
            return this._ngCortexService.updataPassport(userUpdate);
          }
        }
        return of(null);
      }))
      .pipe(tap(() => {
        this._nzNotificationService.success('更新用户成功', null!);
      }))
      .pipe(catchError((httpErrorResponse: HttpErrorResponse) => {
        this._nzNotificationService.error('更新用户失败', httpErrorResponse.error && httpErrorResponse.error.message || httpErrorResponse.statusText);
        return of(null);
      }))
      .subscribe(() => {
        completeSubmitUserFn();
      });
    this._cancelSubmitUserFn = () => {
      submitUserSubscription.unsubscribe();
      completeSubmitUserFn();
    };
  }

  /** 提交密码 */
  _submitPassword(): void {
    this._passwordSubmitLoading = true;
    const completeSubmitPasswordFn = () => {
      this._cancelSubmitPasswordFn = () => { };
      this._passwordSubmitLoading = false;
      this._passwordForm.reset();
    };
    const submitPasswordSubscription = validateForm(this._passwordForm)
      .pipe(mergeMap(valid => {
        if (valid) {
          const passwordUpdate = this._getPasswordUpdate();
          if (passwordUpdate) {
            return this._ngCortexService.changePassword(passwordUpdate);
          }
        }
        return of(null);
      }))
      .pipe(tap(() => {
        this._nzNotificationService.success('更新密码成功', null!);
      }))
      .pipe(catchError((httpErrorResponse: HttpErrorResponse) => {
        this._nzNotificationService.error('更新密码失败', httpErrorResponse.error && httpErrorResponse.error.message || httpErrorResponse.statusText);
        return of(null);
      }))
      .subscribe(() => {
        completeSubmitPasswordFn();
      });
    this._cancelSubmitPasswordFn = () => {
      submitPasswordSubscription.unsubscribe();
      completeSubmitPasswordFn();
    };
  }

  /** 获取用户更新 */
  private _getUserUpdate(): any {
    let update = { ...this._userForm.getRawValue() };
    if (this._avatars.length === 1) {
      update.avatar = this._avatars[0].url;
    }
    const { passport } = this._ngCortexService.data;
    update = getEntityUpdate(update, passport);
    return update ? { ...passport, ...update } : null;
  }

  /** 检查确认密码 */
  private _checkConfirmPassword(): ValidatorFn {
    return contorl => {
      const form = contorl.parent as FormGroup;
      if (form) {
        const { newPassword } = form.controls;
        if (contorl.value !== newPassword.value) {
          return { confirm: '两次输入不一致' };
        }
      }
      return null;
    };
  }

  /** 获取密码更新 */
  private _getPasswordUpdate(): any {
    const update = { ...this._passwordForm.getRawValue() };
    delete update.confirmPassword;
    return update;
  }

}
