import { type InventoryItemLike, itemTrustState, TRUST_STATUS_THRESHOLDS } from "./trust.js";

export interface ReconciliationCandidate {
  itemId: string;
  displayName: string;
  quantity: number;
  unit: string;
  locationName: string;
  /** Prioritet: lägre = viktigare. */
  priority: number;
  reasons: ReconciliationReason[];
  /** Förslag baserat på planerade recept, förbrukningstakt etc. */
  suggestedAction: "exists" | "depleted" | "uncertain";
  suggestedQuantity?: number;
}

export type ReconciliationReason =
  | { kind: "planned_recipe"; recipeIds: string[] }
  | { kind: "expiring_soon"; daysLeft: number | null }
  | { kind: "high_value"; priceMinor: number }
  | { kind: "low_confidence"; confidence: number }
  | { kind: "stale_trust"; trustState: string }
  | { kind: "likely_depleted"; remainingDays: number };

export interface ReconciliationContext {
  /** Ingredienser som behövs i planerade recept under närmaste 7 dagarna. */
  plannedRecipeIngredientIds: Map<string, string[]>;
  /** Utgångsdatum per vara-id. */
  daysLeftByItemId: Map<string, number | null>;
  /** Estimerad förbrukning per dygn per vara (enkel heuristik). */
  dailyConsumptionRate: Map<string, number>;
  /** Pris i minor units per vara. */
  priceMinorByItemId: Map<string, number>;
}

const MS_PER_DAY = 86_400_000;

/**
 * Bygg en prioriterad lista över varor som behöver en snabb avstämning.
 *
 * Prioritet (lägre = viktigare, §5.4):
 * 1. Behövs i planerade recept (inom 7 dagar)
 * 2. Snart utgår
 * 3. Högt ekonomiskt värde
 * 4. Låg confidence / stale trust
 * 5. Borde vara slut enligt förbrukningstakt
 *
 * Deterministisk, UTC, alltid samma svar för samma input.
 */
export function buildReconciliationCandidates(
  items: Array<InventoryItemLike & { id: string; displayName: string; unit: string; locationName: string }>,
  context: ReconciliationContext,
  now: Date = new Date(),
  maxItems = 15,
): ReconciliationCandidate[] {
  const candidates: ReconciliationCandidate[] = [];

  for (const item of items) {
    if ((item.quantity <= 0 && item.depletedAt) || item.depletedAt) continue;

    const reasons: ReconciliationReason[] = [];
    let priorityPenalty = 0;

    // 1. Planerade recept
    const recipeIds = context.plannedRecipeIngredientIds.get(item.id) ?? [];
    if (recipeIds.length > 0) {
      reasons.push({ kind: "planned_recipe", recipeIds });
      priorityPenalty += 10_000;
    }

    // 2. Snart utgår
    const daysLeft = context.daysLeftByItemId.get(item.id) ?? null;
    if (daysLeft != null && daysLeft <= 7) {
      reasons.push({ kind: "expiring_soon", daysLeft });
      priorityPenalty += 8_000 - Math.min(7, Math.max(0, daysLeft)) * 1_000;
    }

    // 3. Ekonomiskt värde
    const priceMinor = context.priceMinorByItemId.get(item.id) ?? 0;
    if (priceMinor > 0) {
      reasons.push({ kind: "high_value", priceMinor });
      priorityPenalty += Math.min(5_000, Math.floor(priceMinor / 10));
    }

    // 4. Låg confidence / stale trust
    if (item.confidence < 0.6) {
      reasons.push({ kind: "low_confidence", confidence: item.confidence });
      priorityPenalty += 3_000;
    }
    const trust = itemTrustState(item, now, undefined);
    if (trust === "stale" || trust === "decaying") {
      reasons.push({ kind: "stale_trust", trustState: trust });
      priorityPenalty += trust === "stale" ? 4_000 : 2_000;
    }

    // 5. Borde vara slut enligt förbrukningstakt
    const dailyRate = context.dailyConsumptionRate.get(item.id) ?? 0;
    if (dailyRate > 0 && item.quantity > 0) {
      const remainingDays = item.quantity / dailyRate;
      if (remainingDays < 3) {
        reasons.push({ kind: "likely_depleted", remainingDays });
        priorityPenalty += 2_500 - Math.min(2, Math.floor(remainingDays)) * 800;
      }
    }

    if (reasons.length === 0) continue;

    // Förslag
    let suggestedAction: ReconciliationCandidate["suggestedAction"] = "uncertain";
    let suggestedQuantity: number | undefined;
    if (dailyRate > 0 && item.quantity > 0) {
      const remainingDays = item.quantity / dailyRate;
      if (remainingDays < 0.5) {
        suggestedAction = "depleted";
      } else {
        suggestedQuantity = Math.max(0, Math.round(item.quantity * 10) / 10);
        suggestedAction = "exists";
      }
    } else if (trust === "trusted") {
      suggestedAction = "exists";
    }

    candidates.push({
      itemId: item.id,
      displayName: item.displayName,
      quantity: item.quantity,
      unit: item.unit,
      locationName: item.locationName,
      priority: -priorityPenalty,
      reasons,
      suggestedAction,
      suggestedQuantity,
    });
  }

  candidates.sort((a, b) => {
    if (a.priority !== b.priority) return a.priority - b.priority;
    return a.displayName.localeCompare(b.displayName, "sv");
  });

  return candidates.slice(0, maxItems);
}
