import { ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, Output, SimpleChanges, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Idp } from 'src/app/shared/model/competency.model';
import { CompetencycourseMiniModel, MyCompetencycourseMiniModel } from 'src/app/shared/model/competencycourse-mini.model';
import { IdpFormModel } from 'src/app/shared/model/idp-form.model';
import { CompetencycourseService } from 'src/app/shared/services/competencycourse.service';
import { EmployeeService } from 'src/app/shared/services/employee.service';
import { EvaluationIdpService } from 'src/app/shared/services/evaluation-Idp.service';

interface table {
  currentPage: number,
  page: number[],
  search: string,
  pageSize: number
}
@Component({
  selector: 'app-pms-idp',
  templateUrl: './pms-idp.component.html',
  styleUrls: ['./pms-idp.component.scss']
})
export class PmsIdpComponent {
  @Input() complete = false
  @Input() canSave = false
  @Input() pathTitle: string[] = []
  @Input() evaluationRoundId = ""
  @Input() evaluateeId = ""
  @Input() evaluaterId = ""
  @Output() sendReturnPath: EventEmitter<any> = new EventEmitter<any>();
  currentDate = new Date()
  hoveredCode: string | null = null;
  @Input() appraisalIdp?: Idp
  originalformIdp?: IdpFormModel
  @Input() canEdit = false
  @Input() dateIso = ""
  @Input() currentStep = ""
  @Input() currentTap = ""
  @Output() idpForm: EventEmitter<any> = new EventEmitter<any>();
  @Input() pdfPrint = false;
  @Output() pdfPrinted = new EventEmitter<void>();
  pdfPrintCheck: 0 | 1 = 0
  @ViewChild('pdfArea') pdfArea!: ElementRef<HTMLElement>;

  competencycourse: { loading: boolean, data: CompetencycourseMiniModel[] } = { loading: false, data: [] }
  competencycourseTable: table = {
    currentPage: 1,
    page: Array.from({ length: 1 }, (_, i) => i + 1),
    search: "",
    pageSize: 10
  }
  competencycourseIndex = -1
  pdfLoading = true
  @ViewChild("competencycourseModal") competencycourseModal: any;
  dialogRefCompetencycourseModal: any
  constructor(private evaluationIdpService: EvaluationIdpService,
    private employeeService: EmployeeService,
    private competencycourseService: CompetencycourseService,
    private cdr: ChangeDetectorRef,
    private dialog: MatDialog
  ) {
  }
  ngOnInit(): void {
    this.getFormIdp()
    this.getCompetencycourseMiniList()
  }
  ngOnChanges(changes: SimpleChanges): void {
    if (changes['currentTap']?.currentValue || changes['appraisalIdp']?.currentValue) {
      this.getFormIdp()
    }
  }
  getCompetencycourseMiniList() {
    this.competencycourse.loading = false
    this.competencycourseService.getMiniList().subscribe({
      next: response => {
        this.competencycourse.data = response.map(x => new MyCompetencycourseMiniModel(x))
        this.competencycourse.loading = false
        this.cdr.detectChanges()
      }, error: error => {
        this.competencycourse.loading = false
        this.cdr.detectChanges()
      }
    })
  }
  openCompetencycourseDialog(index: number) {
    this.competencycourseIndex = index
    this.dialogRefCompetencycourseModal = this.dialog.open(this.competencycourseModal, {
      width: '800px',
    })
  }
  closeCompetencycourseDialog() {
    this.dialogRefCompetencycourseModal.close()
  }

  addCompetencycourse(data: CompetencycourseMiniModel) {
    if (this.appraisalIdp) {
      if (this.appraisalIdp.competencyIndicatorsCourses1[this.competencycourseIndex].competencyCourse) {
        this.appraisalIdp.competencyIndicatorsCourses1[this.competencycourseIndex].competencyCourse.push(new MyCompetencycourseMiniModel(data))
      } else {
        this.appraisalIdp.competencyIndicatorsCourses1[this.competencycourseIndex]['competencyCourse'] = [new MyCompetencycourseMiniModel(data)]
      }
      this.cdr.detectChanges()
    }
  }

