"use client";

/**
 * 수입검사 성적서 문서 컴포넌트 (동적 버전)
 *
 * - 24종 품목별 검사 템플릿 지원
 * - OK/NG 라디오 버튼 클릭 가능
 * - 종합판정 자동 계산
 * - API 데이터 기반 동적 렌더링
 */

import React, { useState, useCallback, useMemo, forwardRef, useImperativeHandle } from 'react';

// ============================================
// 타입 정의
// ============================================

/** 검사 항목 타입 - MNG와 동일 */
export type MeasurementType = 'okng' | 'numeric' | 'both' | 'single_value' | 'substitute';
export type JudgmentResult = 'OK' | 'NG' | null;

/** 검사기준 옵션 (선택형 기준용) */
export interface StandardOption {
  id: string;
  label: string;           // "0.8 이상 ~ 1.0 미만"
  tolerance: string;       // "± 0.07"
  isSelected: boolean;     // 현재 선택된 옵션인지
}

/** 검사 항목 템플릿 */
export interface InspectionItemTemplate {
  id: string;                    // "appearance", "thickness" 등
  no: number;                    // 1, 2, 3...
  name: string;                  // "겉모양", "치수" 등
  subName?: string;              // "두께", "너비", "길이" (하위 항목)
  parentId?: string;             // 상위 항목 ID (그룹핑용)

  // 검사 기준
  standard: {
    description?: string;        // "사용상 해로운 결함이 없을 것" (검사기준 전체)
    value?: string | number;     // 기준값
    tolerance?: string;          // 허용치 문자열 (예: "±0.07")
    options?: StandardOption[];  // 선택형 기준 (두께 범위 등)
  };

  inspectionMethod: string;      // "육안검사", "계측", "n=3 c=0" 등
  inspectionCycle: string;       // "체크검사", "입고시" 등

  // 측정 설정
  measurementType: MeasurementType;
  measurementCount: number;      // 측정 횟수 (1, 3 등)

  // 3단계 그룹핑 (category → item → 옵션)
  // 1차 그룹 (category) rowspan - NO, 카테고리명 컬럼용
  categoryRowSpan?: number;
  isFirstInCategory?: boolean;
  // 2차 그룹 (item) rowspan - 검사항목(세부), 검사방식, 검사주기, 측정치, 판정 컬럼용
  itemRowSpan?: number;
  isFirstInItem?: boolean;

  // rowSpan 설정 (복잡한 레이아웃용 - 기존 호환)
  rowSpan?: number;
  isSubRow?: boolean;            // 하위 행인지
}

/** 검사 항목 입력값 */
export interface InspectionItemValue {
  itemId: string;
  measurements: (number | 'OK' | 'NG' | null)[];
  result: JudgmentResult;
}

/** 수입검사 템플릿 데이터 (API 응답) */
export interface ImportInspectionTemplate {
  templateId: string;
  templateName: string;

  // 기본 정보
  headerInfo: {
    productName: string;
    specification: string;
    materialNo: string;
    lotSize: number;
    supplier: string;
    lotNo: string;
    inspectionDate: string;
    inspector: string;
    reportDate: string;
    approvers: {
      writer?: string;
      reviewer?: string;
      approver?: string;
    };
    // 결재선 원본 데이터 (동적 UI 표시용)
    approvalLines?: Array<{
      id: number;
      name: string;
      dept: string;
      role: string;
      sortOrder: number;
    }>;
  };

  // 검사 항목 배열
  inspectionItems: InspectionItemTemplate[];

  // 주석/비고
  notes?: string[];
}

/** ref를 통한 데이터 접근 인터페이스 */
export interface ImportInspectionRef {
  getInspectionData: () => unknown;
}

/** 컴포넌트 Props */
export interface ImportInspectionDocumentProps {
  template?: ImportInspectionTemplate;
  initialValues?: InspectionItemValue[];
  onValuesChange?: (values: InspectionItemValue[], overallResult: '합격' | '불합격') => void;
  readOnly?: boolean;
  /** 검사자(작성자) 부서명 - 결재라인 첫 번째 항목에 표시 */
  inspectorDept?: string;
}

// ============================================
// Mock 템플릿 데이터 (EGI 강판)
// ============================================

