/**
 * 통합 테스트 스크립트 - 100회 다양한 시나리오 테스트
 * Node.js로 실행하여 로직 검증
 */

// 번호 생성 함수들 (App.jsx에서 복사)
const factoryCodes = {
  '스크린': 'TS',
  '슬랫': 'SL',
  '절곡': 'BD',
};

const formatDateCode = (date) => {
  const d = 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 generateQuoteNo = (date, seq) =>
  `KD-PR-${formatDateCode(date)}-${String(seq).padStart(2, '0')}`;

const generateOrderNo = (modelType, date, seq) => {
  const code = factoryCodes[modelType] || modelType || 'TS';
  return `KD-${code}-${formatDateCode(date)}-${String(seq).padStart(2, '0')}`;
};

const generateProductionLot = (date, seq) =>
  `KD-PL-${formatDateCode(date)}-${String(seq).padStart(2, '0')}`;

const generateProductLot = (orderNo, splitSeq = 1) =>
  `${orderNo}-${String(splitSeq).padStart(2, '0')}`;

const generateIncomingInspectionLot = (date, seq) =>
  `${formatDateCode(date)}-${String(seq).padStart(2, '0')}`;

const generateProcessInspectionLot = (date, seq, step) =>
  `KD-WE-${formatDateCode(date)}-${String(seq).padStart(2, '0')}-(${step})`;

const generateProductInspectionLot = (date, seq) =>
  `KD-SA-${formatDateCode(date)}-${String(seq).padStart(2, '0')}`;

// 테스트 시나리오 정의
const testScenarios = [
  { id: 'normal', label: '정상 프로세스', weight: 30 },
  { id: 'quote-cancel', label: '견적 취소', weight: 10 },
  { id: 'quote-expire', label: '견적 만료', weight: 5 },
  { id: 'quality-fail', label: '품질 불합격', weight: 10 },
  { id: 'quality-conditional', label: '조건부 합격', weight: 10 },
  { id: 'partial-shipment', label: '부분 출하', weight: 10 },
  { id: 'payment-delay', label: '수금 지연', weight: 10 },
  { id: 'rush-order', label: '긴급 주문', weight: 10 },
  { id: 'size-change', label: '사이즈 변경', weight: 5 },
];

// 샘플 고객 데이터
const sampleCustomers = [
  { id: 1, name: '삼성건설', creditGrade: 'A', discountRate: 5 },
  { id: 2, name: '현대개발', creditGrade: 'B', discountRate: 3 },
  { id: 3, name: '한화시공', creditGrade: 'C', discountRate: 0 },
  { id: 4, name: '대우건설', creditGrade: 'A', discountRate: 7 },
  { id: 5, name: '포스코건설', creditGrade: 'B', discountRate: 2 },
];

// 제품 타입
const productTypes = ['스크린', '슬랫', '절곡'];

// 랜덤 선택 함수
const randomChoice = (arr) => arr[Math.floor(Math.random() * arr.length)];
const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

// 가중치 기반 시나리오 선택
const selectScenario = () => {
  const totalWeight = testScenarios.reduce((sum, s) => sum + s.weight, 0);
  let random = Math.random() * totalWeight;
  for (const scenario of testScenarios) {
    random -= scenario.weight;
    if (random <= 0) return scenario.id;
  }
  return 'normal';
};

// 테스트 결과 저장
const testResults = {
  total: 0,
  passed: 0,
  failed: 0,
  errors: [],
  scenarioCounts: {},
  numberPatternErrors: [],
  dataIntegrityErrors: [],
  businessLogicErrors: [],
  performanceIssues: [],
  uxIssues: [],
};

// 번호 패턴 검증
const validateNumberPatterns = (data, testNum) => {
  const errors = [];

  // 견적번호 검증
  if (data.quoteNo && !/^KD-PR-\d{6}-\d{2}$/.test(data.quoteNo)) {
    errors.push(`[Test ${testNum}] 견적번호 형식 오류: ${data.quoteNo}`);
  }

  // 수주번호 검증
  if (data.orderNo && !/^KD-(TS|SL|BD)-\d{6}-\d{2}$/.test(data.orderNo)) {
    errors.push(`[Test ${testNum}] 수주번호 형식 오류: ${data.orderNo}`);
  }

  // 생산 LOT 검증
  if (data.productionLot && !/^KD-PL-\d{6}-\d{2}$/.test(data.productionLot)) {
    errors.push(`[Test ${testNum}] 생산 LOT 형식 오류: ${data.productionLot}`);
  }

  // 완제품 LOT 검증 (수주번호-순번)
  if (data.productLot && !/^KD-(TS|SL|BD)-\d{6}-\d{2}-\d{2}$/.test(data.productLot)) {
    errors.push(`[Test ${testNum}] 완제품 LOT 형식 오류: ${data.productLot}`);
  }

  // 중간검사 LOT 검증
  if (data.processInspLot && !/^KD-WE-\d{6}-\d{2}-\(\d+\)$/.test(data.processInspLot)) {
    errors.push(`[Test ${testNum}] 중간검사 LOT 형식 오류: ${data.processInspLot}`);
  }

  // 제품검사 LOT 검증
  if (data.productInspLot && !/^KD-SA-\d{6}-\d{2}$/.test(data.productInspLot)) {
    errors.push(`[Test ${testNum}] 제품검사 LOT 형식 오류: ${data.productInspLot}`);
  }

  return errors;
};

// 데이터 무결성 검증
const validateDataIntegrity = (data, testNum) => {
  const errors = [];

  // 수주가 견적을 참조하는지
  if (data.order && data.quote) {
    if (data.order.quoteNo !== data.quote.quoteNo) {
      errors.push(`[Test ${testNum}] 수주-견적 연결 오류: 수주(${data.order.quoteNo}) != 견적(${data.quote.quoteNo})`);
    }
  }

  // 생산 수량 일관성
  if (data.workOrders && data.order) {
    const totalProduced = data.workOrders.reduce((sum, wo) => sum + (wo.producedQty || 0), 0);
    // 공정이 5개이므로 qty * 5가 되어야 함
  }

  // 출하 수량 검증
  if (data.shipment && data.order) {
    if (data.shipment.totalQty !== data.order.qty && data.order.qty) {
      // 의도적인 부분 출하가 아닌 경우
    }
  }

  // 금액 일관성
  if (data.sales && data.order) {
    if (Math.abs(data.sales.totalAmount - data.order.totalAmount) > 1) {
      errors.push(`[Test ${testNum}] 매출-수주 금액 불일치: 매출(${data.sales.totalAmount}) != 수주(${data.order.totalAmount})`);
    }
  }

  return errors;
};

// 비즈니스 로직 검증
const validateBusinessLogic = (data, scenario, testNum) => {
  const errors = [];

  // A등급은 바로 출고 가능
  if (data.customer?.creditGrade === 'A' && scenario !== 'payment-delay') {
    if (data.order?.status === '입금대기') {
      errors.push(`[Test ${testNum}] A등급 고객인데 입금대기 상태`);
    }
  }

  // C등급은 경리 승인 필요
  if (data.customer?.creditGrade === 'C') {
    // 경리 승인 없이 출고되면 안됨 (로직 확인용)
  }

  // 견적 취소 시 수주 전환 안됨
  if (scenario === 'quote-cancel') {
    if (data.order) {
      errors.push(`[Test ${testNum}] 견적 취소했는데 수주가 생성됨`);
    }
  }

  // 품질 불합격 시 재작업 필요
  if (scenario === 'quality-fail') {
    if (!data.reworkOrder) {
      errors.push(`[Test ${testNum}] 품질 불합격인데 재작업 지시 없음`);
    }
  }

  // 부분 출하 시 잔여 출하 필요
  if (scenario === 'partial-shipment') {
    if (!data.shipment2) {
      errors.push(`[Test ${testNum}] 부분 출하인데 잔여 출하 없음`);
    }
  }

  return errors;
};

// 단일 테스트 실행
const runSingleTest = (testNum) => {
  const scenario = selectScenario();
  const customer = randomChoice(sampleCustomers);
  const productType = randomChoice(productTypes);
  const today = new Date();
  const seq = randomInt(1, 99);

  testResults.scenarioCounts[scenario] = (testResults.scenarioCounts[scenario] || 0) + 1;

  try {
    // 번호 생성
    const quoteNo = generateQuoteNo(today, seq);
    const orderNo = generateOrderNo(productType, today, seq);
    const productionLot = generateProductionLot(today, seq);
    const productLot = generateProductLot(orderNo, 1);
    const processInspLot = generateProcessInspectionLot(today, seq, 3);
    const productInspLot = generateProductInspectionLot(today, seq);
    const incomingLot = generateIncomingInspectionLot(today, seq);

    // 테스트 데이터 구성
    const data = {
      quoteNo,
      orderNo,
      productionLot,
      productLot,
      processInspLot,
      productInspLot,
      incomingLot,
      customer,
      productType,
      scenario,
      quote: scenario !== 'quote-cancel' && scenario !== 'quote-expire' ? { quoteNo, status: '확정' } : null,
      order: scenario !== 'quote-cancel' && scenario !== 'quote-expire' ? {
        orderNo,
        quoteNo,
        totalAmount: randomInt(100000, 10000000),
        qty: randomInt(1, 100)
      } : null,
      workOrders: scenario !== 'quote-cancel' && scenario !== 'quote-expire' ?
        ['스크린', '절곡', '샤프트', '조립', '전장'].map((p, i) => ({
          processName: p,
          producedQty: randomInt(1, 100),
          status: '완료'
        })) : null,
      shipment: scenario !== 'quote-cancel' && scenario !== 'quote-expire' ? {
        status: scenario === 'partial-shipment' ? '부분출하' : '완료',
        totalQty: randomInt(1, 100)
      } : null,
      shipment2: scenario === 'partial-shipment' ? { status: '완료' } : null,
      reworkOrder: scenario === 'quality-fail' ? { status: '재작업완료' } : null,
      sales: scenario !== 'quote-cancel' && scenario !== 'quote-expire' ? {
        totalAmount: randomInt(100000, 10000000)
      } : null,
    };

    // 번호 패턴 검증
    const patternErrors = validateNumberPatterns(data, testNum);
    testResults.numberPatternErrors.push(...patternErrors);

    // 데이터 무결성 검증
    const integrityErrors = validateDataIntegrity(data, testNum);
    testResults.dataIntegrityErrors.push(...integrityErrors);

    // 비즈니스 로직 검증
    const logicErrors = validateBusinessLogic(data, scenario, testNum);
    testResults.businessLogicErrors.push(...logicErrors);

    if (patternErrors.length === 0 && integrityErrors.length === 0 && logicErrors.length === 0) {
      testResults.passed++;
    } else {
      testResults.failed++;
    }

  } catch (error) {
    testResults.failed++;
    testResults.errors.push(`[Test ${testNum}] 예외 발생: ${error.message}`);
  }

  testResults.total++;
};

// UX 분석
const analyzeUX = () => {
  const issues = [];

  // 1. 번호 체계 가독성
  issues.push({
    category: '번호 체계',
    severity: 'medium',
    issue: '수주번호에서 모델코드(TS/SL/BD)가 직관적이지 않음',
    suggestion: '툴팁이나 범례 추가 필요 (TS=스크린, SL=슬랫, BD=절곡)'
  });

  // 2. 중간검사 LOT 형식
  issues.push({
    category: '번호 체계',
    severity: 'low',
    issue: '중간검사 LOT의 공정단계 표시가 괄호로 되어있어 가독성 저하',
    suggestion: 'KD-WE-251209-01-(3) → KD-WE-251209-01-P3 형태로 개선 고려'
  });

  // 3. 시나리오 실행 피드백
  issues.push({
    category: '테스트 UI',
    severity: 'high',
    issue: '시나리오 실행 중 현재 어떤 단계인지 사용자가 파악하기 어려움',
    suggestion: '프로그레스 바와 현재 단계 텍스트 표시 필요'
  });

  // 4. 에러 상황 처리
  issues.push({
    category: '에러 처리',
    severity: 'high',
    issue: '품질 불합격, 부분 출하 등 예외 상황에서 사용자 안내 부족',
    suggestion: '모달 알림이나 토스트 메시지로 상황 설명 필요'
  });

  // 5. 데이터 연결성 표시
  issues.push({
    category: '데이터 추적',
    severity: 'medium',
    issue: '견적→수주→생산→출하 연결 관계가 시각적으로 표현되지 않음',
    suggestion: '타임라인 또는 플로우 다이어그램으로 관계 표시'
  });

  // 6. 고객 등급별 프로세스
  issues.push({
    category: '비즈니스 로직',
    severity: 'medium',
    issue: 'A/B/C 등급별 프로세스 차이가 명확히 표시되지 않음',
    suggestion: '등급별 워크플로우 차이를 색상이나 아이콘으로 구분'
  });

  // 7. 번호 검색 기능
  issues.push({
    category: '검색/조회',
    severity: 'high',
    issue: '생성된 번호로 데이터 조회하는 기능 없음',
    suggestion: 'LOT 추적, 수주번호 검색 기능 추가 필요'
  });

  // 8. 테스트 결과 저장
  issues.push({
    category: '테스트 기능',
    severity: 'medium',
    issue: '테스트 실행 결과가 저장되지 않아 이력 관리 불가',
    suggestion: '테스트 결과 내보내기(Excel/JSON) 기능 추가'
  });

  // 9. 대량 테스트 지원
  issues.push({
    category: '테스트 기능',
    severity: 'low',
    issue: '단일 시나리오만 실행 가능, 대량 테스트 불가',
    suggestion: '배치 테스트 기능 및 결과 통계 대시보드 추가'
  });

  // 10. 모바일 대응
  issues.push({
    category: 'UI/반응형',
    severity: 'medium',
    issue: '테스트 화면이 모바일에서 사용하기 어려움',
    suggestion: '반응형 레이아웃 및 터치 친화적 UI 개선'
  });

  return issues;
};

// 100회 테스트 실행
console.log('========================================');
console.log('  통합 테스트 시작 - 100회 실행');
console.log('========================================\n');

const startTime = Date.now();

for (let i = 1; i <= 100; i++) {
  runSingleTest(i);
  if (i % 20 === 0) {
    console.log(`  진행: ${i}/100 완료...`);
  }
}

const endTime = Date.now();

// UX 분석
testResults.uxIssues = analyzeUX();

// 결과 출력
console.log('\n========================================');
console.log('  테스트 결과 요약');
console.log('========================================\n');

console.log(`총 테스트: ${testResults.total}회`);
console.log(`성공: ${testResults.passed}회`);
console.log(`실패: ${testResults.failed}회`);
console.log(`실행 시간: ${endTime - startTime}ms\n`);

console.log('시나리오별 실행 횟수:');
Object.entries(testResults.scenarioCounts).forEach(([scenario, count]) => {
  console.log(`  - ${scenario}: ${count}회`);
});

console.log('\n========================================');
console.log('  번호 패턴 검증 결과');
console.log('========================================');
if (testResults.numberPatternErrors.length === 0) {
  console.log('✅ 모든 번호 패턴이 정상입니다.\n');
} else {
  console.log(`❌ ${testResults.numberPatternErrors.length}개 오류 발견:\n`);
  testResults.numberPatternErrors.slice(0, 10).forEach(e => console.log(`  ${e}`));
  if (testResults.numberPatternErrors.length > 10) {
    console.log(`  ... 외 ${testResults.numberPatternErrors.length - 10}개\n`);
  }
}

console.log('========================================');
console.log('  데이터 무결성 검증 결과');
console.log('========================================');
if (testResults.dataIntegrityErrors.length === 0) {
  console.log('✅ 모든 데이터 연결이 정상입니다.\n');
} else {
  console.log(`❌ ${testResults.dataIntegrityErrors.length}개 오류 발견:\n`);
  testResults.dataIntegrityErrors.forEach(e => console.log(`  ${e}`));
}

console.log('========================================');
console.log('  비즈니스 로직 검증 결과');
console.log('========================================');
if (testResults.businessLogicErrors.length === 0) {
  console.log('✅ 모든 비즈니스 로직이 정상입니다.\n');
} else {
  console.log(`❌ ${testResults.businessLogicErrors.length}개 오류 발견:\n`);
  testResults.businessLogicErrors.forEach(e => console.log(`  ${e}`));
}

console.log('========================================');
console.log('  UX/사용성 개선점');
console.log('========================================\n');

const uxByPriority = {
  high: testResults.uxIssues.filter(i => i.severity === 'high'),
  medium: testResults.uxIssues.filter(i => i.severity === 'medium'),
  low: testResults.uxIssues.filter(i => i.severity === 'low'),
};

console.log('🔴 높은 우선순위:');
uxByPriority.high.forEach((issue, idx) => {
  console.log(`  ${idx + 1}. [${issue.category}] ${issue.issue}`);
  console.log(`     → 개선안: ${issue.suggestion}\n`);
});

console.log('🟡 중간 우선순위:');
uxByPriority.medium.forEach((issue, idx) => {
  console.log(`  ${idx + 1}. [${issue.category}] ${issue.issue}`);
  console.log(`     → 개선안: ${issue.suggestion}\n`);
});

console.log('🟢 낮은 우선순위:');
uxByPriority.low.forEach((issue, idx) => {
  console.log(`  ${idx + 1}. [${issue.category}] ${issue.issue}`);
  console.log(`     → 개선안: ${issue.suggestion}\n`);
});

console.log('========================================');
console.log('  종합 분석');
console.log('========================================\n');

const totalIssues = testResults.numberPatternErrors.length +
                   testResults.dataIntegrityErrors.length +
                   testResults.businessLogicErrors.length;

if (totalIssues === 0) {
  console.log('✅ 핵심 로직 테스트 통과! 모든 번호 체계와 비즈니스 로직이 정상 동작합니다.\n');
} else {
  console.log(`⚠️ ${totalIssues}개의 기술적 이슈가 발견되었습니다.\n`);
}

console.log(`📋 UX 개선점: ${testResults.uxIssues.length}개 도출`);
console.log(`   - 높음: ${uxByPriority.high.length}개`);
console.log(`   - 중간: ${uxByPriority.medium.length}개`);
console.log(`   - 낮음: ${uxByPriority.low.length}개\n`);

// JSON 결과 저장
const fs = require('fs');
fs.writeFileSync('test-results.json', JSON.stringify(testResults, null, 2));
console.log('📁 상세 결과가 test-results.json에 저장되었습니다.\n');
