import {
  Component,
  EventEmitter,
  Input,
  Output,
  SimpleChanges,
  TemplateRef,
  ViewChild,
  ViewContainerRef,
} from '@angular/core';
import { AbstractControl, NonNullableFormBuilder, Validators } from '@angular/forms';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalService } from 'ng-zorro-antd/modal';
import { NzUploadFile } from 'ng-zorro-antd/upload';
import { CommonNzModule } from '../../../../../common.nz.module';
import { ApiService } from '../../../../../services/api.service';
import { BasicDataService } from '../../../../../services/basic.service';
import { KnowledgeService } from '../../../../../services/knowledge.service';
import { SettingService } from '../../../../../services/setting.service';
import {
  ComposePositionPickModalComponent,
  ComposePositionPickModalData,
  getPositionLikeDtoText,
  isPositionLikeValid,
  PositionLike,
} from '../../../../../shared/compose-position-pick-modal/compose-position-pick-modal.component';
import { ImageUploadGroupComponent } from '../../../../../shared/image-upload-group/image-upload-group.component';
import { RiskItemDetailComponent } from '../../../risk/risk-bank/risk-item-detail/risk-item-detail.component';
import { hazardLevelOptions, hazardTypeOptions } from '../../hazard.utils';

export interface HazardFormComponentProps {
  data?: Hazard.HazardDto;
  visible: boolean;
  isEdit: boolean;
}

@Component({
  selector: 'hazard-form',
  standalone: true,
  imports: [CommonNzModule, ImageUploadGroupComponent, RiskItemDetailComponent],
  templateUrl: './hazard-form.component.html',
  styleUrl: './hazard-form.component.less',
  host: {
    class: 'custom-scroll-bar',
  },
})
export class HazardFormComponent {
  @ViewChild('detailTpl') detailTpl!: TemplateRef<void>;
  @ViewChild('imageUploadGroup') imageUploadGroup!: ImageUploadGroupComponent;
  @Input() data?: Partial<Hazard.HazardDto>;
  @Input() isEdit = false;
  @Input() fromInspectionPlan = false;
  @Input() riskItemIds: number[] = [];
  @Output() onClose = new EventEmitter<void>();
  @Output() fetch = new EventEmitter<void>();
  @Output() popupValue = new EventEmitter<Partial<Hazard.HazardDto>>();
  @Output() update = new EventEmitter<number>();