export const MOCK_EGI_TEMPLATE: ImportInspectionTemplate = {
  templateId: 'EGI-001',
  templateName: '전기 아연도금 강판',

  headerInfo: {
    productName: '전기 아연도금 강판 (KS D 3528, SECC) "EGI 평국판"',
    specification: '1.55 * 1218 × 480',
    materialNo: 'PE02RB',
    lotSize: 200,
    supplier: '지오TNS (KG스틸)',
    lotNo: '250715-02',
    inspectionDate: '07/15',
    inspector: '노원호',
    reportDate: '2025-07-15',
    approvers: {
      writer: '노원호',
      reviewer: '',
      approver: '',
    },
  },

  inspectionItems: [
    // 1. 겉모양
    {
      id: 'appearance',
      no: 1,
      name: '겉모양',
      standard: {
        description: '사용상 해로운 결함이 없을 것',
      },
      inspectionMethod: '육안검사',
      inspectionCycle: '',
      measurementType: 'okng',
      measurementCount: 3,
    },
    // 2. 치수 - 두께 (두께+너비+길이 = 3행)
    {
      id: 'thickness',
      no: 2,
      name: '치수',
      subName: '두께',
      standard: {
        value: 1.55,
        options: [
          { id: 't1', label: '0.8 이상 ~ 1.0 미만', tolerance: '± 0.07', isSelected: false },
          { id: 't2', label: '1.0 이상 ~ 1.25 미만', tolerance: '± 0.08', isSelected: false },
          { id: 't3', label: '1.25 이상 ~ 1.6 미만', tolerance: '± 0.10', isSelected: true },
          { id: 't4', label: '1.6 이상 ~ 2.0 미만', tolerance: '± 0.12', isSelected: false },
        ],
      },
      inspectionMethod: 'n = 3\nc = 0',
      inspectionCycle: '체크검사',
      measurementType: 'numeric',
      measurementCount: 3,
      rowSpan: 3,
    },
    // 2. 치수 - 너비
    {
      id: 'width',
      no: 2,
      name: '치수',
      subName: '너비',
      parentId: 'thickness',
      standard: {
        value: 1219,
        options: [
          { id: 'w1', label: '1250 미만', tolerance: '+ 7\n- 0', isSelected: true },
        ],
      },
      inspectionMethod: '',
      inspectionCycle: '',
      measurementType: 'numeric',
      measurementCount: 3,
      isSubRow: true,
    },
    // 2. 치수 - 길이
    {
      id: 'length',
      no: 2,
      name: '치수',
      subName: '길이',
      parentId: 'thickness',
      standard: {
        value: 480,
        options: [
          { id: 'l1', label: '2000 이상 ~ 4000 미만', tolerance: '+ 15\n- 0', isSelected: true },
        ],
      },
      inspectionMethod: '',
      inspectionCycle: '',
      measurementType: 'numeric',
      measurementCount: 3,
      isSubRow: true,
    },
    // 3. 인장강도
    {
      id: 'tensileStrength',
      no: 3,
      name: '인장강도 (N/㎟)',
      standard: {
        description: '270 이상',
      },
      inspectionMethod: '',
      inspectionCycle: '',
      measurementType: 'numeric',
      measurementCount: 1,
    },
    // 4. 연신율 (옵션은 한 셀 안에서 세로로 표시)
    {
      id: 'elongation',
      no: 4,
      name: '연신율 %',
      standard: {
        options: [
          { id: 'e1', label: '두께 0.6 이상 ~ 1.0 미만', tolerance: '36 이상', isSelected: false },
          { id: 'e2', label: '두께 1.0 이상 ~ 1.6 미만', tolerance: '37 이상', isSelected: true },
          { id: 'e3', label: '두께 1.6 이상 ~ 2.3 미만', tolerance: '38 이상', isSelected: false },
        ],
      },
      inspectionMethod: '공급업체\n밀시트',
      inspectionCycle: '입고시',
      measurementType: 'numeric',
      measurementCount: 1,
    },
    // 5. 아연 부착량
    {
      id: 'zincCoating',
      no: 5,
      name: '아연의 최소 부착량 (g/㎡)',
      standard: {
        description: '편면 17 이상',
      },
      inspectionMethod: '',
      inspectionCycle: '',
      measurementType: 'numeric',
      measurementCount: 2,
    },
  ],

  notes: [
    '※ 1.55mm의 경우 KS F 4510에 따른 MIN 1.5의 기준에 따름',
    '※ 두께의 경우 너비 1000 이상 ~ 1250 미만 기준에 따름',
  ],
};

// ============================================
// 유틸리티 함수
// ============================================

/**
 * 허용오차 문자열을 파싱하여 min/max 범위 반환
 * 예: "± 0.07" → { plusTolerance: 0.07, minusTolerance: 0.07 }
 * 예: "+ 7\n- 0" → { plusTolerance: 7, minusTolerance: 0 }
 * 예: "36 이상" → { minValue: 36 }
 * 예: "편면 17 이상" → { minValue: 17 }
 */
