import { useMemo } from 'react';
import type { EstimateDetailItem, PriceAdjustmentData } from '../types';

interface CalculatedValues {
  area: number;
  weight: number;
  steelScreen: number;
  caulking: number;
  rail: number;
  bottom: number;
  boxReinforce: number;
  shaft: number;
  painting: number;
  motor: number;
  controller: number;
  widthConst: number;
  heightConst: number;
  unitPrice: number;
  expenseRate: number;
  expense: number;
  quantity: number;
  cost: number;
  costExecution: number;
  marginCost: number;
  marginCostExecution: number;
  expenseExecution: number;
}

// appliedPrices 타입 (전체 적용 시 복사된 가격)
export interface AppliedPrices {
  caulking: number;
  rail: number;
  bottom: number;
  boxReinforce: number;
  shaft: number;
  painting: number;
  motor: number;
  controller: number;
}

// 기본 단가 상수
const DEFAULT_PRICES = {
  caulking: 9500,
  rail: 85000,
  bottom: 113000,
  boxReinforce: 11000,
  shaft: 14000,
  painting: 0,
  motor: 0,
  controller: 0,
};

/**
 * 기본 계산값 생성 (가로/세로 기반)
 * 사용자가 수정하지 않았을 때 사용되는 자동 계산 값
 */
export function getDefaultCalculatedValues(
  width: number,
  height: number,
  priceAdjustmentData: PriceAdjustmentData,
  useAdjustedPrice: boolean
) {
  const caulkingPrice = useAdjustedPrice ? priceAdjustmentData.caulking.adjustedPrice : DEFAULT_PRICES.caulking;
  const railPrice = useAdjustedPrice ? priceAdjustmentData.rail.adjustedPrice : DEFAULT_PRICES.rail;
  const bottomPrice = useAdjustedPrice ? priceAdjustmentData.bottom.adjustedPrice : DEFAULT_PRICES.bottom;
  const boxReinforcePrice = useAdjustedPrice ? priceAdjustmentData.boxReinforce.adjustedPrice : DEFAULT_PRICES.boxReinforce;
  const shaftPrice = useAdjustedPrice ? priceAdjustmentData.shaft.adjustedPrice : DEFAULT_PRICES.shaft;

  // 06. 면적: (가로*0.16)*(세로*0.5)
  const area = (width * 0.16) * (height * 0.5);
  // 05. 무게: 면적*25
  const weight = area * 25;
  // 07. 철제,스크린: 면적*47500
  const steelScreen = Math.round(area * 47500);
  // 08. 코킹: (세로*4)*조정단가
  const caulking = Math.round((height * 4) * caulkingPrice);
  // 09. 레일: (세로*0.2)*조정단가
  const rail = Math.round((height * 0.2) * railPrice);
  // 10. 하장: 가로*조정단가
  const bottom = Math.round(width * bottomPrice);
  // 11. 박스+보강: 가로*조정단가
  const boxReinforce = Math.round(width * boxReinforcePrice);
  // 12. 샤프트: 가로*조정단가
  const shaft = Math.round(width * shaftPrice);

  return { area, weight, steelScreen, caulking, rail, bottom, boxReinforce, shaft };
}

/**
 * 개별 견적 상세 항목의 계산값 반환
 * calcXxx 필드가 있으면 사용자 입력값, 없으면 자동 계산값 사용
 */
