import type { FinanceCostFilterState } from '../../types';

/**
 * 文件职责：成本管理页面纯函数与格式化工具。
 */
import type {
  FinanceCostCategoryCode,
  FinanceCostEntryCategoryDto,
  SaveFinanceCostCategoryPayload,
} from '#/api/finance/cost';

/** 解析为有限数字。 */
export function toFiniteNumber(value: unknown, fallback = 0) {
  const normalized = Number(value);
  return Number.isFinite(normalized) ? normalized : fallback;
}

/** 金额保留两位小数。 */
export function roundAmount(value: unknown) {
  const normalized = toFiniteNumber(value, 0);
  return Math.round(normalized * 100) / 100;
}

/** 货币格式化。 */
export function formatCurrency(value: unknown) {
  return new Intl.NumberFormat('zh-CN', {
    style: 'currency',
    currency: 'CNY',
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  }).format(roundAmount(value));
}

/** 百分比格式化。 */
export function formatPercent(value: unknown) {
  return `${roundAmount(value).toFixed(2)}%`;
}

/** 获取当前月份（yyyy-MM）。 */
export function getCurrentMonthString() {
  const now = new Date();
  const month = `${now.getMonth() + 1}`.padStart(2, '0');
  return `${now.getFullYear()}-${month}`;
}

/** 月份字符串转标题文本。 */
export function formatMonthTitle(month: string) {
  const normalized = month.trim();
  const [year, monthValue] = normalized.split('-');
  if (!year || !monthValue) {
    return normalized || '--';
  }
  return `${year}年${Number(monthValue)}月`;
}

/** 月份位移。 */
export function shiftMonth(month: string, offset: number) {
  const parsed = parseMonth(month);
  if (!parsed) {
    return getCurrentMonthString();
  }
  parsed.setMonth(parsed.getMonth() + offset);
  return formatMonth(parsed);
}

/** 构建查询作用域参数。 */
export function buildScopeQueryPayload(filters: FinanceCostFilterState) {
  return {
    dimension: filters.dimension,
    month: filters.month || undefined,
    storeId:
      filters.dimension === 'store' ? filters.storeId || undefined : undefined,
  };
}

/** 将 API 分类数据映射为页面视图模型。 */
export function mapCategoriesToViewModel(
  categories: FinanceCostEntryCategoryDto[],
  expandedMap: Map<FinanceCostCategoryCode, boolean>,
) {
  return (categories ?? []).map((item) => ({
    ...item,
    items: [...(item.items ?? [])],
    expanded: expandedMap.get(item.category) ?? false,
  }));
}

/** 计算分类总金额。 */
export function sumCategoryItems(
  category: Pick<FinanceCostEntryCategoryDto, 'category' | 'items'>,
) {
  let total = 0;
  for (const item of category.items ?? []) {
    if (category.category === 'labor') {
      const quantity = toFiniteNumber(item.quantity, 0);
      const unitPrice = toFiniteNumber(item.unitPrice, 0);
      total += roundAmount(quantity * unitPrice);
      continue;
    }
    total += roundAmount(item.amount);
  }
  return roundAmount(total);
}

/** 计算全部分类总成本。 */
export function sumAllCategoryTotal(categories: FinanceCostEntryCategoryDto[]) {
  let total = 0;
  for (const category of categories ?? []) {
    total += roundAmount(category.totalAmount);
  }
  return roundAmount(total);
}

/** 构建保存请求分类数组。 */
export function buildSaveCategoryPayload(
  categories: FinanceCostEntryCategoryDto[],
): SaveFinanceCostCategoryPayload[] {
  return (categories ?? []).map((category) => ({
    category: category.category,
    totalAmount: roundAmount(category.totalAmount),
    items: (category.items ?? []).map((item, index) => ({
      itemId: item.itemId,
      itemName: item.itemName.trim(),
      amount: roundAmount(item.amount),
      quantity:
        item.quantity === undefined ? undefined : roundAmount(item.quantity),
      unitPrice:
        item.unitPrice === undefined ? undefined : roundAmount(item.unitPrice),
      sortOrder: item.sortOrder > 0 ? item.sortOrder : index + 1,
    })),
  }));
}

function parseMonth(value: string) {
  const normalized = value.trim();
  const [year, month] = normalized.split('-');
  const yearValue = Number(year);
  const monthValue = Number(month);
  if (
    !Number.isInteger(yearValue) ||
    !Number.isInteger(monthValue) ||
    monthValue < 1 ||
    monthValue > 12
  ) {
    return null;
  }
  return new Date(yearValue, monthValue - 1, 1);
}

function formatMonth(date: Date) {
  const year = date.getFullYear();
  const month = `${date.getMonth() + 1}`.padStart(2, '0');
  return `${year}-${month}`;
}
