// 원가계산 로직 설정
// 상용 MES 대비 개선사항 Phase 3

/**
 * ═══════════════════════════════════════════════════════════════════
 * 원가계산 (Cost Calculation) 시스템
 * ═══════════════════════════════════════════════════════════════════
 *
 * 목적: 제품별/수주별 정확한 원가 계산 및 분석
 *       - 재료비 계산 (직접재료비 + 간접재료비)
 *       - 노무비 계산 (직접노무비 + 간접노무비)
 *       - 경비 계산 (제조경비 + 판매관리비)
 *       - 원가 분석 및 개선점 도출
 *
 * ═══════════════════════════════════════════════════════════════════
 */

// 원가 구분 (Cost Elements)
export const costElements = {
  // 직접비 (Direct Costs)
  DIRECT_MATERIAL: {
    code: 'DIRECT_MATERIAL',
    name: '직접재료비',
    category: 'MATERIAL',
    type: 'DIRECT',
    description: '제품 생산에 직접 투입되는 주요 원재료비',
    examples: ['철판', '코일', '원단', '구매부품'],
  },
  DIRECT_LABOR: {
    code: 'DIRECT_LABOR',
    name: '직접노무비',
    category: 'LABOR',
    type: 'DIRECT',
    description: '제품 생산에 직접 종사하는 작업자의 인건비',
    examples: ['생산직 급여', '생산직 상여금', '시간외수당'],
  },
  DIRECT_EXPENSE: {
    code: 'DIRECT_EXPENSE',
    name: '직접경비',
    category: 'EXPENSE',
    type: 'DIRECT',
    description: '제품 생산에 직접 소요되는 경비',
    examples: ['외주가공비', '특허권사용료', '설계비'],
  },

  // 간접비 (Indirect Costs / Overhead)
  INDIRECT_MATERIAL: {
    code: 'INDIRECT_MATERIAL',
    name: '간접재료비',
    category: 'MATERIAL',
    type: 'INDIRECT',
    description: '제품 생산에 간접적으로 소요되는 재료비',
    examples: ['소모품', '윤활유', '포장재', '보조재료'],
  },
  INDIRECT_LABOR: {
    code: 'INDIRECT_LABOR',
    name: '간접노무비',
    category: 'LABOR',
    type: 'INDIRECT',
    description: '생산 지원 인력의 인건비',
    examples: ['관리직 급여', '품질관리 인건비', '생산관리 인건비'],
  },
  MANUFACTURING_OVERHEAD: {
    code: 'MANUFACTURING_OVERHEAD',
    name: '제조간접비',
    category: 'EXPENSE',
    type: 'INDIRECT',
    description: '제조 활동 관련 간접 비용',
    examples: ['감가상각비', '수선비', '전력비', '보험료'],
  },
  SGA: {
    code: 'SGA',
    name: '판매관리비',
    fullName: 'Selling, General & Administrative',
    category: 'EXPENSE',
    type: 'PERIOD',
    description: '판매 및 일반관리 활동 관련 비용',
    examples: ['영업비', '광고비', '일반관리비', '연구개발비'],
  },
};

// 원가 계산 단위
export const costingMethods = {
  JOB_ORDER: {
    code: 'JOB_ORDER',
    name: '개별원가계산',
    description: '수주별/작업지시별 원가 집계',
    suitable: ['주문생산', '프로젝트', '다품종소량'],
  },
  PROCESS: {
    code: 'PROCESS',
    name: '공정별원가계산',
    description: '공정별 원가 집계 후 배분',
    suitable: ['대량생산', '연속생산'],
  },
  ACTIVITY_BASED: {
    code: 'ACTIVITY_BASED',
    name: '활동기준원가계산 (ABC)',
    description: '활동 단위로 간접비 배분',
    suitable: ['복잡한 제품', '다양한 활동'],
  },
};

// 원가 배부 기준
export const allocationBases = {
  DIRECT_LABOR_HOURS: {
    code: 'DIRECT_LABOR_HOURS',
    name: '직접노동시간',
    description: '직접 작업자의 투입 시간 기준',
    unit: '시간',
  },
  MACHINE_HOURS: {
    code: 'MACHINE_HOURS',
    name: '기계시간',
    description: '설비 가동 시간 기준',
    unit: '시간',
  },
  DIRECT_MATERIAL_COST: {
    code: 'DIRECT_MATERIAL_COST',
    name: '직접재료비',
    description: '직접재료비 금액 기준',
    unit: '원',
  },
  PRODUCTION_QUANTITY: {
    code: 'PRODUCTION_QUANTITY',
    name: '생산수량',
    description: '생산된 수량 기준',
    unit: 'EA',
  },
  FLOOR_SPACE: {
    code: 'FLOOR_SPACE',
    name: '점유면적',
    description: '작업 공간 면적 기준',
    unit: 'm²',
  },
};