export function calculateItemValues(
  item: EstimateDetailItem,
  priceAdjustmentData: PriceAdjustmentData,
  useAdjustedPrice: boolean
): CalculatedValues {
  // 조정단가 사용 여부에 따른 단가 선택
  const paintingPrice = useAdjustedPrice ? priceAdjustmentData.painting.adjustedPrice : DEFAULT_PRICES.painting;
  const motorPrice = useAdjustedPrice ? priceAdjustmentData.motor.adjustedPrice : DEFAULT_PRICES.motor;
  const controllerPrice = useAdjustedPrice ? priceAdjustmentData.controller.adjustedPrice : DEFAULT_PRICES.controller;

  // 기본 계산값 가져오기
  const defaultCalc = getDefaultCalculatedValues(
    item.width,
    item.height,
    priceAdjustmentData,
    useAdjustedPrice
  );

  // 사용자 입력값이 있으면 사용, 없으면 자동 계산값 사용
  const area = item.calcArea ?? defaultCalc.area;
  const weight = item.calcWeight ?? defaultCalc.weight;
  const steelScreen = item.calcSteelScreen ?? defaultCalc.steelScreen;
  const caulking = item.calcCaulking ?? defaultCalc.caulking;
  const rail = item.calcRail ?? defaultCalc.rail;
  const bottom = item.calcBottom ?? defaultCalc.bottom;
  const boxReinforce = item.calcBoxReinforce ?? defaultCalc.boxReinforce;
  const shaft = item.calcShaft ?? defaultCalc.shaft;

  // 13~17: 셀렉트박스 (도장, 모터, 제어기, 가로시공비, 세로시공비)
  // 조정단가 적용 시 셀렉트 값 대신 조정단가 사용
  const painting = useAdjustedPrice && paintingPrice > 0 ? paintingPrice : (item.coating || 0);
  const motor = useAdjustedPrice && motorPrice > 0 ? motorPrice : (item.mounting || 0);
  const controller = useAdjustedPrice && controllerPrice > 0 ? controllerPrice : (item.controller || 0);
  const widthConst = item.widthConstruction || 0;
  const heightConst = item.heightConstruction || 0;

  // 18. 단가: (7)~(17)의 합 - 사용자 입력값이 있으면 사용
  const calculatedUnitPrice = steelScreen + caulking + rail + bottom + boxReinforce + shaft + painting + motor + controller + widthConst + heightConst;
  const unitPrice = item.calcUnitPrice ?? calculatedUnitPrice;

  // 19. 공과율: 입력값
  const expenseRate = item.expense || 0;

  // 20. 공과: 단가*공과율 - 사용자 입력값이 있으면 사용
  const calculatedExpense = Math.round(unitPrice * expenseRate);
  const expense = item.calcExpense ?? calculatedExpense;

  // 21. 수량
  const quantity = item.quantity || 1;
  // 22. 원가: 단가+공과*수량
  const cost = Math.round((unitPrice + expense) * quantity);
  // 23. 원가실행: (단가+공과)*수량
  const costExecution = Math.round((unitPrice + expense) * quantity);
  // 24. 마진원가: 단가*공과율*1.03
  const marginCost = Math.round(unitPrice * expenseRate * 1.03);
  // 25. 마진원가실행: 마진원가*수량
  const marginCostExecution = Math.round(marginCost * quantity);
  // 26. 공과실행: 공과*수량
  const expenseExecution = Math.round(expense * quantity);

  return {
    area,
    weight,
    steelScreen,
    caulking,
    rail,
    bottom,
    boxReinforce,
    shaft,
    painting,
    motor,
    controller,
    widthConst,
    heightConst,
    unitPrice,
    expenseRate,
    expense,
    quantity,
    cost,
    costExecution,
    marginCost,
    marginCostExecution,
    expenseExecution,
  };
}

interface TotalValues {
  weight: number;
  area: number;
  steelScreen: number;
  caulking: number;
  rail: number;
  bottom: number;
  boxReinforce: number;
  shaft: number;
  painting: number;
  motor: number;
  controller: number;
  widthConstruction: number;
  heightConstruction: number;
  unitPrice: number;
  expense: number;
  quantity: number;
  cost: number;
  costExecution: number;
  marginCost: number;
  marginCostExecution: number;
  expenseExecution: number;
}

/**
 * 모든 견적 상세 항목의 합계 계산
 */