  deleteCompetencyCourse(index: number, removeIndex: number) {
    if (this.appraisalIdp) {
      this.appraisalIdp.competencyIndicatorsCourses1[index].competencyCourse.splice(removeIndex, 1)
    }
  }
  onCompetencycourseSearch() {
    this.competencycourseTable.currentPage = 1
    this.competencycourseTable.page = Array.from({ length: Math.ceil(this.filterCompetencycourse().length / 10) }, (_, i) => i + 1);
  }
  filterCompetencycourse() {
    return this.competencycourse.data.filter(x => x.competencyCourseId.toLowerCase().includes(this.competencycourseTable.search.toLowerCase()) ||
      x.tdesc.toLowerCase().includes(this.competencycourseTable.search.toLowerCase()) ||
      x.edesc.toLowerCase().includes(this.competencycourseTable.search.toLowerCase()))
  }
  resetFormIdp() {
    if (this.originalformIdp && this.appraisalIdp) {
      this.appraisalIdp.competencyIndicatorsCourses1 = JSON.parse(JSON.stringify(this.originalformIdp.competencyIndicatorsCourses1))
    }
  }
  getFormIdp() {
    if (this.appraisalIdp) {
      switch (this.currentStep) {
        case ("0"): {
          this.appraisalIdp.masfromEvaluationIdp.apsassessyDate = this.dateIso
          break
        }
        case ("1"): {
          this.appraisalIdp.masfromEvaluationIdp.apsapprove1Date = this.dateIso
          break
        }
        case ("2"): {
          this.appraisalIdp.masfromEvaluationIdp.apsapprove2Date = this.dateIso
          break
        }
        case ("3"): {
          this.appraisalIdp.masfromEvaluationIdp.apsapprove3Date = this.dateIso
          break
        }
        case ("4"): {
          this.appraisalIdp.masfromEvaluationIdp.apsapprove4Date = this.dateIso
          break
        }
        case ("5"): {
          this.appraisalIdp.masfromEvaluationIdp.apsapprove5Date = this.dateIso
          break
        }
        default: { return }
      }
      this.appraisalIdp.masfromEvaluationIdp.idpStatus = this.appraisalIdp.masfromEvaluationIdp.idpStatus ? this.appraisalIdp.masfromEvaluationIdp.idpStatus : '0'
      this.cdr.detectChanges()
    }
  }
  returnPath() {
    this.sendReturnPath.emit()
  }
  convertDate(dateInput?: string | Date): string {
    let date = new Date()
    if (dateInput) {
      if (typeof dateInput === 'string') {
        const [year, month, day] = dateInput.split('-').map(Number);
        date = new Date(year, month - 1, day);
      } else {
        date = dateInput
      }
    }
    return date?.toLocaleDateString('th-TH', { day: 'numeric', month: 'long', year: 'numeric' }) || ''
  }
  convertDateFormat(dateString: string): string {
    const [year, month, day] = dateString.split("-");
    return `${day}-${month}-${year}`;
  }


  sendForm() {
    this.idpForm.emit(this.appraisalIdp)
  }

  print() {
    window.print();
  }

  /** ล็อคความกว้างเทียบ A4 (≈794px @96dpi) ให้ layout เสถียรตอนแคปเจอร์ */
  private freezeWidthForA4(el: HTMLElement) {
    const prev = {
      width: el.style.width,
      maxWidth: el.style.maxWidth,
      transform: el.style.transform,
      transformOrigin: el.style.transformOrigin,
    };
    el.style.width = '794px';
    el.style.maxWidth = '794px';
    el.style.transformOrigin = 'top left';
    el.style.transform = 'scale(1)';

    return () => {
      el.style.width = prev.width;
      el.style.maxWidth = prev.maxWidth;
      el.style.transform = prev.transform;
      el.style.transformOrigin = prev.transformOrigin;
    };
  }

