import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { NgCortexService } from '@ng-cortex/core';
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-dict-item-editor',
  templateUrl: './nc-dict-item-editor.component.html',
  styleUrls: ['./nc-dict-item-editor.component.scss']
})
export class NcDictItemEditorComponent implements OnInit, OnDestroy {

  /** 字典项目 */
  @Input() dictItem: any = null;

  /** 字典项目表单 */
  _dictItemForm!: FormGroup;

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

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

  /** 初始化后 */
  ngOnInit(): void {
    const { passport } = this._ngCortexService.data;
    this._dictItemForm = this._formBuilder.group({
      dictId: [null],
      label: [null, [Validators.required, Validators.maxLength(30)]],
      value: [null, [Validators.required, Validators.maxLength(30)]],
      sequence: [null, [Validators.required]],
      companyId: [null]
    });
    const dictItemFormPatch = {
      companyId: passport!.companyId,
      ...this.dictItem
    };
    this._dictItemForm.patchValue(dictItemFormPatch);
  }

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

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

  /** 获取字典项目更新 */
  private _getDictItemUpdate(): any {
    let update = { ...this._dictItemForm.getRawValue() };
    for (const key in update) {
      if (!isValid(update[key])) {
        update[key] = null;
      }
    }
    update = getEntityUpdate(update, this.dictItem) && { ...this.dictItem, ...update };
    if (update) {
      update.companyId = this._ngCortexService.data.passport!.companyId;
    }
    return update;
  }

  /**
   * 提交字典项目
   * @param update 更新
   */
  private _submitDictItem(update: any): Observable<any> {
    const url = '@<%= getSeparatorCase(serviceName) %>/api/dict-items';
    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);
        }));
    }
  }

}
