// ============================================================
// E2E 테스트 데이터 설정
// 견적 → 수주 → 생산지시 → 작업지시(공정별) → 중간검사(PQC) → 포장 → 출하
// 50건의 전체 프로세스 테스트 데이터
// ============================================================
// 채번규칙 적용:
// - 견적번호: KD-PR-YYMMDD-##
// - 수주번호(스크린): KD-TS-YYMMDD-##
// - 수주번호(슬랫): KD-SL-YYMMDD-##
// - 수주번호(절곡): KD-BD-YYMMDD-##
// - 작업지시번호: KD-WO-YYMMDD-##
// - 출하번호: KD-SH-YYMMDD-##
// - 발주번호: KD-SO-YYMMDD-##
// - 생산LOT: KD-PL-YYMMDD-##
// - 현장코드: PJ-YYMMDD-##
// ============================================================

import processMasterConfig from './processMasterConfig';

// ============ 채번 유틸리티 함수 ============
// 날짜를 YYMMDD 형식으로 변환
const formatDateCode = (date) => {
  const d = date instanceof Date ? date : new Date(date);
  const yy = String(d.getFullYear()).slice(-2);
  const mm = String(d.getMonth() + 1).padStart(2, '0');
  const dd = String(d.getDate()).padStart(2, '0');
  return `${yy}${mm}${dd}`;
};

// 채번 생성 함수
const generateDocNo = (prefix, date, seq) => {
  const dateCode = formatDateCode(date);
  return `${prefix}-${dateCode}-${String(seq).padStart(2, '0')}`;
};

// 제품 유형별 수주번호 접두사 결정
const getOrderPrefix = (productType) => {
  if (productType?.includes('스크린') || productType === '스크린') return 'KD-TS';
  if (productType?.includes('슬랫') || productType === '슬랫') return 'KD-SL';
  if (productType?.includes('절곡') || productType === '절곡') return 'KD-BD';
  return 'KD-TS'; // 기본값
};

// ============ 공정-품목 카테고리 매핑 (정합성 개선) ============
// 제품 유형에 따라 필요한 공정 결정
export const productProcessMapping = {
  '스크린': {
    primaryProcess: 'SCREEN',
    processCode: 'SCR-001',
    processName: '스크린 생산',
    requiredProcesses: ['SCREEN', 'SLAT', 'FOLD'],  // 스크린 + 슬랫 + 절곡(케이스/가이드)
    description: '스크린셔터 제조 (스크린+슬랫+절곡부품)',
  },
  '철재': {
    primaryProcess: 'SLAT',
    processCode: 'SLT-001',
    processName: '슬랫 생산',
    requiredProcesses: ['SLAT', 'FOLD'],  // 슬랫 + 절곡(케이스/가이드)
    description: '철재셔터 제조 (슬랫+절곡부품)',
  },
};

// BOM 품목 → 공정 매핑 (processMasterConfig.processWorkflows 연계)
export const bomItemProcessMapping = {
  // 스크린 관련 품목 → SCREEN 공정
  'SCR-SCREEN': { processCode: 'SCR-001', workflowCode: 'SCREEN', stepCodes: ['SCR-MAT', 'SCR-CNT', 'SCR-CUT', 'SCR-CHK', 'SCR-SEW', 'SCR-END', 'SCR-QC', 'SCR-PACK'] },

  // 절곡 부품 → FOLD 공정
  'STL-GUIDE': { processCode: 'FLD-001', workflowCode: 'FOLD', stepCodes: ['FLD-CUT', 'FLD-VCUT', 'FLD-BEND', 'FLD-QC', 'FLD-PACK'] },
  'STL-CASE': { processCode: 'FLD-001', workflowCode: 'FOLD', stepCodes: ['FLD-CUT', 'FLD-VCUT', 'FLD-BEND', 'FLD-QC', 'FLD-PACK'] },
  'STL-BRACKET': { processCode: 'FLD-001', workflowCode: 'FOLD', stepCodes: ['FLD-CUT', 'FLD-VCUT', 'FLD-BEND', 'FLD-QC', 'FLD-PACK'] },

  // 샤프트 → STOCK 공정 (재고생산/포밍)
  'STL-SHAFT': { processCode: 'STK-001', workflowCode: 'STOCK', stepCodes: ['STK-FORM', 'STK-QC', 'STK-PACK'] },

  // 슬랫 관련 → SLAT 공정
  'SLT-SLAT': { processCode: 'SLT-001', workflowCode: 'SLAT', stepCodes: ['SLT-CUT', 'SLT-FIN', 'SLT-QC1', 'SLT-PACK'] },

  // 구매품 (공정 불필요 - 자재입고만)
  'MTR-MOTOR': { processCode: null, workflowCode: null, stepCodes: [], isPurchased: true },
  'CTL-CTRL': { processCode: null, workflowCode: null, stepCodes: [], isPurchased: true },
  'INSP-FEE': { processCode: null, workflowCode: null, stepCodes: [], isService: true },
};