const parseTolerance = (tolerance: string): { plusTolerance?: number; minusTolerance?: number; minValue?: number; maxValue?: number } => {
  // "± X" 형식
  const plusMinusMatch = tolerance.match(/±\s*([\d.]+)/);
  if (plusMinusMatch) {
    const val = parseFloat(plusMinusMatch[1]);
    return { plusTolerance: val, minusTolerance: val };
  }

  // "+ X\n- Y" 또는 "+X -Y" 형식
  const separateMatch = tolerance.match(/\+\s*([\d.]+)[\s\n]*-\s*([\d.]+)/);
  if (separateMatch) {
    return {
      plusTolerance: parseFloat(separateMatch[1]),
      minusTolerance: parseFloat(separateMatch[2]),
    };
  }

  // "X 이상" 형식
  const minMatch = tolerance.match(/([\d.]+)\s*이상/);
  if (minMatch) {
    return { minValue: parseFloat(minMatch[1]) };
  }

  // "X 이하" 형식
  const maxMatch = tolerance.match(/([\d.]+)\s*이하/);
  if (maxMatch) {
    return { maxValue: parseFloat(maxMatch[1]) };
  }

  return {};
};

/**
 * 측정값이 검사기준 범위 내인지 확인
 */
const isValueInRange = (
  measuredValue: number,
  baseValue: number | undefined,
  tolerance: { plusTolerance?: number; minusTolerance?: number; minValue?: number; maxValue?: number }
): boolean => {
  // "X 이상" 기준
  if (tolerance.minValue !== undefined) {
    return measuredValue >= tolerance.minValue;
  }

  // "X 이하" 기준
  if (tolerance.maxValue !== undefined) {
    return measuredValue <= tolerance.maxValue;
  }

  // 기준값 ± 허용오차 기준
  if (baseValue !== undefined && tolerance.plusTolerance !== undefined && tolerance.minusTolerance !== undefined) {
    const min = baseValue - tolerance.minusTolerance;
    const max = baseValue + tolerance.plusTolerance;
    return measuredValue >= min && measuredValue <= max;
  }

  // 기준을 파싱할 수 없으면 통과로 처리
  return true;
};

// ============================================
// 컴포넌트
// ============================================