  validateForm = this.fb.group({
    title: this.fb.control<string>('', [Validators.required, Validators.maxLength(100)]),
    level: this.fb.control<string>('', [Validators.required]),
    type: this.fb.control<string>('', [Validators.required]),
    riskType: this.fb.control<number | undefined>(undefined, [Validators.required]),
    riskCategory: this.fb.control<number | undefined>(undefined, [Validators.required]),
    riskItem: this.fb.control<number>(0, [Validators.required]),
    content: this.fb.control<string>('', [Validators.required, Validators.maxLength(1500)]),
    // position: this.fb.control<number[]>([], [Validators.required]),
    // spot: this.fb.control<string>('', []),
    operation: this.fb.control<number | undefined>(undefined, []),
    equipment: this.fb.control<number | undefined>(undefined, []),
    department: this.fb.control<number | undefined>(undefined, [Validators.required]),
    responsible: this.fb.control<string>('', []),
    images: this.fb.control<string[]>([]),
    // position like dto fields
    position: this.fb.control<number | undefined>(undefined, [this.involvedValidator.bind(this)]),
    positionNext: this.fb.control<number | undefined>(undefined, []),
    positionOther: this.fb.control<string | undefined>(undefined, []),
    positionType: this.fb.control<string | undefined>(undefined, []),
    line: this.fb.control<number | undefined>(undefined, []),
  });
  levels: Option[] = hazardLevelOptions.slice();
  types: Option[] = hazardTypeOptions.slice();
  categories: Option[] = [];
  departments: BasicData.Department[] = [];
  uploading = false;
  fileList: NzUploadFile[] = [
    // {
    //   uid: '15',
    //   name: '现场照片',
    //   status: 'done',
    //   url: 'https://precaution-check2.stage.leadinvr.com/api/uploadFile/get?name=tZuzRmxRvku74ccb898b08bdcbe77a050b20863d1cc6.jpg',
    //   preview:
    //     'https://precaution-check2.stage.leadinvr.com/api/uploadFile/get?name=tZuzRmxRvku74ccb898b08bdcbe77a050b20863d1cc6.jpg',
    // },
  ];
  positionText = '';
  constructor(
    private viewContainerRef: ViewContainerRef,
    private modal: NzModalService,
    private fb: NonNullableFormBuilder,
    private message: NzMessageService,
    private setting: SettingService,
    private api: ApiService,
    private knowledge: KnowledgeService,
    private basic: BasicDataService
  ) {
    setting.getUsersOfCurrentCompany();
  }
  setPositionText() {
    this.positionText = getPositionLikeDtoText(
      this.validateForm.value as PositionLike,
      this.basic.lines,
      this.basic.positions,
      this.basic.positionCategories
    );
  }
  ngOnChanges(changes: SimpleChanges) {
    if (changes['data']) {
      this.validateForm.patchValue({
        title: this.data?.title,
        level: this.data?.level,
        type: this.data?.type,
        riskType: this.data?.riskType,
        riskCategory: this.data?.riskCategory,
        riskItem: this.data?.riskPoint,
        content: this.data?.content,
        // position: this.data?.position || [],
        // spot: this.data?.troublePosition,
        operation: this.data?.operation,
        equipment: this.data?.equipment,
        department: this.data?.toDepartment,
        responsible: this.data?.toUserId,
        images: this.data?.images || [],
        // position like dto fields
        position: this.data?.position,
        positionNext: this.data?.positionNext,
        positionOther: this.data?.positionOther,
        positionType: this.data?.positionType,
        line: this.data?.line,
      });
      if (this.data?.images) {
        this.fileList = this.data.images.map(url => ({
          uid: url,
          name: '现场照片',
          status: 'done',
          url,
        }));
      }
      if (this.fromInspectionPlan) {
        this.setPositionText();
        this.validateForm.get('position')?.updateValueAndValidity();
      }
    }
  }
  involvedValidator(control: AbstractControl) {
    if (!this.validateForm) {
      return null;
    }
    const operation = this.validateForm.get('operation')?.value;
    const equipment = this.validateForm.get('equipment')?.value;
    const positionLikeValid = isPositionLikeValid(this.validateForm.value as PositionLike);
    if (!positionLikeValid && !operation && !equipment) {
      return { involved: true, error: true, required: true };
    }
    return null;
  }
  reset() {
    this.validateForm.reset();
    Object.values(this.validateForm.controls).forEach(control => {
      control.markAsPending();
      control.markAsPristine();
      control.markAsUntouched();
    });
    this.fileList = [];
    this.uploading = false;
  }
  onCancel() {
    this.onClose.emit();
  }
  onInvolvedChange() {
    this.validateForm.get('position')?.updateValueAndValidity();
    this.validateForm.get('operation')?.updateValueAndValidity();
    this.validateForm.get('equipment')?.updateValueAndValidity();
  }

  createPositionModal(data?: ComposePositionPickModalData) {
    this.modal.create<ComposePositionPickModalComponent, ComposePositionPickModalData>({
      nzTitle: '选择地点',
      nzClassName: 'precaution-modal',
      nzContent: ComposePositionPickModalComponent,
      nzMaskClosable: false,
      nzData: {
        position: data?.position,
        positionNext: data?.positionNext,
        positionOther: data?.positionOther,
        positionType: data?.positionType,
        line: data?.line,
      },
      nzOnOk: async instance => {
        const data = await instance.validate();
        this.validateForm.patchValue({
          position: data.position,
          positionNext: data.positionNext,
          positionOther: data.positionOther,
          positionType: data.positionType,
          line: data.line,
        });
        this.setPositionText();
        this.validateForm.get('position')?.updateValueAndValidity();
      },
    });
  }