// ============ 자재 LOT 마스터 데이터 ============
export const materialLotMaster = {
  // 스크린 원단 LOT
  'SCR-SCREEN': [
    { lotNo: 'LOT-SCR-2025-001', material: '스크린 원단', qty: 1000, unit: 'm²', receivedDate: '2025-01-05', status: '사용중', supplier: '원단공급사A' },
    { lotNo: 'LOT-SCR-2025-002', material: '스크린 원단', qty: 800, unit: 'm²', receivedDate: '2025-01-10', status: '대기', supplier: '원단공급사B' },
    { lotNo: 'LOT-SCR-2025-003', material: '스크린 원단', qty: 1200, unit: 'm²', receivedDate: '2025-01-15', status: '대기', supplier: '원단공급사A' },
  ],
  // 슬랫 코일 LOT
  'SLT-SLAT': [
    { lotNo: 'LOT-SLT-2025-001', material: '슬랫 코일', qty: 5000, unit: 'EA', receivedDate: '2025-01-03', status: '사용중', supplier: '철강사A' },
    { lotNo: 'LOT-SLT-2025-002', material: '슬랫 코일', qty: 3000, unit: 'EA', receivedDate: '2025-01-08', status: '대기', supplier: '철강사B' },
  ],
  // 절곡판/코일 LOT
  'STL-FOLD': [
    { lotNo: 'LOT-FLD-2025-001', material: '절곡판', qty: 500, unit: 'kg', receivedDate: '2025-01-04', status: '사용중', supplier: '철강사A' },
    { lotNo: 'LOT-FLD-2025-002', material: '절곡코일', qty: 800, unit: 'kg', receivedDate: '2025-01-12', status: '대기', supplier: '철강사C' },
  ],
  // 샤프트 자재 LOT
  'STL-SHAFT': [
    { lotNo: 'LOT-SFT-2025-001', material: '샤프트 원자재', qty: 200, unit: 'EA', receivedDate: '2025-01-06', status: '사용중', supplier: '부품사A' },
  ],
};