// 공정별 표준 원가 (예시)
export const standardCostByProcess = {
  SCREEN: {
    processCode: 'SCREEN',
    processName: '스크린',
    laborRatePerHour: 25000,       // 시간당 노무비
    overheadRatePerHour: 15000,    // 시간당 제조간접비
    standardHoursPerUnit: 2.5,     // 단위당 표준 시간
    yieldRate: 0.98,               // 수율
  },
  SLAT: {
    processCode: 'SLAT',
    processName: '슬랫',
    laborRatePerHour: 25000,
    overheadRatePerHour: 18000,
    standardHoursPerUnit: 3.0,
    yieldRate: 0.97,
  },
  FOLD: {
    processCode: 'FOLD',
    processName: '절곡',
    laborRatePerHour: 28000,
    overheadRatePerHour: 20000,
    standardHoursPerUnit: 1.5,
    yieldRate: 0.99,
  },
  ASSEMBLY: {
    processCode: 'ASSEMBLY',
    processName: '조립',
    laborRatePerHour: 22000,
    overheadRatePerHour: 12000,
    standardHoursPerUnit: 4.0,
    yieldRate: 0.99,
  },
};

// 원가계산서 양식
export const costSheetTemplate = {
  sections: [
    {
      id: 'material',
      name: '재료비',
      items: [
        { code: 'DIRECT_MATERIAL', name: '직접재료비' },
        { code: 'INDIRECT_MATERIAL', name: '간접재료비' },
      ],
      subtotal: '재료비 계',
    },
    {
      id: 'labor',
      name: '노무비',
      items: [
        { code: 'DIRECT_LABOR', name: '직접노무비' },
        { code: 'INDIRECT_LABOR', name: '간접노무비' },
      ],
      subtotal: '노무비 계',
    },
    {
      id: 'expense',
      name: '경비',
      items: [
        { code: 'DIRECT_EXPENSE', name: '직접경비' },
        { code: 'MANUFACTURING_OVERHEAD', name: '제조간접비' },
      ],
      subtotal: '경비 계',
    },
  ],
  totals: [
    { code: 'MANUFACTURING_COST', name: '제조원가', formula: '재료비 + 노무비 + 경비' },
    { code: 'SGA', name: '판매관리비', rateBase: 'MANUFACTURING_COST', rate: 0.1 },
    { code: 'TOTAL_COST', name: '총원가', formula: '제조원가 + 판매관리비' },
  ],
};

/**
 * 재료비 계산
 * @param {Array} materials - 투입 자재 목록 [{ itemCode, quantity, unitPrice }]
 * @returns {object} 재료비 계산 결과
 */
export const calculateMaterialCost = (materials) => {
  let directMaterial = 0;
  let indirectMaterial = 0;

  materials.forEach(mat => {
    const cost = (mat.quantity || 0) * (mat.unitPrice || 0);
    if (mat.isIndirect) {
      indirectMaterial += cost;
    } else {
      directMaterial += cost;
    }
  });

  return {
    directMaterial,
    indirectMaterial,
    totalMaterial: directMaterial + indirectMaterial,
    breakdown: materials.map(mat => ({
      itemCode: mat.itemCode,
      itemName: mat.itemName,
      quantity: mat.quantity,
      unitPrice: mat.unitPrice,
      amount: (mat.quantity || 0) * (mat.unitPrice || 0),
      isIndirect: mat.isIndirect || false,
    })),
  };
};

/**
 * 노무비 계산
 * @param {Array} laborRecords - 작업 시간 기록 [{ workerType, hours, rate }]
 * @returns {object} 노무비 계산 결과
 */
export const calculateLaborCost = (laborRecords) => {
  let directLabor = 0;
  let indirectLabor = 0;

  laborRecords.forEach(record => {
    const cost = (record.hours || 0) * (record.rate || 0);
    if (record.isIndirect) {
      indirectLabor += cost;
    } else {
      directLabor += cost;
    }
  });

  return {
    directLabor,
    indirectLabor,
    totalLabor: directLabor + indirectLabor,
    totalHours: laborRecords.reduce((sum, r) => sum + (r.hours || 0), 0),
  };
};

/**
 * 제조간접비 배부
 * @param {number} totalOverhead - 총 제조간접비
 * @param {string} allocationBase - 배부 기준
 * @param {Array} products - 제품별 배부 기준 데이터
 * @returns {Array} 제품별 배부 결과
 */
