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

// Get all cards (for local caching)
export const list = query({
  args: {},
  handler: async (ctx) => {
    return await ctx.db.query("cards").collect();
  },
});

// Get cards updated after a timestamp (for incremental sync)
export const listUpdatedAfter = query({
  args: { since: v.number() },
  handler: async (ctx, { since }) => {
    return await ctx.db
      .query("cards")
      .withIndex("by_updated", (q) => q.gt("updatedAt", since))
      .collect();
  },
});

// Get a single card by Scryfall ID
export const getByScryfallId = query({
  args: { scryfallId: v.string() },
  handler: async (ctx, { scryfallId }) => {
    return await ctx.db
      .query("cards")
      .withIndex("by_scryfall", (q) => q.eq("scryfallId", scryfallId))
      .first();
  },
});

// Get cards by oracle ID (all printings of a card)
export const getByOracleId = query({
  args: { oracleId: v.string() },
  handler: async (ctx, { oracleId }) => {
    return await ctx.db
      .query("cards")
      .withIndex("by_oracle", (q) => q.eq("oracleId", oracleId))
      .collect();
  },
});

// Search cards by name
export const searchByName = query({
  args: { name: v.string() },
  handler: async (ctx, { name }) => {
    const cards = await ctx.db.query("cards").collect();
    const lowerName = name.toLowerCase();
    return cards.filter((card) =>
      card.name.toLowerCase().includes(lowerName)
    );
  },
});

// Get total card count
export const count = query({
  args: {},
  handler: async (ctx) => {
    const cards = await ctx.db.query("cards").collect();
    return cards.length;
  },
});

// Insert a card (used by migration script)
export const insert = mutation({
  args: {
    scryfallId: v.string(),
    oracleId: v.string(),
    name: v.string(),
    setCode: v.string(),
    collectorNumber: v.string(),
    rarity: v.string(),
    artist: v.optional(v.string()),
    imageUri: v.optional(v.string()),
    hash: v.bytes(),
    hashVersion: v.number(),
  },
  handler: async (ctx, args) => {
    // Check if card already exists
    const existing = await ctx.db
      .query("cards")
      .withIndex("by_scryfall", (q) => q.eq("scryfallId", args.scryfallId))
      .first();

    if (existing) {
      // Update existing card
      await ctx.db.patch(existing._id, {
        ...args,
        updatedAt: Date.now(),
      });
      return existing._id;
    }

    // Insert new card
    return await ctx.db.insert("cards", {
      ...args,
      updatedAt: Date.now(),
    });
  },
});

// Batch insert cards
export const insertBatch = mutation({
  args: {
    cards: v.array(
      v.object({
        scryfallId: v.string(),
        oracleId: v.string(),
        name: v.string(),
        setCode: v.string(),
        collectorNumber: v.string(),
        rarity: v.string(),
        artist: v.optional(v.string()),
        imageUri: v.optional(v.string()),
        hash: v.bytes(),
        hashVersion: v.number(),
      })
    ),
  },
  handler: async (ctx, { cards }) => {
    const results = [];
    for (const card of cards) {
      const existing = await ctx.db
        .query("cards")
        .withIndex("by_scryfall", (q) => q.eq("scryfallId", card.scryfallId))
        .first();

      if (existing) {
        await ctx.db.patch(existing._id, {
          ...card,
          updatedAt: Date.now(),
        });
        results.push(existing._id);
      } else {
        const id = await ctx.db.insert("cards", {
          ...card,
          updatedAt: Date.now(),
        });
        results.push(id);
      }
    }
    return results;
  },
});