  /** ขยายเป็นความกว้างจริง (scrollWidth) แล้วสเกลลงให้พอดี A4 */
  private expandToFullWidthThenScale(el: HTMLElement) {
    const A4_PX = 794; // ≈ 210mm @ 96dpi
    const full = el.scrollWidth;               // ความกว้างจริงทั้งหมด (รวมพื้นที่ต้องเลื่อนขวา)
    const scale = Math.min(1, A4_PX / full);   // สเกลลงให้พอดี A4 (ถ้ากว้างกว่า)

    // เก็บค่าเดิมไว้คืนทีหลัง
    const prev = {
      width: el.style.width,
      maxWidth: el.style.maxWidth,
      overflowX: el.style.overflowX,
      transform: el.style.transform,
      transformOrigin: el.style.transformOrigin,
    };

    // คลี่ความกว้างออกทั้งหมด แล้วสเกลให้พอดี A4
    el.style.width = `${full}px`;
    el.style.maxWidth = 'none';
    el.style.overflowX = 'visible';
    el.style.transformOrigin = 'top left';
    el.style.transform = `scale(${scale})`;

    // คืนค่า
    return () => {
      el.style.width = prev.width;
      el.style.maxWidth = prev.maxWidth;
      el.style.overflowX = prev.overflowX;
      el.style.transform = prev.transform;
      el.style.transformOrigin = prev.transformOrigin;
    };
  }

  /** ทำให้ทุกกล่องใน subtree ไม่ตัดขอบขวา: overflowX => visible, ยกเลิก position:sticky ชั่วคราว */
  private unclipOverflows(el: HTMLElement) {
    const patched: Array<{ node: HTMLElement, prev: Partial<CSSStyleDeclaration> }> = [];
    const walker = document.createTreeWalker(el, NodeFilter.SHOW_ELEMENT);

    const patchNode = (node: HTMLElement) => {
      const style = window.getComputedStyle(node);
      const needOverflowPatch = style.overflowX !== 'visible' || style.overflow !== 'visible';
      const isSticky = style.position === 'sticky';

      if (needOverflowPatch || isSticky) {
        const prev = {
          overflow: node.style.overflow,
          overflowX: node.style.overflowX,
          overflowY: node.style.overflowY,
          position: node.style.position,
          clipPath: (node.style as any).clipPath,
        };
        patched.push({ node, prev });

        node.style.overflow = 'visible';
        node.style.overflowX = 'visible';
        node.style.overflowY = 'visible';
        if (isSticky) node.style.position = 'static';
        (node.style as any).clipPath = 'none';
      }
    };

    // รวม el เองด้วย
    patchNode(el as HTMLElement);
    while (walker.nextNode()) {
      patchNode(walker.currentNode as HTMLElement);
    }

    // ฟังก์ชันคืนค่าเดิม
    return () => {
      for (const { node, prev } of patched) {
        node.style.overflow = prev.overflow || '';
        node.style.overflowX = prev.overflowX || '';
        node.style.overflowY = prev.overflowY || '';
        node.style.position = prev.position || '';
        (node.style as any).clipPath = prev.clipPath || '';
      }
    };
  }


  // @ViewChild('pdfArea') pdfArea!: ElementRef<HTMLElement>;

  // async exportPdf() {
  //   this.pdfPrintCheck = 1
  //   const el = this.pdfArea?.nativeElement;
  //   if (!el) return;

  //   const mod: any = await import('html2pdf.js');
  //   const html2pdf = mod.default ?? mod;

  //   // 1) คลี่กว้างจริงแล้วสเกลลงพอดี A4
  //   const cleanupScale = this.expandToFullWidthThenScale(el);
  //   // 2) ปลดคลิป overflow/sticky ของลูก ๆ ทั้งหมด
  //   const cleanupUnclip = this.unclipOverflows(el);