  changeLevel(level: string) {
    if (level === 'A') {
      // TODO
    }
  }
  selectRiskItem(ev: Event) {
    ev.preventDefault();
    this.modal.create<TemplateRef<void>, {}>({
      nzContent: this.detailTpl,
      nzViewContainerRef: this.viewContainerRef,
      nzClassName: 'noop-modal',
      nzClosable: true,
      nzData: {},
      nzWidth: 'calc(100vw - 144px)',
      nzFooter: null,
    });
  }
  async submitForm() {
    if (!this.validateForm.valid) {
      Object.values(this.validateForm.controls).forEach(control => {
        if (control.invalid) {
          control.markAsDirty();
          control.updateValueAndValidity({ onlySelf: true });
        }
      });
    } else {
      if (this.fromInspectionPlan) {
        this.popupValue.emit(this.getValues());
        this.onClose.emit();
        return;
      }
      if (this.isEdit) {
        this.onUpdate();
      } else {
        this.onSubmit();
      }
    }
  }
  getValues(): Partial<Hazard.HazardDto> {
    const {
      title,
      level,
      type,
      riskType,
      riskCategory,
      riskItem: riskPoint,
      content,
      // spot: troublePosition,
      operation,
      equipment,
      department: toDepartment,
      responsible: toUserId,
      // position like dto fields
      position,
      positionNext,
      positionOther,
      positionType,
      line,
    } = this.validateForm.value;
    const result: Partial<Hazard.HazardDto> = {
      company: this.setting.userCompany,
      title,
      level,
      type,
      riskType,
      riskCategory,
      riskPoint,
      content,
      // troublePosition,
      operation,
      equipment,
      toDepartment,
      toUserId,
      // position like dto fields
      position,
      positionNext,
      positionOther,
      positionType,
      line,
    };
    if (toUserId) {
      result.toUserName = this.setting.usersOfCurrentCompany.find(u => u.id === toUserId)?.name || '';
    }
    if (this.imageUrls.length) {
      result.images = this.imageUrls;
    }
    return result;
  }
  async onSubmit() {
    await this.api.hazard.createHazard(this.getValues()).then(res => {
      if (!res.code) {
        this.message.success('新增隐患成功');
        this.onClose.emit();
        this.fetch.emit();
      } else {
        this.message.error('新增隐患失败:' + res.message);
      }
    });
  }
  async onUpdate() {
    await this.api.hazard
      .updateHazard({
        ...this.getValues(),
        id: this.data?.id,
      })
      .then(res => {
        if (!res.code) {
          this.message.success('编辑隐患成功');
          this.onClose.emit();
          this.update.emit(this.data?.id);
        } else {
          this.message.error('编辑隐患失败:' + res.message);
        }
      });
  }
  changeRiskType(t: number) {
    // const { riskType } = this.validateForm.value;
    this.validateForm.get('riskCategory')?.reset();
    this.validateForm.get('department')?.reset();
    this.validateForm.get('responsible')?.reset();
    if (!this.fromInspectionPlan) {
      this.validateForm.get('riskItem')?.reset();
    }
    if (t) {
      this.categories = this.knowledge.getCategoryOptionsByType(t);
    } else {
      this.categories = [];
    }
  }
  onDepartmentChange() {
    this.validateForm.get('responsible')?.reset();
  }
  changeRiskCategory(category: number) {
    this.validateForm.get('department')?.reset();
    this.validateForm.get('responsible')?.reset();
    this.departments = this.knowledge.getDepartmentOptionsByCategory(category);
    if (!this.fromInspectionPlan) {
      this.validateForm.get('riskItem')?.reset();
    }
  }
  handleSelectRiskItem(id: number) {
    this.validateForm.get('riskItem')?.setValue(id);
    if (this.fromInspectionPlan) {
      this.validateForm.get('riskType')?.setValue(this.selectRiskItemDto?.type);
      this.validateForm.get('riskCategory')?.setValue(this.selectRiskItemDto?.category);
    }
  }
  editPosition() {
    this.createPositionModal(this.validateForm.value);
  }
  get positions() {
    return this.basic.positions;
  }
  get operations() {
    return this.basic.operations;
  }
  get equipments() {
    return this.basic.equipments;
  }
  get users() {
    const { department } = this.validateForm.value;
    if (!department) return [];
    return this.setting.usersOfCurrentCompany.filter(u => u.department === department);
  }
  get imageUrls(): string[] {
    return this.imageUploadGroup.urls;
  }
  get riskTypes() {
    return this.knowledge.types().map(t => ({ label: t.value, value: t.id }));
  }
  get allRiskItems() {
    return this.knowledge.riskItems();
  }
  get selectRiskItemId() {
    return this.validateForm.get('riskItem')?.value;
  }
  get currentFilteredRiskItems() {
    if (this.fromInspectionPlan) {
      return this.allRiskItems.filter(r => {
        return this.riskItemIds.includes(r.id);
      });
    }
    const { riskType, riskCategory } = this.validateForm.value;
    if (!riskType || !riskCategory) return [];
    return this.allRiskItems.filter(r => {
      return r.category === riskCategory && r.type === riskType;
    });
  }
  get selectRiskItemDto() {
    return this.allRiskItems.find(r => r.id === this.selectRiskItemId);
  }
  get missTypeOrCategory() {
    const { riskType, riskCategory } = this.validateForm.value;
    return !riskType || !riskCategory;
  }
  get selectRiskItemDisabled() {
    if (this.fromInspectionPlan) {
      return false;
    }
    return this.missTypeOrCategory;
  }
  get departmentOptionIsNone() {
    return this.departments.length === 0;
  }
}