export const allocateOverhead = (totalOverhead, allocationBase, products) => {
  // 총 배부 기준 계산
  const totalBase = products.reduce((sum, p) => sum + (p[allocationBase] || 0), 0);

  if (totalBase === 0) {
    return products.map(p => ({
      ...p,
      allocatedOverhead: 0,
      allocationRate: 0,
    }));
  }

  // 배부율 계산
  const allocationRate = totalOverhead / totalBase;

  // 제품별 배부
  return products.map(p => ({
    ...p,
    allocatedOverhead: Math.round((p[allocationBase] || 0) * allocationRate),
    allocationRate,
    baseValue: p[allocationBase] || 0,
  }));
};

/**
 * 수주별 원가 계산
 * @param {object} order - 수주 정보
 * @param {object} costData - 원가 데이터 { materials, labor, overhead }
 * @returns {object} 원가계산서
 */
export const calculateOrderCost = (order, costData) => {
  const { materials = [], laborRecords = [], overheadItems = [] } = costData;

  // 재료비 계산
  const materialCost = calculateMaterialCost(materials);

  // 노무비 계산
  const laborCost = calculateLaborCost(laborRecords);

  // 경비 계산
  let directExpense = 0;
  let manufacturingOverhead = 0;

  overheadItems.forEach(item => {
    if (item.isDirect) {
      directExpense += item.amount || 0;
    } else {
      manufacturingOverhead += item.amount || 0;
    }
  });

  // 제조원가 계산
  const manufacturingCost =
    materialCost.totalMaterial +
    laborCost.totalLabor +
    directExpense +
    manufacturingOverhead;

  // 판매관리비 (제조원가의 10%)
  const sgaRate = 0.10;
  const sga = Math.round(manufacturingCost * sgaRate);

  // 총원가
  const totalCost = manufacturingCost + sga;

  // 수량으로 나눈 단위원가
  const quantity = order.quantity || 1;
  const unitCost = Math.round(totalCost / quantity);

  // 원가 구성비 계산
  const composition = {
    materialRate: totalCost > 0 ? Math.round(materialCost.totalMaterial / totalCost * 1000) / 10 : 0,
    laborRate: totalCost > 0 ? Math.round(laborCost.totalLabor / totalCost * 1000) / 10 : 0,
    expenseRate: totalCost > 0 ? Math.round((directExpense + manufacturingOverhead) / totalCost * 1000) / 10 : 0,
    sgaRate: totalCost > 0 ? Math.round(sga / totalCost * 1000) / 10 : 0,
  };

  return {
    orderNo: order.orderNo,
    productName: order.productName,
    quantity,
    calculatedAt: new Date().toISOString(),
    costBreakdown: {
      // 재료비
      directMaterial: materialCost.directMaterial,
      indirectMaterial: materialCost.indirectMaterial,
      totalMaterial: materialCost.totalMaterial,
      // 노무비
      directLabor: laborCost.directLabor,
      indirectLabor: laborCost.indirectLabor,
      totalLabor: laborCost.totalLabor,
      // 경비
      directExpense,
      manufacturingOverhead,
      totalExpense: directExpense + manufacturingOverhead,
    },
    // 원가 합계
    manufacturingCost,
    sga,
    totalCost,
    unitCost,
    // 분석
    composition,
    profitAnalysis: order.sellingPrice ? {
      sellingPrice: order.sellingPrice,
      profit: order.sellingPrice - unitCost,
      profitRate: Math.round((order.sellingPrice - unitCost) / order.sellingPrice * 1000) / 10,
    } : null,
  };
};

/**
 * 표준원가 vs 실제원가 차이 분석
 * @param {object} standardCost - 표준원가
 * @param {object} actualCost - 실제원가
 * @returns {object} 차이 분석 결과
 */