  //   const prevBodyOverflow = document.body.style.overflow;
  //   document.body.style.overflow = 'hidden';

  //   // ขนาดจริงของ element (หลังถูกขยายแล้ว)
  //   const fullW = el.scrollWidth;
  //   const fullH = el.scrollHeight;
  //   const epsilon = 2; // กันเผื่อ

  //   const opt = {
  //     margin: [10, 10, 10, 10],
  //     filename: `pms-${this.evaluateeId || 'employee'}-${new Date().toISOString().slice(0, 10)}.pdf`,
  //     image: { type: 'jpeg', quality: 0.96 },
  //     html2canvas: {
  //       scale: 2,
  //       useCORS: true,
  //       logging: false,
  //       scrollX: 0,
  //       scrollY: -window.scrollY,
  //       // 👇 บอกขนาดที่จะเรนเดอร์ให้เท่าของจริงทั้งหมด
  //       width: 800,
  //       // height: fullH,
  //       height: Math.max(0, fullH - epsilon),
  //       windowWidth: 800,
  //       // windowHeight: fullH,
  //       windowHeight: Math.max(0, fullH - epsilon),
  //       // foreignObjectRendering: true, // ลองเปิดถ้า layout ยังเพี้ยน (มีข้อจำกัดกับบางเคส)
  //     },
  //     jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
  //     pagebreak: { mode: ['css', 'legacy'], avoid: ['.no-break', 'table', 'img'] },
  //     onclone: (doc:any) => {
  //   doc.querySelectorAll('[data-hide-in-pdf]').forEach((el:any) => el.remove());
  // }
  //   };

  //   try {
  //     await html2pdf().from(el).set(opt).save();
  //   } finally {
  //     cleanupUnclip();
  //     cleanupScale();
  //     document.body.style.overflow = prevBodyOverflow;
  //   }
  //   this.pdfPrintCheck = 0
  // }

  async exportPdf() {
  this.pdfPrintCheck = 1;
  const el = this.pdfArea?.nativeElement;
  if (!el) return;

  // 👉 ลบ shadow ออกจากทุก element ที่มี shadow class
  const shadowEls = el.querySelectorAll('.shadow');
  shadowEls.forEach(e => e.classList.remove('shadow'));

  const mod: any = await import('html2pdf.js');
  const html2pdf = mod.default ?? mod;

  const cleanupScale = this.expandToFullWidthThenScale(el);
  const cleanupUnclip = this.unclipOverflows(el);

  const prevBodyOverflow = document.body.style.overflow;
  document.body.style.overflow = 'hidden';

  const fullW = el.scrollWidth;
  const fullH = el.scrollHeight;
  const epsilon = 2;

  const opt = {
    margin: [10, 10, 10, 10],
    filename: `pms-${this.evaluateeId || 'employee'}-${new Date().toISOString().slice(0, 10)}.pdf`,
    image: { type: 'jpeg', quality: 0.96 },
    html2canvas: {
      scale: 2,
      useCORS: true,
      logging: false,
      scrollX: 0,
      scrollY: -window.scrollY,
      width: 800,
      height: Math.max(0, fullH - epsilon),
      windowWidth: 800,
      windowHeight: Math.max(0, fullH - epsilon),
    },
    jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
    pagebreak: { mode: ['css', 'legacy'], avoid: ['.no-break', 'table', 'img'] },
    onclone: (doc: any) => {
      doc.querySelectorAll('[data-hide-in-pdf]').forEach((el: any) => el.remove());
    },
  };

  try {
    await html2pdf().from(el).set(opt).save();
  } finally {
    cleanupUnclip();
    cleanupScale();
    document.body.style.overflow = prevBodyOverflow;

    // 👉 คืน class shadow กลับ
    shadowEls.forEach(e => e.classList.add('shadow'));
  }

  this.pdfPrintCheck = 0;
}



}
