import { mutation } from "../_generated/server";
import { v } from "convex/values";

/**
 * Create a new referral code
 */
export const createReferral = mutation({
  args: {
    userId: v.string(),
    code: v.string(),
    name: v.string(),
    description: v.optional(v.string()),
    rewardType: v.string(),
    rewardValue: v.number(),
    rewardCurrency: v.string(),
    maxUses: v.optional(v.number()),
    expiresAt: v.optional(v.number()),
    uses: v.optional(v.number()),
    conversions: v.optional(v.number()),
    rewardsIssued: v.optional(v.number()),
    status: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    const now = Date.now();
    const id = await ctx.db.insert("referrals", {
      userId: args.userId,
      code: args.code,
      name: args.name,
      description: args.description,
      rewardType: args.rewardType,
      rewardValue: args.rewardValue,
      rewardCurrency: args.rewardCurrency,
      maxUses: args.maxUses,
      expiresAt: args.expiresAt,
      uses: args.uses ?? 0,
      conversions: args.conversions ?? 0,
      rewardsIssued: args.rewardsIssued ?? 0,
      status: args.status ?? "active",
      createdAt: now,
      updatedAt: now,
    });
    return id;
  },
});

/**
 * Update a referral. Supports increment fields via special keys:
 * - conversions_increment, uses_increment, rewardsIssued_increment
 */
export const updateReferral = mutation({
  args: {
    id: v.string(),
    // Direct set fields
    name: v.optional(v.string()),
    description: v.optional(v.string()),
    rewardType: v.optional(v.string()),
    rewardValue: v.optional(v.number()),
    rewardCurrency: v.optional(v.string()),
    maxUses: v.optional(v.number()),
    expiresAt: v.optional(v.number()),
    status: v.optional(v.string()),
    lastConvertedAt: v.optional(v.number()),
    lastRewardAt: v.optional(v.number()),
    uses: v.optional(v.number()),
    conversions: v.optional(v.number()),
    rewardsIssued: v.optional(v.number()),
    // Increment fields
    uses_increment: v.optional(v.number()),
    conversions_increment: v.optional(v.number()),
    rewardsIssued_increment: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    const now = Date.now();

    // Resolve referral by _id or prismaId
    let docId: string | null = null;
    try {
      const doc = await ctx.db.get(args.id as never);
      if (doc) docId = args.id;
    } catch {
      // Not a valid Convex ID
    }

    if (!docId) {
      const byPrismaId = await ctx.db
        .query("referrals")
        .filter((q) => q.eq(q.field("prismaId"), args.id))
        .first();
      if (byPrismaId) docId = byPrismaId._id;
    }

    if (!docId) {
      throw new Error(`Referral not found: ${args.id}`);
    }

    const existing = await ctx.db.get(docId as never);
    if (!existing) throw new Error(`Referral not found: ${args.id}`);

    const patch: Record<string, unknown> = { updatedAt: now };

    // Direct set fields
    const directFields = [
      "name",
      "description",
      "rewardType",
      "rewardValue",
      "rewardCurrency",
      "maxUses",
      "expiresAt",
      "status",
      "lastConvertedAt",
      "lastRewardAt",
      "uses",
      "conversions",
      "rewardsIssued",
    ] as const;

    for (const field of directFields) {
      if (args[field] !== undefined) {
        patch[field] = args[field];
      }
    }

    // Increment fields
    const existingDoc = existing as Record<string, unknown>;
    if (args.uses_increment !== undefined) {
      patch.uses = ((existingDoc.uses as number) ?? 0) + args.uses_increment;
    }
    if (args.conversions_increment !== undefined) {
      patch.conversions =
        ((existingDoc.conversions as number) ?? 0) + args.conversions_increment;
    }
    if (args.rewardsIssued_increment !== undefined) {
      patch.rewardsIssued =
        ((existingDoc.rewardsIssued as number) ?? 0) +
        args.rewardsIssued_increment;
    }

    await ctx.db.patch(docId as never, patch);
    return docId;
  },
});

/**
 * Delete a referral by id
 */
export const deleteReferral = mutation({
  args: { id: v.string() },
  handler: async (ctx, args) => {
    // Resolve referral by _id or prismaId
    let docId: string | null = null;
    try {
      const doc = await ctx.db.get(args.id as never);
      if (doc) docId = args.id;
    } catch {
      // Not a valid Convex ID
    }

    if (!docId) {
      const byPrismaId = await ctx.db
        .query("referrals")
        .filter((q) => q.eq(q.field("prismaId"), args.id))
        .first();
      if (byPrismaId) docId = byPrismaId._id;
    }

    if (!docId) {
      throw new Error(`Referral not found: ${args.id}`);
    }

    await ctx.db.delete(docId as never);
    return true;
  },
});