export const ImportInspectionDocument = forwardRef<ImportInspectionRef, ImportInspectionDocumentProps>(function ImportInspectionDocument({
  template = MOCK_EGI_TEMPLATE,
  initialValues,
  onValuesChange,
  readOnly = false,
  inspectorDept,
}, ref) {
  // 검사 항목별 입력값 상태
  const [values, setValues] = useState<Record<string, InspectionItemValue>>(() => {
    const initial: Record<string, InspectionItemValue> = {};

    template.inspectionItems.forEach((item) => {
      const existingValue = initialValues?.find((v) => v.itemId === item.id);
      initial[item.id] = existingValue || {
        itemId: item.id,
        measurements: Array(item.measurementCount).fill(null),
        result: null,
      };
    });

    return initial;
  });

  // 검사 항목의 기준값과 허용오차를 기반으로 자동 판정 계산
  const calculateAutoResult = useCallback((
    item: InspectionItemTemplate,
    measurements: (number | 'OK' | 'NG' | null)[]
  ): JudgmentResult => {
    // OK/NG 타입은 수동 판정 (자동 계산 안함)
    if (item.measurementType === 'okng') {
      // 모든 측정값이 OK면 OK, 하나라도 NG면 NG
      const validMeasurements = measurements.filter((m) => m === 'OK' || m === 'NG');
      if (validMeasurements.length === 0) return null;
      if (validMeasurements.some((m) => m === 'NG')) return 'NG';
      if (validMeasurements.length === item.measurementCount && validMeasurements.every((m) => m === 'OK')) return 'OK';
      return null;
    }

    // numeric 타입: 측정값이 기준 범위 내인지 확인
    const numericMeasurements = measurements.filter((m): m is number => typeof m === 'number');

    // 아직 측정값이 하나도 없으면 null
    if (numericMeasurements.length === 0) return null;

    // 기준값
    const baseValue = typeof item.standard.value === 'number' ? item.standard.value : undefined;

    // 선택된 옵션의 허용오차 가져오기
    const selectedOption = item.standard.options?.find((opt) => opt.isSelected);

    // description에서 기준 파싱 (예: "270 이상", "편면 17 이상")
    let tolerance: ReturnType<typeof parseTolerance> = {};

    if (selectedOption?.tolerance) {
      tolerance = parseTolerance(selectedOption.tolerance);
    } else if (item.standard.description) {
      tolerance = parseTolerance(item.standard.description);
    }

    // 모든 측정값이 범위 내인지 확인
    const allInRange = numericMeasurements.every((val) =>
      isValueInRange(val, baseValue, tolerance)
    );

    // 모든 측정값이 입력되었고 모두 범위 내면 OK
    if (numericMeasurements.length === item.measurementCount && allInRange) {
      return 'OK';
    }

    // 범위 밖 값이 있으면 NG
    if (!allInRange) {
      return 'NG';
    }

    // 아직 모든 값이 입력되지 않음
    return null;
  }, []);

  // 종합판정 계산 (하위 항목은 제외하고 계산)
  const overallResult = useMemo(() => {
    // 판정이 필요한 항목만 필터링 (isSubRow가 아니고 parentId가 없는 항목)
    const mainItems = template.inspectionItems.filter(
      (item) => !item.isSubRow && !item.parentId
    );
    const mainResults = mainItems.map((item) => values[item.id]?.result);

    // 하나라도 NG면 불합격, 모두 OK면 합격, 미입력 있으면 null
    if (mainResults.some((r) => r === 'NG')) return '불합격';
    if (mainResults.every((r) => r === 'OK')) return '합격';
    return null;
  }, [values, template.inspectionItems]);

  // ref를 통한 데이터 접근
  useImperativeHandle(ref, () => ({
    getInspectionData: () => ({
      templateId: template.templateId,
      values: Object.values(values),
      overallResult,
    }),
  }), [template.templateId, values, overallResult]);

  // 날짜 포맷
  const fullDate = new Date().toLocaleDateString('ko-KR', {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  });

  // OK/NG 선택 핸들러
  const _handleResultChange = useCallback((itemId: string, result: JudgmentResult) => {
    if (readOnly) return;

    setValues((prev) => {
      const newValues = {
        ...prev,
        [itemId]: {
          ...prev[itemId],
          result,
        },
      };

      // 콜백 호출
      if (onValuesChange) {
        const valueArray = Object.values(newValues);
        const allResults = valueArray.map((v) => v.result);
        const calculatedResult = allResults.some((r) => r === 'NG')
          ? '불합격'
          : allResults.every((r) => r === 'OK')
            ? '합격'
            : '불합격';
        onValuesChange(valueArray, calculatedResult);
      }

      return newValues;
    });
  }, [readOnly, onValuesChange]);

  // 측정값 변경 핸들러 (자동 판정 포함)
  const handleMeasurementChange = useCallback((
    itemId: string,
    index: number,
    value: number | 'OK' | 'NG' | null
  ) => {
    if (readOnly) return;

    // 해당 항목의 템플릿 정보 가져오기
    const item = template.inspectionItems.find((i) => i.id === itemId);
    if (!item) return;

    setValues((prev) => {
      const newMeasurements = [...prev[itemId].measurements];
      newMeasurements[index] = value;

      // 자동 판정 계산
      const autoResult = calculateAutoResult(item, newMeasurements);

      const newValues = {
        ...prev,
        [itemId]: {
          ...prev[itemId],
          measurements: newMeasurements,
          result: autoResult, // 자동 판정 결과 적용
        },
      };

      // 콜백 호출
      if (onValuesChange) {
        const valueArray = Object.values(newValues);
        const allResults = valueArray.map((v) => v.result);
        const calculatedResult = allResults.some((r) => r === 'NG')
          ? '불합격'
          : allResults.every((r) => r === 'OK')
            ? '합격'
            : '불합격';
        onValuesChange(valueArray, calculatedResult);
      }

      return newValues;
    });
  }, [readOnly, template.inspectionItems, calculateAutoResult, onValuesChange]);

  // OK/NG 라디오 버튼 렌더링 (PDF 출력 호환)
  const renderOkNgRadio = (itemId: string, measurementIndex?: number) => {
    const itemValue = values[itemId];

    // 측정값용 (n1, n2, n3)
    if (measurementIndex !== undefined) {
      const currentValue = itemValue.measurements[measurementIndex];
      return (
        <div className="flex items-center justify-center gap-1">
          <button
            type="button"
            onClick={() => !readOnly && handleMeasurementChange(itemId, measurementIndex, 'OK')}
            disabled={readOnly}
            className={`flex items-center gap-0.5 px-1 py-0.5 rounded text-xs transition-colors ${
              currentValue === 'OK'
                ? 'bg-blue-100 text-blue-700 font-bold border border-blue-400'
                : 'hover:bg-gray-100'
            } ${readOnly ? 'cursor-not-allowed' : 'cursor-pointer'}`}
          >
            <span className="w-3 h-3 border border-gray-400 rounded-full flex items-center justify-center text-[8px] print:border-black">
              {currentValue === 'OK' && <span className="w-2 h-2 bg-blue-600 rounded-full print:bg-black" />}
            </span>
            <span>OK</span>
          </button>
          <button
            type="button"
            onClick={() => !readOnly && handleMeasurementChange(itemId, measurementIndex, 'NG')}
            disabled={readOnly}
            className={`flex items-center gap-0.5 px-1 py-0.5 rounded text-xs transition-colors ${
              currentValue === 'NG'
                ? 'bg-red-100 text-red-700 font-bold border border-red-400'
                : 'hover:bg-gray-100'
            } ${readOnly ? 'cursor-not-allowed' : 'cursor-pointer'}`}
          >
            <span className="w-3 h-3 border border-gray-400 rounded-full flex items-center justify-center text-[8px] print:border-black">
              {currentValue === 'NG' && <span className="w-2 h-2 bg-red-600 rounded-full print:bg-black" />}
            </span>
            <span>NG</span>
          </button>
        </div>
      );
    }

    // 판정용 - 자동 계산 결과 표시 (선택 버튼 없음)
    const currentResult = itemValue.result;
    return (
      <div className="flex flex-col items-center justify-center">
        {currentResult === 'OK' && (
          <span className="text-blue-700 font-bold text-sm">적</span>
        )}
        {currentResult === 'NG' && (
          <span className="text-red-700 font-bold text-sm">부</span>
        )}
        {currentResult === null && (
          <span className="text-gray-400 text-xs">-</span>
        )}
      </div>
    );
  };

  // 측정값 입력 필드 렌더링
  const renderMeasurementInput = (itemId: string, index: number) => {
    const itemValue = values[itemId];
    const currentValue = itemValue.measurements[index];

    return (
      <input
        type="number"
        value={currentValue !== null && typeof currentValue === 'number' ? currentValue : ''}
        onChange={(e) => {
          const val = e.target.value ? parseFloat(e.target.value) : null;
          handleMeasurementChange(itemId, index, val);
        }}
        disabled={readOnly}
        className="w-full text-center border-0 bg-transparent focus:outline-none focus:ring-1 focus:ring-blue-500 rounded text-xs"
        placeholder="-"
      />
    );
  };

  // 검사기준 옵션 렌더링 (PDF 출력 호환 - 특수문자 사용 안함)
  const renderStandardOptions = (options: StandardOption[]) => {
    return options.map((opt) => (
      <div
        key={opt.id}
        className={`flex items-center gap-1 px-1 py-0.5 text-xs ${
          opt.isSelected ? 'bg-blue-50 font-medium print:bg-gray-200' : ''
        }`}
      >
        {/* PDF 호환 체크박스: 테두리 박스 + V 텍스트 */}
        <span
          className={`w-3.5 h-3.5 border flex items-center justify-center text-[9px] font-bold flex-shrink-0 ${
            opt.isSelected
              ? 'border-blue-600 bg-blue-100 text-blue-700 print:border-black print:bg-gray-300 print:text-black'
              : 'border-gray-400 bg-white'
          }`}
          style={{ lineHeight: 1 }}
        >
          {opt.isSelected ? 'V' : ''}
        </span>
        <span className="whitespace-nowrap">{opt.label}</span>
        <span className="ml-auto whitespace-nowrap">{opt.tolerance.replace(/\n/g, ' ')}</span>
      </div>
    ));
  };

  const { headerInfo, inspectionItems, notes } = template;

  // 결재선 동적 생성 (API에서 제공하는 결재선 사용, 없으면 기본값)
  const approvalLines = useMemo(() => {
    if (headerInfo.approvalLines && headerInfo.approvalLines.length > 0) {
      return headerInfo.approvalLines;
    }
    // 기본 결재선 (작성, 검토, 승인, 승인)
    return [
      { id: 1, name: '작성', dept: '', role: '작성', sortOrder: 1 },
      { id: 2, name: '검토', dept: '', role: '검토', sortOrder: 2 },
      { id: 3, name: '승인', dept: '', role: '승인', sortOrder: 3 },
      { id: 4, name: '승인', dept: '', role: '승인', sortOrder: 4 },
    ];
  }, [headerInfo.approvalLines]);

  return (
    <div className="bg-white p-8 w-full text-sm shadow-sm print:shadow-none">
      {/* 문서 헤더 (중간검사 성적서 스타일) */}
      <div className="flex justify-between items-start mb-6">
        <div>
          <h1 className="text-2xl font-bold">수입검사 성적서</h1>
          <p className="text-xs text-gray-500 mt-1 whitespace-nowrap">
            문서번호: {headerInfo.lotNo || template.templateId} | 작성일자: {fullDate}
          </p>
        </div>

        {/* 결재란 - 동적 렌더링 */}
        <table className="border-collapse text-sm flex-shrink-0">
          <tbody>
            <tr>
              <td className="border border-gray-400 px-4 py-1 text-center align-middle" rowSpan={3}>결<br/>재</td>
              {approvalLines.map((line) => (
                <td key={`role-${line.id}`} className="border border-gray-400 px-6 py-1 text-center">
                  {line.name || line.role}
                </td>
              ))}
            </tr>
            <tr>
              {approvalLines.map((line, idx) => (
                <td key={`name-${line.id}`} className="border border-gray-400 px-6 py-3 text-center">
                  {/* 첫 번째(작성자)는 검사자 이름, 나머지는 결재 대기 */}
                  {idx === 0 && headerInfo.inspector ? (
                    <span>{headerInfo.inspector}</span>
                  ) : (
                    <span className="text-gray-400">이름</span>
                  )}
                </td>
              ))}
            </tr>
            <tr>
              {approvalLines.map((line, idx) => (
                <td key={`dept-${line.id}`} className="border border-gray-400 px-6 py-1 text-center whitespace-nowrap">
                  {/* 첫 번째(작성자/검사자)는 로그인 사용자 부서 우선, 나머지는 템플릿 부서 */}
                  {(idx === 0 && inspectorDept) ? inspectorDept : (line.dept || <span className="text-gray-400">부서명</span>)}
                </td>
              ))}
            </tr>
          </tbody>
        </table>
      </div>

      {/* 기본 정보 테이블 - 15:35:15:35 비율 (4컬럼) */}
      <table className="w-full border-collapse mb-4 text-xs">
        <colgroup>
          <col style={{ width: '15%' }} />
          <col style={{ width: '35%' }} />
          <col style={{ width: '15%' }} />
          <col style={{ width: '35%' }} />
        </colgroup>
        <tbody>
          <tr>
            <td className="border border-gray-400 px-3 py-2 bg-gray-100 font-medium text-center">품 명</td>
            <td className="border border-gray-400 px-3 py-2">{headerInfo.productName}</td>
            <td className="border border-gray-400 px-3 py-2 bg-gray-100 font-medium text-center">납품업체<br/>(제조업체)</td>
            <td className="border border-gray-400 px-3 py-2">{headerInfo.supplier}</td>
          </tr>
          <tr>
            <td className="border border-gray-400 px-3 py-2 bg-gray-100 font-medium text-center">규 격<br/>(두께*너비*길이)</td>
            <td className="border border-gray-400 px-3 py-2">{headerInfo.specification}</td>
            <td className="border border-gray-400 px-3 py-2 bg-gray-100 font-medium text-center">로트번호</td>
            <td className="border border-gray-400 px-3 py-2">{headerInfo.lotNo}</td>
          </tr>
          <tr>
            <td className="border border-gray-400 px-3 py-2 bg-gray-100 font-medium text-center">자재번호</td>
            <td className="border border-gray-400 px-3 py-2">{headerInfo.materialNo}</td>
            <td className="border border-gray-400 px-3 py-2 bg-gray-100 font-medium text-center">검사일자</td>
            <td className="border border-gray-400 px-3 py-2">{headerInfo.inspectionDate}</td>
          </tr>
          <tr>
            <td className="border border-gray-400 px-3 py-2 bg-gray-100 font-medium text-center">로트크기</td>
            <td className="border border-gray-400 px-3 py-2">{headerInfo.lotSize} 매</td>
            <td className="border border-gray-400 px-3 py-2 bg-gray-100 font-medium text-center">검사자</td>
            <td className="border border-gray-400 px-3 py-2">
              {headerInfo.inspector}
              <span className="inline-flex items-center justify-center w-4 h-4 border border-gray-600 text-[10px] font-bold ml-2">V</span>
            </td>
          </tr>
        </tbody>
      </table>

      {/* 검사 항목 테이블 - MNG와 동일한 구조 */}
      <table className="w-full border-collapse text-xs">
{/* NO, 카테고리, 항목, 기준, 허용치, 검사방식, 검사주기, n1, n2, n3, 판정 */}
        <colgroup>
          <col style={{ width: '4%' }} />
          <col style={{ width: '8%' }} />
          <col style={{ width: '8%' }} />
          <col style={{ width: '15%' }} />
          <col style={{ width: '10%' }} />
          <col style={{ width: '10%' }} />
          <col style={{ width: '10%' }} />
          <col style={{ width: '9%' }} />
          <col style={{ width: '9%' }} />
          <col style={{ width: '9%' }} />
          <col style={{ width: '8%' }} />
        </colgroup>
        <thead>
          <tr className="bg-gray-100">
            <th className="border border-gray-400 px-2 py-2 text-center" rowSpan={2}>NO</th>
            <th className="border border-gray-400 px-2 py-2 text-center" colSpan={2}>검사항목</th>
            <th className="border border-gray-400 px-2 py-2 text-center" colSpan={2}>검사기준</th>
            <th className="border border-gray-400 px-2 py-2 text-center" rowSpan={2}>검사방식</th>
            <th className="border border-gray-400 px-2 py-2 text-center" rowSpan={2}>검사주기</th>
            <th className="border border-gray-400 px-2 py-2 text-center" colSpan={3}>측정값</th>
            <th className="border border-gray-400 px-2 py-2 text-center" rowSpan={2}>판정<br/>(적/부)</th>
          </tr>
          <tr className="bg-gray-100">
            <th className="border border-gray-400 px-2 py-1 text-center">항목</th>
            <th className="border border-gray-400 px-2 py-1 text-center">세부항목</th>
            <th className="border border-gray-400 px-2 py-1 text-center">기준</th>
            <th className="border border-gray-400 px-2 py-1 text-center">허용치</th>
            <th className="border border-gray-400 px-2 py-1 text-center">n1</th>
            <th className="border border-gray-400 px-2 py-1 text-center">n2</th>
            <th className="border border-gray-400 px-2 py-1 text-center">n3</th>
          </tr>
        </thead>
        <tbody>
          {inspectionItems.map((item, _idx) => {
            const _itemValue = values[item.id];

            // 그룹핑 정보
            const hasCategory = !!item.subName;
            const categoryRowSpan = item.categoryRowSpan || 1;
            const itemRowSpan = item.itemRowSpan || 1;
            const isFirstInCategory = item.isFirstInCategory ?? true;
            const isFirstInItem = item.isFirstInItem ?? true;
            // 그룹 항목인지 (category가 있거나, 같은 item 이름이 여러 개)
            const isGroupItem = hasCategory || itemRowSpan > 1 || !isFirstInItem;

            return (
              <tr key={item.id}>
                {/* NO - 카테고리/그룹 첫 행에만 렌더링 */}
                {isFirstInCategory && (
                  <td
                    className="border border-gray-400 px-2 py-2 text-center align-middle font-medium"
                    rowSpan={categoryRowSpan}
                  >
                    {item.no}
                  </td>
                )}

                {/* 검사항목 */}
                {hasCategory ? (
                  // category가 있는 그룹 항목: 카테고리(categoryRowSpan) + 세부항목(itemRowSpan)
                  <>
                    {/* 카테고리명 (치수) - 카테고리 첫 행에만 */}
                    {isFirstInCategory && (
                      <td
                        className="border border-gray-400 px-2 py-2 text-center align-middle font-medium"
                        rowSpan={categoryRowSpan}
                      >
                        <span className="whitespace-pre-line">{item.name}</span>
                      </td>
                    )}
                    {/* 세부항목 (두께/너비/길이) - item 첫 행에만 */}
                    {isFirstInItem && (
                      <td
                        className="border border-gray-400 px-2 py-1 text-center align-middle font-medium"
                        rowSpan={itemRowSpan}
                      >
                        <span className="whitespace-pre-line">{item.subName}</span>
                      </td>
                    )}
                  </>
                ) : isGroupItem ? (
                  // category 없는 그룹 항목 (연신율 등): 항목명만 rowspan으로
                  isFirstInCategory && (
                    <td
                      className="border border-gray-400 px-2 py-2 text-center align-middle font-medium"
                      colSpan={2}
                      rowSpan={categoryRowSpan}
                    >
                      <span className="whitespace-pre-line">{item.name}</span>
                    </td>
                  )
                ) : (
                  // 단독 항목: colspan="2"로 항목명만 표시
                  <td
                    className="border border-gray-400 px-2 py-2 text-center align-middle font-medium"
                    colSpan={2}
                  >
                    <span className="whitespace-pre-line">{item.name}</span>
                  </td>
                )}

                {/* 검사기준 - 모든 행에 표시 (rowspan 없음) */}
                {hasCategory ? (
                  // 그룹 항목: 기준 + 허용치 각각 별도 셀
                  <>
                    <td className="border border-gray-400 px-2 py-1 text-center align-middle">
                      {item.standard.options ? (
                        <div className="text-xs">{renderStandardOptions(item.standard.options)}</div>
                      ) : (
                        <span className="whitespace-pre-line text-xs">{item.standard.description || '-'}</span>
                      )}
                    </td>
                    <td className="border border-gray-400 px-2 py-1 text-center align-middle">
                      <span className="text-blue-600 font-medium text-xs">{item.standard.tolerance || '-'}</span>
                    </td>
                  </>
                ) : (
                  // 단일 항목: colspan="2"로 검사기준 전체 표시
                  <td
                    className="border border-gray-400 px-2 py-1 align-middle"
                    colSpan={2}
                  >
                    {item.standard.options ? (
                      <div className="text-xs">{renderStandardOptions(item.standard.options)}</div>
                    ) : (
                      <span className="whitespace-pre-line text-xs">{item.standard.description || '-'}</span>
                    )}
                  </td>
                )}

                {/* 검사방식 - item 첫 행에만 렌더링 (itemRowSpan) */}
                {(isGroupItem ? isFirstInItem : true) && (
                  <td
                    className="border border-gray-400 px-2 py-1 text-center align-middle whitespace-pre-line"
                    rowSpan={isGroupItem ? itemRowSpan : 1}
                  >
                    {item.inspectionMethod}
                  </td>
                )}

                {/* 검사주기 - item 첫 행에만 렌더링 (itemRowSpan) */}
                {(isGroupItem ? isFirstInItem : true) && (
                  <td
                    className="border border-gray-400 px-2 py-1 text-center align-middle"
                    rowSpan={isGroupItem ? itemRowSpan : 1}
                  >
                    {item.inspectionCycle}
                  </td>
                )}

                {/* 측정값 - item 첫 행에만 렌더링 (itemRowSpan), n=3이면 3개 열 */}
                {(isGroupItem ? isFirstInItem : true) ? (
                  item.measurementType === 'substitute' ? (
                    // 성적서로 대체 (밀시트 등)
                    <td
                      className="border border-gray-400 px-2 py-1 text-center align-middle text-gray-500"
                      colSpan={3}
                      rowSpan={isGroupItem ? itemRowSpan : 1}
                      style={{ fontSize: '10px' }}
                    >
                      성적서로 대체
                    </td>
                  ) : item.measurementType === 'single_value' ? (
                    // 단일 입력 (colspan으로 합침) - 저장된 값이 있으면 표시
                    <td
                      className="border border-gray-400 px-2 py-1 text-center align-middle"
                      colSpan={3}
                      rowSpan={isGroupItem ? itemRowSpan : 1}
                    >
                      {renderMeasurementInput(item.id, 0)}
                    </td>
                  ) : item.measurementType === 'okng' ? (
                    // OK/NG 선택형 - n 값에 따라 열 개수 결정
                    <>
                      {Array.from({ length: 3 }).map((_, i) => (
                        <td
                          key={i}
                          className="border border-gray-400 px-1 py-1 text-center align-middle"
                          rowSpan={isGroupItem ? itemRowSpan : 1}
                        >
                          {i < item.measurementCount ? renderOkNgRadio(item.id, i) : ''}
                        </td>
                      ))}
                    </>
                  ) : item.measurementCount === 1 ? (
                    // 단일 측정값 (3칸 합치기)
                    <td
                      className="border border-gray-400 px-2 py-1 text-center align-middle"
                      colSpan={3}
                      rowSpan={isGroupItem ? itemRowSpan : 1}
                    >
                      {renderMeasurementInput(item.id, 0)}
                    </td>
                  ) : item.measurementCount === 2 ? (
                    // 2개 측정값
                    <>
                      <td
                        className="border border-gray-400 px-2 py-1 text-center align-middle"
                        rowSpan={isGroupItem ? itemRowSpan : 1}
                      >
                        {renderMeasurementInput(item.id, 0)}
                      </td>
                      <td
                        className="border border-gray-400 px-2 py-1 text-center align-middle"
                        colSpan={2}
                        rowSpan={isGroupItem ? itemRowSpan : 1}
                      >
                        {renderMeasurementInput(item.id, 1)}
                      </td>
                    </>
                  ) : (
                    // 3개 측정값 (n=3)
                    <>
                      {Array.from({ length: 3 }).map((_, i) => (
                        <td
                          key={i}
                          className="border border-gray-400 px-2 py-1 text-center align-middle"
                          rowSpan={isGroupItem ? itemRowSpan : 1}
                        >
                          {renderMeasurementInput(item.id, i)}
                        </td>
                      ))}
                    </>
                  )
                ) : null}

                {/* 판정 - item 첫 행에만 렌더링 (itemRowSpan) */}
                {(isGroupItem ? isFirstInItem : true) && (
                  <td
                    className="border border-gray-400 px-2 py-1 text-center align-middle"
                    rowSpan={isGroupItem ? itemRowSpan : 1}
                  >
                    {renderOkNgRadio(item.id)}
                  </td>
                )}
              </tr>
            );
          })}
        </tbody>
      </table>

      {/* 주석 */}
      {notes && notes.length > 0 && (
        <div className="mt-2 text-xs text-gray-600">
          {notes.map((note, idx) => (
            <p key={idx}>{note}</p>
          ))}
        </div>
      )}
      {/* 비고 입력란 */}
      <div className="mt-4 border border-gray-400">
        <div className="flex">
          <div className="bg-gray-100 px-4 py-2 font-medium text-xs border-r border-gray-400 flex items-center w-20">
            비 고
          </div>
          <div className="flex-1 p-2">
            <textarea
              className="w-full min-h-[60px] text-xs border-0 bg-transparent focus:outline-none focus:ring-1 focus:ring-blue-500 rounded resize-none"
              placeholder="검사 관련 특이사항을 입력하세요."
              disabled={readOnly}
            />
          </div>
        </div>
      </div>

      {/* 종합판정 */}
      <div className="mt-4 flex justify-end">
        <div className="border border-gray-400">
          <div className="bg-gray-100 px-4 py-1 text-center text-xs font-medium border-b border-gray-400">종합판정</div>
          <div className={`px-8 py-2 text-center text-sm font-bold whitespace-nowrap ${
            overallResult === '합격' ? 'text-blue-600' :
            overallResult === '불합격' ? 'text-red-600' :
            'text-gray-400'
          }`}>
            {overallResult === '합격' && '합격 (PASS)'}
            {overallResult === '불합격' && '불합격 (FAIL)'}
            {overallResult === null && '미완료'}
          </div>
        </div>
      </div>
    </div>
  );
});
