import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { getEntityUpdate, isValid, validateForm, Validators } from '@ng-cortex/utils';
import { NzNotificationService } from 'ng-zorro-antd/notification';
import { Observable, of } from 'rxjs';
import { catchError, map, mergeMap, tap } from 'rxjs/operators';

/** 公司编辑器组件 */
@Component({
  selector: 'nc-company-editor',
  templateUrl: './nc-company-editor.component.html',
  styleUrls: ['./nc-company-editor.component.scss']
})
export class NcCompanyEditorComponent implements OnInit, OnDestroy {

  /** 公司 */
  @Input() company: any = null;

  /** 公司表单 */
  _companyForm!: FormGroup;
  /** 密码可见状态 */
  _passwordVisible: boolean = false;
  /** 应用列表 */
  _applicationList: any[] = [];
  /** 应用加载状态 */
  _applicationLoading: boolean = false;
  /** 实体比较 */
  _entityCompareWith = (entityA: any, entityB: any) => (entityA && entityA.id) === (entityB && entityB.id);

  /** 取消提交 */
  private _cancelSubmitFn = () => { };

  constructor(
    private _formBuilder: FormBuilder,
    private _httpClient: HttpClient,
    private _nzNotificationService: NzNotificationService) { }

  /** 初始化后 */
  ngOnInit(): void {
    this._companyForm = this._formBuilder.group({
      name: [null, [Validators.required, Validators.maxLength(50)]],
      alias: [null, [Validators.required, Validators.maxLength(20)]],
      enabled: [null, [Validators.required]],
      logoPath: [null, [Validators.maxLength(200)]],
      tags: [null, [Validators.maxLength(200)]],
      applications: [null]
    });
    const companyFormPatch = {
      enabled: true,
      ...this.company
    };
    if (companyFormPatch.tags) {
      companyFormPatch.tags = JSON.parse(companyFormPatch.tags);
    }
    if (!companyFormPatch.id) {
      const extendGroup: any = {
        userAccount: [null, [Validators.required, Validators.maxLength(30)]],
        userPassword: [null, [Validators.required, Validators.maxLength(20)]],
        userName: [null, [Validators.required, Validators.maxLength(30)]],
        userMobileNumber: [null, [Validators.required, Validators.maxLength(20)]]
      };
      for (const name in extendGroup) {
        this._companyForm.addControl(name, new FormControl(...extendGroup[name]));
      }
    }
    this._companyForm.patchValue(companyFormPatch);
    this._getApplicationList();
  }

  /** 注销后 */
  ngOnDestroy(): void {
    this._cancelSubmitFn();
  }

  /** 提交 */
  submit(): Observable<{ success: boolean; updated: any }> {
    return new Observable(subscriber => {
      const submitResult = {
        success: false,
        updated: null
      };
      const submitSubscription = validateForm(this._companyForm)
        .pipe(mergeMap(valid => {
          if (valid) {
            const companyUpdate = this._getCompanyUpdate();
            if (companyUpdate) {
              return this._submitCompany(companyUpdate)
                .pipe(tap(companyUpdated => {
                  submitResult.success = true;
                  submitResult.updated = companyUpdated;
                }));
            } else {
              submitResult.success = true;
            }
          }
          return of(null);
        }))
        .pipe(catchError(() => of(null)))
        .pipe(map(() => submitResult))
        .subscribe(subscriber);
      this._cancelSubmitFn = () => {
        submitSubscription.unsubscribe();
      };
    });
  }

  /** 获取应用列表 */
  private _getApplicationList(): void {
    this._applicationLoading = true;
    const url = '@<%= getSeparatorCase(serviceName) %>/api/applications';
    this._httpClient.get<any[]>(url)
      .pipe(catchError((httpErrorResponse: HttpErrorResponse) => {
        this._nzNotificationService.error('获取应用列表失败', httpErrorResponse.error && httpErrorResponse.error.message || httpErrorResponse.statusText);
        return of([]);
      }))
      .subscribe(applicationList => {
        this._applicationList = applicationList.sort((application1, application2) => application1.sequence - application2.sequence);
        this._applicationLoading = false;
      });
  }

  /** 获取公司更新 */
  private _getCompanyUpdate(): any {
    const update = { ...this._companyForm.getRawValue() };
    for (const key in update) {
      if (!isValid(update[key])) {
        update[key] = null;
      }
    }
    if (update.tags) {
      update.tags = JSON.stringify(update.tags);
    }
    return getEntityUpdate(update, this.company) && { ...this.company, ...update };
  }

  /**
   * 提交公司
   * @param update 更新
   */
  private _submitCompany(update: any): Observable<any> {
    const url = '@<%= getSeparatorCase(serviceName) %>/api/companies';
    const body = update;
    if (body.id) {
      return this._httpClient.put(url, body).pipe(tap(
        () => {
          this._nzNotificationService.success('更新公司成功', null!);
        },
        (httpErrorResponse: HttpErrorResponse) => {
          this._nzNotificationService.success('更新公司失败', httpErrorResponse.error && httpErrorResponse.error.message || httpErrorResponse.statusText);
        }));
    } else {
      return this._httpClient.post(url, body).pipe(tap(
        () => {
          this._nzNotificationService.success('新增公司成功', null!);
        },
        (httpErrorResponse: HttpErrorResponse) => {
          this._nzNotificationService.success('新增公司失败', httpErrorResponse.error && httpErrorResponse.error.message || httpErrorResponse.statusText);
        }));
    }
  }

}