export const analyzeVariance = (standardCost, actualCost) => {
  const variances = {
    material: {
      standard: standardCost.totalMaterial || 0,
      actual: actualCost.totalMaterial || 0,
      variance: (standardCost.totalMaterial || 0) - (actualCost.totalMaterial || 0),
      rate: standardCost.totalMaterial > 0
        ? Math.round(((standardCost.totalMaterial - actualCost.totalMaterial) / standardCost.totalMaterial) * 1000) / 10
        : 0,
      status: null,
    },
    labor: {
      standard: standardCost.totalLabor || 0,
      actual: actualCost.totalLabor || 0,
      variance: (standardCost.totalLabor || 0) - (actualCost.totalLabor || 0),
      rate: standardCost.totalLabor > 0
        ? Math.round(((standardCost.totalLabor - actualCost.totalLabor) / standardCost.totalLabor) * 1000) / 10
        : 0,
      status: null,
    },
    overhead: {
      standard: standardCost.totalExpense || 0,
      actual: actualCost.totalExpense || 0,
      variance: (standardCost.totalExpense || 0) - (actualCost.totalExpense || 0),
      rate: standardCost.totalExpense > 0
        ? Math.round(((standardCost.totalExpense - actualCost.totalExpense) / standardCost.totalExpense) * 1000) / 10
        : 0,
      status: null,
    },
    total: {
      standard: standardCost.totalCost || 0,
      actual: actualCost.totalCost || 0,
      variance: (standardCost.totalCost || 0) - (actualCost.totalCost || 0),
      rate: standardCost.totalCost > 0
        ? Math.round(((standardCost.totalCost - actualCost.totalCost) / standardCost.totalCost) * 1000) / 10
        : 0,
      status: null,
    },
  };

  // 상태 판정 (양수: 유리, 음수: 불리)
  Object.keys(variances).forEach(key => {
    const v = variances[key];
    if (v.variance > 0) {
      v.status = { code: 'FAVORABLE', name: '유리', color: 'text-green-600' };
    } else if (v.variance < 0) {
      v.status = { code: 'UNFAVORABLE', name: '불리', color: 'text-red-600' };
    } else {
      v.status = { code: 'NEUTRAL', name: '동일', color: 'text-gray-600' };
    }
  });

  return variances;
};

/**
 * 손익분기점 계산
 * @param {number} fixedCost - 고정비
 * @param {number} variableCostPerUnit - 단위당 변동비
 * @param {number} sellingPricePerUnit - 단위당 판매가
 * @returns {object} 손익분기점 분석
 */
export const calculateBreakEvenPoint = (fixedCost, variableCostPerUnit, sellingPricePerUnit) => {
  const contributionMargin = sellingPricePerUnit - variableCostPerUnit;
  const contributionRatio = sellingPricePerUnit > 0 ? contributionMargin / sellingPricePerUnit : 0;

  const breakEvenQuantity = contributionMargin > 0 ? Math.ceil(fixedCost / contributionMargin) : Infinity;
  const breakEvenSales = contributionRatio > 0 ? Math.round(fixedCost / contributionRatio) : Infinity;

  return {
    breakEvenQuantity,
    breakEvenSales,
    contributionMargin,
    contributionRatio: Math.round(contributionRatio * 1000) / 10,
    marginOfSafety: null, // 실제 판매량 대비 계산 필요
  };
};

/**
 * 원가 트렌드 분석
 * @param {Array} historicalCosts - 과거 원가 데이터
 * @returns {object} 트렌드 분석 결과
 */
export const analyzeCostTrend = (historicalCosts) => {
  if (historicalCosts.length < 2) {
    return { trend: 'insufficient_data', message: '데이터 부족' };
  }

  const recentCosts = historicalCosts.slice(-6);
  const avgCost = recentCosts.reduce((sum, c) => sum + (c.totalCost || 0), 0) / recentCosts.length;
  const firstHalf = recentCosts.slice(0, 3);
  const secondHalf = recentCosts.slice(-3);

  const firstHalfAvg = firstHalf.reduce((sum, c) => sum + (c.totalCost || 0), 0) / firstHalf.length;
  const secondHalfAvg = secondHalf.reduce((sum, c) => sum + (c.totalCost || 0), 0) / secondHalf.length;

  const changeRate = firstHalfAvg > 0
    ? Math.round((secondHalfAvg - firstHalfAvg) / firstHalfAvg * 1000) / 10
    : 0;

  let trend, recommendation;
  if (changeRate > 5) {
    trend = 'increasing';
    recommendation = '원가 상승 추세. 재료비/노무비 절감 방안 검토 필요';
  } else if (changeRate < -5) {
    trend = 'decreasing';
    recommendation = '원가 절감 추세. 현재 개선 활동 유지';
  } else {
    trend = 'stable';
    recommendation = '원가 안정 추세. 지속적인 모니터링 필요';
  }

  return {
    trend,
    changeRate,
    avgCost: Math.round(avgCost),
    recommendation,
    dataPoints: historicalCosts.length,
  };
};

export default {
  costElements,
  costingMethods,
  allocationBases,
  standardCostByProcess,
  costSheetTemplate,
  calculateMaterialCost,
  calculateLaborCost,
  allocateOverhead,
  calculateOrderCost,
  analyzeVariance,
  calculateBreakEvenPoint,
  analyzeCostTrend,
};