export function calculateTotals(
  items: EstimateDetailItem[],
  priceAdjustmentData: PriceAdjustmentData,
  useAdjustedPrice: boolean
): TotalValues {
  return items.reduce(
    (acc, item) => {
      const values = calculateItemValues(item, priceAdjustmentData, useAdjustedPrice);
      return {
        weight: acc.weight + values.weight,
        area: acc.area + values.area,
        steelScreen: acc.steelScreen + values.steelScreen,
        caulking: acc.caulking + values.caulking,
        rail: acc.rail + values.rail,
        bottom: acc.bottom + values.bottom,
        boxReinforce: acc.boxReinforce + values.boxReinforce,
        shaft: acc.shaft + values.shaft,
        painting: acc.painting + values.painting,
        motor: acc.motor + values.motor,
        controller: acc.controller + values.controller,
        widthConstruction: acc.widthConstruction + values.widthConst,
        heightConstruction: acc.heightConstruction + values.heightConst,
        unitPrice: acc.unitPrice + values.unitPrice,
        expense: acc.expense + values.expense,
        quantity: acc.quantity + values.quantity,
        cost: acc.cost + values.cost,
        costExecution: acc.costExecution + values.costExecution,
        marginCost: acc.marginCost + values.marginCost,
        marginCostExecution: acc.marginCostExecution + values.marginCostExecution,
        expenseExecution: acc.expenseExecution + values.expenseExecution,
      };
    },
    {
      weight: 0,
      area: 0,
      steelScreen: 0,
      caulking: 0,
      rail: 0,
      bottom: 0,
      boxReinforce: 0,
      shaft: 0,
      painting: 0,
      motor: 0,
      controller: 0,
      widthConstruction: 0,
      heightConstruction: 0,
      unitPrice: 0,
      expense: 0,
      quantity: 0,
      cost: 0,
      costExecution: 0,
      marginCost: 0,
      marginCostExecution: 0,
      expenseExecution: 0,
    }
  );
}

/**
 * 견적 상세 테이블용 계산 훅
 */
export function useEstimateCalculations(
  items: EstimateDetailItem[],
  priceAdjustmentData: PriceAdjustmentData,
  useAdjustedPrice: boolean
) {
  const totals = useMemo(
    () => calculateTotals(items, priceAdjustmentData, useAdjustedPrice),
    [items, priceAdjustmentData, useAdjustedPrice]
  );

  return { totals, calculateItemValues };
}

// ============================================================
// appliedPrices 기반 계산 함수들 (priceAdjustmentData와 독립적)
// "전체 적용" 버튼 클릭 시점에 복사된 가격만 사용
// ============================================================

/**
 * 기본 계산값 생성 (개별 항목 조정단가 → appliedPrices → 기본단가 순으로 적용)
 *
 * 우선순위:
 * 1. 개별 항목의 adjustedXxx (선택 적용 버튼으로 설정)
 * 2. appliedPrices (전체 적용 버튼으로 설정)
 * 3. DEFAULT_PRICES (기본값)
 */
export function getDefaultCalculatedValuesWithApplied(
  width: number,
  height: number,
  appliedPrices: AppliedPrices | null,
  itemAdjusted?: {
    caulking?: number;
    rail?: number;
    bottom?: number;
    boxReinforce?: number;
    shaft?: number;
  }
) {
  // 우선순위: 개별 항목 조정단가 → 전체 적용 단가 → 기본 단가
  const caulkingPrice = itemAdjusted?.caulking ?? appliedPrices?.caulking ?? DEFAULT_PRICES.caulking;
  const railPrice = itemAdjusted?.rail ?? appliedPrices?.rail ?? DEFAULT_PRICES.rail;
  const bottomPrice = itemAdjusted?.bottom ?? appliedPrices?.bottom ?? DEFAULT_PRICES.bottom;
  const boxReinforcePrice = itemAdjusted?.boxReinforce ?? appliedPrices?.boxReinforce ?? DEFAULT_PRICES.boxReinforce;
  const shaftPrice = itemAdjusted?.shaft ?? appliedPrices?.shaft ?? DEFAULT_PRICES.shaft;

  // 06. 면적: (가로*0.16)*(세로*0.5)
  const area = (width * 0.16) * (height * 0.5);
  // 05. 무게: 면적*25
  const weight = area * 25;
  // 07. 철제,스크린: 면적*47500
  const steelScreen = Math.round(area * 47500);
  // 08. 코킹: (세로*4)*조정단가
  const caulking = Math.round((height * 4) * caulkingPrice);
  // 09. 레일: (세로*0.2)*조정단가
  const rail = Math.round((height * 0.2) * railPrice);
  // 10. 하장: 가로*조정단가
  const bottom = Math.round(width * bottomPrice);
  // 11. 박스+보강: 가로*조정단가
  const boxReinforce = Math.round(width * boxReinforcePrice);
  // 12. 샤프트: 가로*조정단가
  const shaft = Math.round(width * shaftPrice);

  return { area, weight, steelScreen, caulking, rail, bottom, boxReinforce, shaft };
}