// ============ 50건 E2E 테스트 데이터 생성 ============
export const generateE2ETestData = (customerMaster, siteMaster) => {
  const testData = {
    quotes: [],           // 견적 50건
    orders: [],           // 수주 50건
    productionOrders: [], // 생산지시 50건
    workOrders: [],       // 작업지시 (공정×단계별)
    workResults: [],      // 작업실적 (신규 추가)
    pqcInspections: [],   // 중간검사 (PQC)
    packaging: [],        // 포장
    shipments: [],        // 출하
    materialLotUsage: [], // 자재 LOT 사용 이력 (신규 추가)
  };

  // 공정 워크플로우 참조
  const workflows = processMasterConfig.processWorkflows;

  const sizeOptions = [
    { W0: 2000, H0: 2500 }, { W0: 2500, H0: 2800 }, { W0: 3000, H0: 3000 },
    { W0: 3500, H0: 3200 }, { W0: 4000, H0: 3500 }, { W0: 4500, H0: 3000 },
    { W0: 5000, H0: 3500 }, { W0: 5500, H0: 4000 }, { W0: 6000, H0: 4000 },
    { W0: 6500, H0: 4500 },
  ];

  const productTypes = ['스크린', '철재'];
  const statusFlow = ['생산완료', '출하중', '출하완료', '완료'];

  for (let i = 0; i < 50; i++) {
    const siteIdx = (i % (siteMaster?.length || 100)) + 1;
    const site = siteMaster?.find(s => s.id === siteIdx) || {
      id: siteIdx,
      code: `S-${String(siteIdx).padStart(3, '0')}`,
      name: `테스트현장${siteIdx}`,
      customerId: (i % 10) + 1,
      customerName: `테스트거래처${(i % 10) + 1}`,
      address: `테스트주소 ${siteIdx}`,
      manager: `현장담당${siteIdx}`,
      tel: '010-0000-0000'
    };

    const customer = customerMaster?.find(c => c.id === site.customerId) || {
      id: site.customerId,
      code: `C-${String(site.customerId).padStart(3, '0')}`,
      name: site.customerName,
      creditGrade: 'A',
      discountRate: 5
    };

    const sizeOpt = sizeOptions[i % sizeOptions.length];
    const qty = (i % 5) + 1;
    const productType = productTypes[i % 2];
    const processMapping = productProcessMapping[productType];
    const baseDate = new Date(2025, 0, 1 + i);
    const orderStatus = statusFlow[i % statusFlow.length];

    // ============ 1. 견적 생성 ============
    const area = (sizeOpt.W0 * sizeOpt.H0) / 1000000;
    const weight = area * 25;
    const basePrice = productType === '스크린' ? 850000 : 750000;
    const totalAmount = Math.round(area * basePrice * qty);

    const quoteId = i + 1;
    // 채번규칙 적용: KD-PR-YYMMDD-##
    const quoteNo = generateDocNo('KD-PR', baseDate, (i % 10) + 1);

    // BOM 품목 생성
    const bomItems = generateBOMItems(productType, sizeOpt, qty);

    testData.quotes.push({
      id: quoteId,
      quoteNo,
      quoteDate: baseDate.toISOString().split('T')[0],
      validUntil: new Date(baseDate.getTime() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
      status: '수주전환',
      customerId: customer.id,
      customerCode: customer.code,
      customerName: customer.name,
      creditGrade: customer.creditGrade,
      siteId: site.id,
      siteCode: site.code,
      siteName: site.name,
      siteAddress: site.address,
      productType,
      width: sizeOpt.W0,
      height: sizeOpt.H0,
      productionSizeW: sizeOpt.W0 + 140,
      productionSizeH: sizeOpt.H0 + 350,
      area: parseFloat(area.toFixed(2)),
      weight: parseFloat(weight.toFixed(1)),
      qty,
      supplyAmount: totalAmount,
      discountRate: customer.discountRate || 0,
      discountAmount: Math.round(totalAmount * (customer.discountRate || 0) / 100),
      finalAmount: totalAmount - Math.round(totalAmount * (customer.discountRate || 0) / 100),
      items: bomItems,
      createdBy: '판매팀',
      createdAt: baseDate.toISOString(),
    });

    // ============ 2. 수주 생성 ============
    const orderDate = new Date(baseDate.getTime() + 5 * 24 * 60 * 60 * 1000);
    const dueDate = new Date(orderDate.getTime() + 45 * 24 * 60 * 60 * 1000);
    const orderId = i + 1;
    // 채번규칙 적용: 스크린=KD-TS, 슬랫=KD-SL, 절곡=KD-BD + YYMMDD-##
    const orderPrefix = getOrderPrefix(productType);
    const orderNo = generateDocNo(orderPrefix, orderDate, (i % 10) + 1);

    testData.orders.push({
      id: orderId,
      orderNo,
      orderDate: orderDate.toISOString().split('T')[0],
      status: orderStatus,
      quoteId,
      quoteNo,
      customerId: customer.id,
      customerCode: customer.code,
      customerName: customer.name,
      siteId: site.id,
      siteCode: site.code,
      siteName: site.name,
      siteAddress: site.address,
      productType,
      width: sizeOpt.W0,
      height: sizeOpt.H0,
      productionSizeW: sizeOpt.W0 + 140,
      productionSizeH: sizeOpt.H0 + 350,
      qty,
      orderAmount: totalAmount,
      dueDate: dueDate.toISOString().split('T')[0],
      items: bomItems,
      requiredProcesses: processMapping.requiredProcesses,
      createdBy: '판매팀',
      createdAt: orderDate.toISOString(),
    });

    // ============ 3. 생산지시 생성 ============
    const poDate = new Date(orderDate.getTime() + 2 * 24 * 60 * 60 * 1000);
    const productionOrderId = i + 1;
    // 채번규칙 적용: KD-PL-YYMMDD-##
    const productionOrderNo = generateDocNo('KD-PL', poDate, (i % 10) + 1);

    // 필요 공정별 그룹화
    const processGroups = groupItemsByProcess(bomItems, processMapping.requiredProcesses);

    testData.productionOrders.push({
      id: productionOrderId,
      productionOrderNo,
      productionOrderDate: poDate.toISOString().split('T')[0],
      status: orderStatus === '완료' ? '생산완료' : '생산중',
      orderId,
      orderNo,
      quoteNo,
      customerId: customer.id,
      customerName: customer.name,
      siteId: site.id,
      siteName: site.name,
      productType,
      qty,
      dueDate: dueDate.toISOString().split('T')[0],
      processGroups,
      totalProcesses: processMapping.requiredProcesses.length,
      completedProcesses: orderStatus === '완료' ? processMapping.requiredProcesses.length :
                          Math.floor(processMapping.requiredProcesses.length / 2),
      createdBy: '생산관리',
      createdAt: poDate.toISOString(),
    });

    // ============ 4. 작업지시 생성 (공정별 세부 단계) ============
    let workOrderSeq = 0;
    processMapping.requiredProcesses.forEach((workflowCode, procIdx) => {
      const workflow = workflows[workflowCode];
      if (!workflow) return;

      const woBaseDate = new Date(poDate.getTime() + procIdx * 3 * 24 * 60 * 60 * 1000);

      // 각 공정의 세부 단계별 작업지시 생성
      workflow.steps.forEach((step, stepIdx) => {
        workOrderSeq++;
        const workOrderId = (i * 20) + workOrderSeq; // 충분한 ID 범위 확보
        // 채번규칙 적용: KD-WO-YYMMDD-## (공정별 순번 포함)
        const woSeqNum = (procIdx * 10) + stepIdx + 1;
        const workOrderNo = generateDocNo('KD-WO', woBaseDate, woSeqNum);

        const stepStartDate = new Date(woBaseDate.getTime() + stepIdx * 0.5 * 24 * 60 * 60 * 1000);
        const stepEndDate = new Date(stepStartDate.getTime() + (step.estimatedTime / 60 / 8) * 24 * 60 * 60 * 1000);

        // 진행 상태 결정
        let woStatus = '완료';
        if (orderStatus === '생산중' || orderStatus === '출하중') {
          if (procIdx > processMapping.requiredProcesses.length / 2) woStatus = '대기';
          else if (stepIdx > workflow.steps.length / 2) woStatus = '진행중';
        }

        // 자재투입 단계(MAT, CUT)에서 LOT 정보 할당
        const isMaterialInputStep = step.stepCode.includes('-MAT') || step.stepCode.includes('-CUT');
        let assignedLots = [];

        if (isMaterialInputStep && woStatus !== '대기') {
          // 공정별 자재 LOT 할당
          const lotKey = workflowCode === 'SCREEN' ? 'SCR-SCREEN' :
                         workflowCode === 'SLAT' ? 'SLT-SLAT' :
                         workflowCode === 'FOLD' ? 'STL-FOLD' :
                         workflowCode === 'STOCK' ? 'STL-SHAFT' : null;

          if (lotKey && materialLotMaster[lotKey]) {
            const availableLots = materialLotMaster[lotKey];
            const selectedLot = availableLots[(i + procIdx) % availableLots.length];
            assignedLots.push({
              lotNo: selectedLot.lotNo,
              material: selectedLot.material,
              usedQty: qty,
              unit: selectedLot.unit === 'm²' ? Math.ceil(sizeOpt.W0 * sizeOpt.H0 / 1000000 * qty * 1.1) : qty,
              unitLabel: selectedLot.unit,
            });

            // 자재 LOT 사용 이력 추가
            testData.materialLotUsage.push({
              id: testData.materialLotUsage.length + 1,
              lotNo: selectedLot.lotNo,
              material: selectedLot.material,
              workOrderId,
              workOrderNo,
              orderNo,
              stepCode: step.stepCode,
              stepName: step.stepName,
              usedQty: assignedLots[0].unit,
              unitLabel: selectedLot.unit,
              usedDate: stepStartDate.toISOString().split('T')[0],
              usedBy: `${workflow.name}작업자${stepIdx + 1}`,
            });
          }
        }

        const workOrder = {
          id: workOrderId,
          workOrderNo,
          workOrderDate: stepStartDate.toISOString().split('T')[0],
          status: woStatus,
          // 연결 정보
          orderId,
          orderNo,
          productionOrderId,
          productionOrderNo,
          // 공정 정보
          workflowCode,
          workflowName: workflow.name,
          processCode: processMasterConfig.sampleProcesses.find(p => p.workflowCode === workflowCode)?.processCode || `${workflowCode}-001`,
          processName: workflow.name,
          // 단계 정보
          stepNo: step.stepNo,
          stepCode: step.stepCode,
          stepName: step.stepName,
          stepDescription: step.description,
          estimatedTime: step.estimatedTime,
          isQCStep: step.isQCStep || false,
          isMaterialInputStep, // 자재투입 단계 여부
          // 제품 정보
          productType,
          productionSizeW: sizeOpt.W0 + 140,
          productionSizeH: sizeOpt.H0 + 350,
          qty,
          // 작업 계획
          plannedStartDate: stepStartDate.toISOString().split('T')[0],
          plannedEndDate: stepEndDate.toISOString().split('T')[0],
          plannedQty: qty,
          // 작업 실적
          actualStartDate: woStatus !== '대기' ? stepStartDate.toISOString().split('T')[0] : null,
          actualEndDate: woStatus === '완료' ? stepEndDate.toISOString().split('T')[0] : null,
          actualQty: woStatus === '완료' ? qty : (woStatus === '진행중' ? Math.floor(qty / 2) : 0),
          // 자재 정보 (LOT 추적 포함)
          inputMaterials: step.inputMaterials || [],
          outputMaterials: step.outputMaterials || [],
          assignedLots, // 할당된 자재 LOT 정보
          checkPoints: step.checkPoints || [],
          requiredEquipment: step.requiredEquipment || [],
          // 작업자
          worker: `${workflow.name}작업자${stepIdx + 1}`,
          workCenter: `${workflow.name}라인`,
          // 메타
          createdBy: '생산관리',
          createdAt: stepStartDate.toISOString(),
          note: `${site.siteName} ${workflow.name} ${step.stepName}`,
        };

        testData.workOrders.push(workOrder);

        // ============ 4-1. 작업실적 생성 (완료된 작업지시에 대해) ============
        if (woStatus === '완료' || woStatus === '진행중') {
          const resultStartTime = woStatus === '완료' ? stepStartDate : stepStartDate;
          const resultEndTime = woStatus === '완료' ? stepEndDate : null;
          const resultQty = woStatus === '완료' ? qty : Math.floor(qty / 2);

          testData.workResults.push({
            id: testData.workResults.length + 1,
            resultNo: `WR-${workOrderNo}`,
            resultDate: stepStartDate.toISOString().split('T')[0],
            status: woStatus === '완료' ? '확정' : '입력중',
            // 연결 정보
            workOrderId,
            workOrderNo,
            orderId,
            orderNo,
            productionOrderId,
            productionOrderNo,
            // 공정/단계 정보
            workflowCode,
            workflowName: workflow.name,
            stepCode: step.stepCode,
            stepName: step.stepName,
            // 작업 시간
            startTime: resultStartTime.toISOString(),
            endTime: resultEndTime ? resultEndTime.toISOString() : null,
            workingMinutes: woStatus === '완료' ? step.estimatedTime : Math.floor(step.estimatedTime / 2),
            // 생산 수량
            plannedQty: qty,
            goodQty: resultQty,
            defectQty: 0,
            scrapQty: 0,
            // 자재 투입 정보
            materialInputs: assignedLots.length > 0 ? assignedLots : [],
            // 작업자 정보
            worker: workOrder.worker,
            workCenter: workOrder.workCenter,
            equipmentUsed: step.requiredEquipment || [],
            // 품질 체크
            checkResults: (step.checkPoints || []).map((cp, idx) => ({
              checkItem: cp,
              result: 'OK',
              value: '',
              note: '',
            })),
            // 메타
            createdBy: workOrder.worker,
            createdAt: stepStartDate.toISOString(),
            confirmedBy: woStatus === '완료' ? '생산관리자' : null,
            confirmedAt: woStatus === '완료' ? stepEndDate.toISOString() : null,
            note: `${site.siteName} ${workflow.name} ${step.stepName} 작업실적`,
          });
        }

        // ============ 5. 중간검사(PQC) 생성 - isQCStep이 true인 단계만 ============
        if (step.isQCStep && woStatus === '완료') {
          const inspDate = new Date(stepEndDate.getTime() + 0.5 * 24 * 60 * 60 * 1000);
          const result = (workOrderId % 15 === 0) ? '불합격' : '합격'; // 약 7%만 불합격
          const pqcId = testData.pqcInspections.length + 1;

          // 불합격 시 재작업 정보 생성
          let reworkInfo = null;
          if (result === '불합격') {
            const reworkStartDate = new Date(inspDate.getTime() + 1 * 24 * 60 * 60 * 1000);
            const reworkEndDate = new Date(reworkStartDate.getTime() + 2 * 24 * 60 * 60 * 1000);

            reworkInfo = {
              reworkOrderNo: `RW-${workOrderNo}`,
              reworkType: '재가공', // 재가공, 수리, 폐기 중 선택
              reworkReason: `${step.stepName} 검사 불합격 - 기준 미달`,
              reworkStepCode: step.stepCode.replace('-QC', ''), // QC 이전 단계로 복귀
              reworkStepName: workflow.steps.find(s => s.stepCode === step.stepCode.replace('-QC', ''))?.stepName || '이전 단계',
              reworkStartDate: reworkStartDate.toISOString().split('T')[0],
              reworkEndDate: reworkEndDate.toISOString().split('T')[0],
              reworkQty: qty,
              reworkStatus: '완료', // 재작업 완료 처리
              reworkResult: '합격', // 재작업 후 재검사 합격
              reworkInspectionNo: `PQC-RW-${workOrderNo}`,
              reworkBy: `${workflow.name}작업자${stepIdx + 1}`,
              note: '재작업 완료 후 재검사 합격',
            };
          }

          testData.pqcInspections.push({
            id: pqcId,
            inspectionNo: `PQC-${workOrderNo}`,
            inspectionDate: inspDate.toISOString().split('T')[0],
            inspectionType: '중간검사(PQC)',
            status: result === '합격' ? '완료' : '재작업',
            result,
            // 연결 정보
            workOrderId,
            workOrderNo,
            orderId,
            orderNo,
            productionOrderId,
            productionOrderNo,
            // 공정/단계 정보
            workflowCode,
            workflowName: workflow.name,
            stepCode: step.stepCode,
            stepName: step.stepName,
            // 검사 정보
            inspectedQty: qty,
            passedQty: result === '합격' ? qty : 0,
            failedQty: result === '불합격' ? qty : 0,
            // 검사 항목
            checkItems: (step.checkPoints || []).map((cp, idx) => ({
              seq: idx + 1,
              item: cp,
              spec: '기준 충족',
              result: result === '합격' ? 'OK' : (idx === 0 ? 'NG' : 'OK'),
              note: result === '불합격' && idx === 0 ? '기준 미달로 재작업 필요' : '',
            })),
            // 재작업 정보 (불합격 시에만)
            reworkInfo,
            // 메타
            inspector: '품질검사원',
            createdAt: inspDate.toISOString(),
            note: result === '불합격' ? `${step.stepName} 검사 불합격 - 재작업 지시` : '',
          });
        }
      });
    });

    // ============ 6. 포장 데이터 생성 ============
    if (['생산완료', '출하중', '출하완료', '완료'].includes(orderStatus)) {
      const packDate = new Date(dueDate.getTime() - 5 * 24 * 60 * 60 * 1000);

      // 포장 합류점(mergePoint) - 모든 공정의 PACK 단계 정보 수집
      const mergedProcesses = processMapping.requiredProcesses.map(wfCode => {
        const packStepCode = wfCode === 'SCREEN' ? 'SCR-PACK' :
                             wfCode === 'SLAT' ? 'SLT-PACK' :
                             wfCode === 'FOLD' ? 'FLD-PACK' :
                             wfCode === 'STOCK' ? 'STK-PACK' : null;
        return {
          workflowCode: wfCode,
          workflowName: workflows[wfCode]?.name || wfCode,
          packStepCode,
          status: '완료',
          completedDate: new Date(packDate.getTime() - 1 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
        };
      });

      // 채번규칙 적용: 포장번호
      const packagingNo = generateDocNo('KD-PK', packDate, (i % 10) + 1);
      testData.packaging.push({
        id: i + 1,
        packagingNo,
        packagingDate: packDate.toISOString().split('T')[0],
        status: '완료',
        // 연결 정보
        orderId,
        orderNo,
        productionOrderId,
        productionOrderNo,
        // 포장 합류점 정보 (모든 공정의 PACK 단계 합류)
        mergePoint: 'PACK',
        mergedProcesses, // 합류된 공정 목록
        totalMergedProcesses: processMapping.requiredProcesses.length,
        // 포장 정보
        packedQty: qty,
        packagingType: '목재포장',
        packageCount: Math.ceil(qty / 2), // 2개씩 포장
        totalWeight: weight * qty,
        // 라벨 정보
        labelInfo: {
          orderNo,
          siteName: site.siteName,
          productType,
          size: `${sizeOpt.W0}×${sizeOpt.H0}`,
          qty,
          packDate: packDate.toISOString().split('T')[0],
        },
        // 품질 정보 (FQC 통과 여부)
        fqcPassed: true,
        fqcDate: new Date(packDate.getTime() - 1 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
        // 메타
        worker: '포장작업자',
        createdAt: packDate.toISOString(),
        note: `${site.siteName} 방화셔터 ${qty}대 포장 (${processMapping.requiredProcesses.join('+')} 합류)`,
      });
    }

    // ============ 7. 출하 데이터 생성 ============
    if (['출하중', '출하완료', '완료'].includes(orderStatus)) {
      const shipDate = new Date(dueDate.getTime() - 3 * 24 * 60 * 60 * 1000);
      const deliveryDate = new Date(shipDate.getTime() + 2 * 24 * 60 * 60 * 1000);

      let shipStatus = '출하대기';
      if (orderStatus === '완료') shipStatus = '배송완료';
      else if (orderStatus === '출하완료') shipStatus = '배송중';
      else if (orderStatus === '출하중') shipStatus = '출하중';

      // 채번규칙 적용: KD-SH-YYMMDD-##
      const shipmentNo = generateDocNo('KD-SH', shipDate, (i % 10) + 1);
      const shipPackagingNo = generateDocNo('KD-PK', new Date(shipDate.getTime() - 3 * 24 * 60 * 60 * 1000), (i % 10) + 1);
      testData.shipments.push({
        id: i + 1,
        shipmentNo,
        shipmentDate: shipDate.toISOString().split('T')[0],
        expectedDeliveryDate: deliveryDate.toISOString().split('T')[0],
        actualDeliveryDate: shipStatus === '배송완료' ? deliveryDate.toISOString().split('T')[0] : null,
        status: shipStatus,
        // 연결 정보
        orderId,
        orderNo,
        packagingId: i + 1,
        packagingNo: shipPackagingNo,
        // 거래처/현장 정보
        customerId: customer.id,
        customerName: customer.name,
        siteId: site.id,
        siteName: site.siteName,
        deliveryAddress: site.address,
        siteManager: site.manager,
        siteTel: site.tel,
        // 출하 정보
        shippedQty: qty,
        packageCount: Math.ceil(qty / 2),
        totalWeight: weight * qty,
        // 배송 정보
        carrier: '자사배송',
        vehicleNo: `서울 가 ${1000 + (i % 100)}`,
        driverName: `운전자${(i % 5) + 1}`,
        driverTel: `010-9999-${String(1000 + (i % 100)).padStart(4, '0')}`,
        // 출하 진행률 (수주관리에서 표시용)
        progress: shipStatus === '배송완료' ? 100 :
                  shipStatus === '배송중' ? 75 :
                  shipStatus === '출하중' ? 50 : 25,
        // 메타
        createdBy: '물류팀',
        createdAt: shipDate.toISOString(),
        note: `${site.siteName} 배송`,
      });
    }
  }

  return testData;
};

// ============ BOM 품목 생성 함수 ============
const generateBOMItems = (productType, sizeOpt, qty) => {
  const { W0, H0 } = sizeOpt;
  const area = (W0 * H0) / 1000000;

  const items = [];
  let lineNo = 0;

  if (productType === '스크린') {
    // 스크린 원단
    items.push({
      lineNo: ++lineNo,
      itemCode: 'SCR-SCREEN',
      itemName: '스크린 원단',
      itemType: '반제품',
      processCode: 'SCR-001',
      workflowCode: 'SCREEN',
      qty,
      unit: 'EA',
      unitPrice: Math.round(area * 350000),
      amount: Math.round(area * 350000 * qty),
      spec: `${W0}×${H0}mm`,
    });
  }

  // 슬랫 (스크린, 철재 공통)
  const slatCount = Math.ceil(H0 / 75) * qty; // 75mm 피치 기준
  items.push({
    lineNo: ++lineNo,
    itemCode: 'SLT-SLAT',
    itemName: '슬랫',
    itemType: '반제품',
    processCode: 'SLT-001',
    workflowCode: 'SLAT',
    qty: slatCount,
    unit: 'EA',
    unitPrice: Math.round(W0 * 8),
    amount: Math.round(W0 * 8 * slatCount),
    spec: `W${W0}mm`,
  });

  // 가이드레일 (절곡)
  items.push({
    lineNo: ++lineNo,
    itemCode: 'STL-GUIDE',
    itemName: '가이드레일',
    itemType: '반제품',
    processCode: 'FLD-001',
    workflowCode: 'FOLD',
    qty: qty * 2,
    unit: 'EA',
    unitPrice: Math.round(H0 * 15),
    amount: Math.round(H0 * 15 * qty * 2),
    spec: `H${H0}mm`,
  });

  // 케이스 (절곡)
  items.push({
    lineNo: ++lineNo,
    itemCode: 'STL-CASE',
    itemName: '케이스',
    itemType: '반제품',
    processCode: 'FLD-001',
    workflowCode: 'FOLD',
    qty,
    unit: 'EA',
    unitPrice: Math.round(W0 * 20),
    amount: Math.round(W0 * 20 * qty),
    spec: `W${W0}mm`,
  });

  // 샤프트 (재고생산/포밍)
  items.push({
    lineNo: ++lineNo,
    itemCode: 'STL-SHAFT',
    itemName: '샤프트',
    itemType: '반제품',
    processCode: 'STK-001',
    workflowCode: 'STOCK',
    qty,
    unit: 'EA',
    unitPrice: Math.round(W0 * 12),
    amount: Math.round(W0 * 12 * qty),
    spec: `W${W0}mm`,
  });

  // 브라켓 (절곡)
  items.push({
    lineNo: ++lineNo,
    itemCode: 'STL-BRACKET',
    itemName: '브라켓',
    itemType: '반제품',
    processCode: 'FLD-001',
    workflowCode: 'FOLD',
    qty: qty * 2,
    unit: 'EA',
    unitPrice: 25000,
    amount: 25000 * qty * 2,
  });

  // 구매품 (공정 불필요)
  items.push({
    lineNo: ++lineNo,
    itemCode: 'MTR-MOTOR',
    itemName: '튜블러모터',
    itemType: '구매품',
    processCode: null,
    workflowCode: null,
    qty,
    unit: 'EA',
    unitPrice: 180000,
    amount: 180000 * qty,
    isPurchased: true,
  });

  items.push({
    lineNo: ++lineNo,
    itemCode: 'CTL-CTRL',
    itemName: '제어기',
    itemType: '구매품',
    processCode: null,
    workflowCode: null,
    qty,
    unit: 'EA',
    unitPrice: 85000,
    amount: 85000 * qty,
    isPurchased: true,
  });

  return items;
};

// ============ 품목별 공정 그룹화 함수 ============
const groupItemsByProcess = (bomItems, requiredProcesses) => {
  const groups = {};

  requiredProcesses.forEach(workflowCode => {
    groups[workflowCode] = {
      workflowCode,
      workflowName: processMasterConfig.processWorkflows[workflowCode]?.name || workflowCode,
      processCode: processMasterConfig.sampleProcesses.find(p => p.workflowCode === workflowCode)?.processCode,
      items: [],
      totalSteps: processMasterConfig.processWorkflows[workflowCode]?.steps?.length || 0,
    };
  });

  bomItems.forEach(item => {
    if (item.workflowCode && groups[item.workflowCode]) {
      groups[item.workflowCode].items.push(item);
    }
  });

  return Object.values(groups).filter(g => g.items.length > 0 || g.totalSteps > 0);
};

// ============ 테스트 데이터 요약 정보 생성 ============
export const generateTestDataSummary = (testData) => {
  return {
    totalQuotes: testData.quotes.length,
    totalOrders: testData.orders.length,
    totalProductionOrders: testData.productionOrders.length,
    totalWorkOrders: testData.workOrders.length,
    totalWorkResults: testData.workResults?.length || 0,
    totalPQCInspections: testData.pqcInspections.length,
    totalPackaging: testData.packaging.length,
    totalShipments: testData.shipments.length,
    totalMaterialLotUsage: testData.materialLotUsage?.length || 0,

    // 상태별 분포
    orderStatusDistribution: testData.orders.reduce((acc, o) => {
      acc[o.status] = (acc[o.status] || 0) + 1;
      return acc;
    }, {}),

    // 공정별 작업지시 분포
    workOrdersByProcess: testData.workOrders.reduce((acc, wo) => {
      acc[wo.workflowCode] = (acc[wo.workflowCode] || 0) + 1;
      return acc;
    }, {}),

    // 작업실적 상태 분포
    workResultStatusDistribution: (testData.workResults || []).reduce((acc, wr) => {
      acc[wr.status] = (acc[wr.status] || 0) + 1;
      return acc;
    }, {}),

    // PQC 검사 결과 분포
    pqcResultDistribution: testData.pqcInspections.reduce((acc, insp) => {
      acc[insp.result] = (acc[insp.result] || 0) + 1;
      return acc;
    }, {}),

    // 재작업 건수
    reworkCount: testData.pqcInspections.filter(p => p.reworkInfo).length,

    // 자재 LOT 사용 현황
    materialLotUsageSummary: (testData.materialLotUsage || []).reduce((acc, mu) => {
      acc[mu.material] = (acc[mu.material] || 0) + 1;
      return acc;
    }, {}),

    // 출하 상태 분포
    shipmentStatusDistribution: testData.shipments.reduce((acc, s) => {
      acc[s.status] = (acc[s.status] || 0) + 1;
      return acc;
    }, {}),

    // 포장 합류점 통계
    packagingMergeStats: testData.packaging.reduce((acc, pkg) => {
      acc.totalMerged = (acc.totalMerged || 0) + (pkg.totalMergedProcesses || 0);
      return acc;
    }, { totalMerged: 0 }),
  };
};

// ============ 데이터 정합성 검증 함수 ============
export const validateE2EDataIntegrity = (testData) => {
  const issues = [];

  // 1. 견적→수주 연결 검증
  testData.orders.forEach(order => {
    const quote = testData.quotes.find(q => q.id === order.quoteId);
    if (!quote) {
      issues.push(`수주 ${order.orderNo}: 연결된 견적(${order.quoteId}) 없음`);
    }
  });

  // 2. 수주→생산지시 연결 검증
  testData.productionOrders.forEach(po => {
    const order = testData.orders.find(o => o.id === po.orderId);
    if (!order) {
      issues.push(`생산지시 ${po.productionOrderNo}: 연결된 수주(${po.orderId}) 없음`);
    }
  });

  // 3. 작업지시→PQC 연결 검증 (QC 단계만)
  const qcWorkOrders = testData.workOrders.filter(wo => wo.isQCStep && wo.status === '완료');
  qcWorkOrders.forEach(wo => {
    const pqc = testData.pqcInspections.find(p => p.workOrderId === wo.id);
    if (!pqc) {
      issues.push(`작업지시 ${wo.workOrderNo}: QC 단계이나 PQC 검사 없음`);
    }
  });

  // 4. 출하→포장 연결 검증
  testData.shipments.forEach(ship => {
    const pkg = testData.packaging.find(p => p.id === ship.packagingId);
    if (!pkg) {
      issues.push(`출하 ${ship.shipmentNo}: 연결된 포장(${ship.packagingId}) 없음`);
    }
  });

  // 5. 작업지시→작업실적 연결 검증 (완료/진행중 상태만)
  const completedWorkOrders = testData.workOrders.filter(wo => wo.status === '완료' || wo.status === '진행중');
  completedWorkOrders.forEach(wo => {
    const wr = (testData.workResults || []).find(r => r.workOrderId === wo.id);
    if (!wr) {
      issues.push(`작업지시 ${wo.workOrderNo}: ${wo.status} 상태이나 작업실적 없음`);
    }
  });

  // 6. 자재투입 단계→LOT 할당 검증
  const materialInputSteps = testData.workOrders.filter(wo => wo.isMaterialInputStep && wo.status !== '대기');
  materialInputSteps.forEach(wo => {
    if (!wo.assignedLots || wo.assignedLots.length === 0) {
      // 경고 수준 (필수는 아니지만 권장)
      // issues.push(`작업지시 ${wo.workOrderNo}: 자재투입 단계이나 LOT 할당 없음`);
    }
  });

  // 7. 포장 합류점 검증
  testData.packaging.forEach(pkg => {
    if (!pkg.mergedProcesses || pkg.mergedProcesses.length === 0) {
      issues.push(`포장 ${pkg.packagingNo}: 합류된 공정 정보 없음`);
    }
  });

  // 8. PQC 불합격→재작업 정보 검증
  const failedPQC = testData.pqcInspections.filter(p => p.result === '불합격');
  failedPQC.forEach(pqc => {
    if (!pqc.reworkInfo) {
      issues.push(`PQC ${pqc.inspectionNo}: 불합격이나 재작업 정보 없음`);
    }
  });

  return {
    isValid: issues.length === 0,
    issueCount: issues.length,
    issues,
    validationStats: {
      totalQuotes: testData.quotes.length,
      totalOrders: testData.orders.length,
      totalWorkOrders: testData.workOrders.length,
      totalWorkResults: testData.workResults?.length || 0,
      totalPQC: testData.pqcInspections.length,
      failedPQC: failedPQC.length,
      reworkCompleted: failedPQC.filter(p => p.reworkInfo?.reworkStatus === '완료').length,
    },
  };
};

export default {
  productProcessMapping,
  bomItemProcessMapping,
  materialLotMaster,
  generateE2ETestData,
  generateTestDataSummary,
  validateE2EDataIntegrity,
};
