import type { PromoCode, PurchaseContext } from "@/types";
import { promoCodes as seed } from "@/features/_mock/extra";

let store = [...seed];

export type PromoApplyResult =
  | { ok: true; code: PromoCode; discountAmount: number; message?: string }
  | { ok: false; reason: "not_found" | "disabled" | "expired" | "usage_limit" | "not_eligible" | "min_order" | "user_limit"; message: string };

export const promoService = {
  async listAdmin() { return [...store]; },
  async get(code: string) { return store.find((c) => c.code.toLowerCase() === code.toLowerCase()) ?? null; },
  async apply(code: string, ctx: PurchaseContext, subtotal: number): Promise<PromoApplyResult> {
    const c = await this.get(code);
    if (!c) return { ok: false, reason: "not_found", message: "Code not found" };
    if (!c.enabled) return { ok: false, reason: "disabled", message: "This code is disabled" };
    if (c.endsAt && new Date(c.endsAt) < new Date()) return { ok: false, reason: "expired", message: "This code has expired" };
    if (c.usageLimit && c.usedCount >= c.usageLimit) return { ok: false, reason: "usage_limit", message: "Usage limit reached" };
    if (c.minOrder && subtotal < c.minOrder) return { ok: false, reason: "min_order", message: `Minimum order $${c.minOrder}` };
    if (c.scope === "category" && ctx.metadata?.category !== c.scopeValue) return { ok: false, reason: "not_eligible", message: "Not eligible for this item" };
    if (c.scope === "server" && ctx.serverId !== c.scopeValue) return { ok: false, reason: "not_eligible", message: "Not eligible for this server" };
    if (c.scope === "subscription" && (ctx.purchaseType !== "subscription" || (c.scopeValue && ctx.metadata?.planId !== c.scopeValue))) return { ok: false, reason: "not_eligible", message: "Not eligible for this plan" };
    let discount = 0;
    if (c.discountType === "percentage") discount = +(subtotal * c.discountValue / 100).toFixed(2);
    else if (c.discountType === "fixed") discount = Math.min(c.discountValue, subtotal);
    return { ok: true, code: c, discountAmount: discount, message: c.description };
  },
  async create(data: Omit<PromoCode, "id" | "usedCount" | "revenue">) {
    const c: PromoCode = { ...data, id: `pc-${Date.now()}`, usedCount: 0, revenue: 0 };
    store.push(c); return c;
  },
  async update(id: string, patch: Partial<PromoCode>) {
    store = store.map((c) => c.id === id ? { ...c, ...patch } : c);
    return store.find((c) => c.id === id)!;
  },
  async remove(id: string) { store = store.filter((c) => c.id !== id); },
  async duplicate(id: string) {
    const orig = store.find((c) => c.id === id);
    if (!orig) return null;
    const copy: PromoCode = { ...orig, id: `pc-${Date.now()}`, code: `${orig.code}-COPY`, usedCount: 0, revenue: 0 };
    store.push(copy); return copy;
  },
};