/**
 * 개별 견적 상세 항목의 계산값 반환 (appliedPrices 기반)
 *
 * 우선순위:
 * 1. 개별 항목의 adjustedXxx (선택 적용 버튼으로 설정)
 * 2. appliedPrices (전체 적용 버튼으로 설정)
 * 3. DEFAULT_PRICES (기본값)
 */
export function calculateItemValuesWithApplied(
  item: EstimateDetailItem,
  appliedPrices: AppliedPrices | null
): CalculatedValues {
  // 개별 항목의 조정단가 (선택 적용 시 설정됨)
  const itemAdjusted = {
    caulking: item.adjustedCaulking,
    rail: item.adjustedRail,
    bottom: item.adjustedBottom,
    boxReinforce: item.adjustedBoxReinforce,
    shaft: item.adjustedShaft,
  };

  // 우선순위: 개별 항목 조정단가 → 전체 적용 단가 → 기본 단가
  const paintingPrice = item.adjustedPainting ?? appliedPrices?.painting ?? DEFAULT_PRICES.painting;
  const motorPrice = item.adjustedMotor ?? appliedPrices?.motor ?? DEFAULT_PRICES.motor;
  const controllerPrice = item.adjustedController ?? appliedPrices?.controller ?? DEFAULT_PRICES.controller;

  // 기본 계산값 가져오기 (개별 조정단가 우선 적용)
  const defaultCalc = getDefaultCalculatedValuesWithApplied(
    item.width,
    item.height,
    appliedPrices,
    itemAdjusted
  );

  // 사용자 입력값이 있으면 사용, 없으면 자동 계산값 사용
  const area = item.calcArea ?? defaultCalc.area;
  const weight = item.calcWeight ?? defaultCalc.weight;
  const steelScreen = item.calcSteelScreen ?? defaultCalc.steelScreen;
  const caulking = item.calcCaulking ?? defaultCalc.caulking;
  const rail = item.calcRail ?? defaultCalc.rail;
  const bottom = item.calcBottom ?? defaultCalc.bottom;
  const boxReinforce = item.calcBoxReinforce ?? defaultCalc.boxReinforce;
  const shaft = item.calcShaft ?? defaultCalc.shaft;

  // 13~17: 셀렉트박스 (도장, 모터, 제어기, 가로시공비, 세로시공비)
  // 우선순위: 개별 조정단가 → 전체 적용 단가 → 셀렉트박스 값
  const hasItemPainting = item.adjustedPainting !== undefined;
  const hasAppliedPainting = appliedPrices && appliedPrices.painting > 0;
  const painting = hasItemPainting ? paintingPrice : (hasAppliedPainting ? paintingPrice : (item.coating || 0));

  const hasItemMotor = item.adjustedMotor !== undefined;
  const hasAppliedMotor = appliedPrices && appliedPrices.motor > 0;
  const motor = hasItemMotor ? motorPrice : (hasAppliedMotor ? motorPrice : (item.mounting || 0));

  const hasItemController = item.adjustedController !== undefined;
  const hasAppliedController = appliedPrices && appliedPrices.controller > 0;
  const controller = hasItemController ? controllerPrice : (hasAppliedController ? controllerPrice : (item.controller || 0));

  const widthConst = item.widthConstruction || 0;
  const heightConst = item.heightConstruction || 0;

  // 18. 단가: (7)~(17)의 합 - 사용자 입력값이 있으면 사용
  const calculatedUnitPrice = steelScreen + caulking + rail + bottom + boxReinforce + shaft + painting + motor + controller + widthConst + heightConst;
  const unitPrice = item.calcUnitPrice ?? calculatedUnitPrice;

  // 19. 공과율: 입력값
  const expenseRate = item.expense || 0;

  // 20. 공과: 단가*공과율 - 사용자 입력값이 있으면 사용
  const calculatedExpense = Math.round(unitPrice * expenseRate);
  const expense = item.calcExpense ?? calculatedExpense;

  // 21. 수량
  const quantity = item.quantity || 1;
  // 22. 원가: 단가+공과*수량
  const cost = Math.round((unitPrice + expense) * quantity);
  // 23. 원가실행: (단가+공과)*수량
  const costExecution = Math.round((unitPrice + expense) * quantity);
  // 24. 마진원가: 단가*공과율*1.03
  const marginCost = Math.round(unitPrice * expenseRate * 1.03);
  // 25. 마진원가실행: 마진원가*수량
  const marginCostExecution = Math.round(marginCost * quantity);
  // 26. 공과실행: 공과*수량
  const expenseExecution = Math.round(expense * quantity);

  return {
    area,
    weight,
    steelScreen,
    caulking,
    rail,
    bottom,
    boxReinforce,
    shaft,
    painting,
    motor,
    controller,
    widthConst,
    heightConst,
    unitPrice,
    expenseRate,
    expense,
    quantity,
    cost,
    costExecution,
    marginCost,
    marginCostExecution,
    expenseExecution,
  };
}

/**
 * 모든 견적 상세 항목의 합계 계산 (appliedPrices 기반)
 * priceAdjustmentData 변경에 영향받지 않음
 */
export function calculateTotalsWithApplied(
  items: EstimateDetailItem[],
  appliedPrices: AppliedPrices | null
): TotalValues {
  return items.reduce(
    (acc, item) => {
      const values = calculateItemValuesWithApplied(item, appliedPrices);
      return {
        weight: acc.weight + values.weight,
        area: acc.area + values.area,
        steelScreen: acc.steelScreen + values.steelScreen,
        caulking: acc.caulking + values.caulking,
        rail: acc.rail + values.rail,
        bottom: acc.bottom + values.bottom,
        boxReinforce: acc.boxReinforce + values.boxReinforce,
        shaft: acc.shaft + values.shaft,
        painting: acc.painting + values.painting,
        motor: acc.motor + values.motor,
        controller: acc.controller + values.controller,
        widthConstruction: acc.widthConstruction + values.widthConst,
        heightConstruction: acc.heightConstruction + values.heightConst,
        unitPrice: acc.unitPrice + values.unitPrice,
        expense: acc.expense + values.expense,
        quantity: acc.quantity + values.quantity,
        cost: acc.cost + values.cost,
        costExecution: acc.costExecution + values.costExecution,
        marginCost: acc.marginCost + values.marginCost,
        marginCostExecution: acc.marginCostExecution + values.marginCostExecution,
        expenseExecution: acc.expenseExecution + values.expenseExecution,
      };
    },
    {
      weight: 0,
      area: 0,
      steelScreen: 0,
      caulking: 0,
      rail: 0,
      bottom: 0,
      boxReinforce: 0,
      shaft: 0,
      painting: 0,
      motor: 0,
      controller: 0,
      widthConstruction: 0,
      heightConstruction: 0,
      unitPrice: 0,
      expense: 0,
      quantity: 0,
      cost: 0,
      costExecution: 0,
      marginCost: 0,
      marginCostExecution: 0,
      expenseExecution: 0,
    }
  );
}