import { query, mutation, internalMutation, internalQuery } from "./_generated/server";
import { getAuthUserId } from "@convex-dev/auth/server";
import { v } from "convex/values";

// Get current user with profile
export const current = query({
  args: {},
  handler: async (ctx) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) return null;

    const user = await ctx.db.get(userId);
    const profile = await ctx.db
      .query("userProfiles")
      .withIndex("by_user", (q) => q.eq("userId", userId))
      .first();

    return { user, profile };
  },
});

// Get or create user profile
export const getOrCreateProfile = mutation({
  args: {},
  handler: async (ctx) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) throw new Error("Not authenticated");

    // Check if profile exists
    let profile = await ctx.db
      .query("userProfiles")
      .withIndex("by_user", (q) => q.eq("userId", userId))
      .first();

    if (!profile) {
      // Create profile and home space
      const user = await ctx.db.get(userId);
      const homeSpaceId = await ctx.db.insert("spaces", {
        name: `${user?.name || "My"} Home`,
        ownerId: userId,
        isHomeSpace: true,
        showcaseConfig: {
          theme: {
            primaryColor: "#3b82f6",
            backgroundColor: "#1f2937",
          },
        },
      });

      // Create default room in home space
      await ctx.db.insert("rooms", {
        spaceId: homeSpaceId,
        name: "general",
        type: "chat",
      });

      // Create space member record
      await ctx.db.insert("spaceMembers", {
        spaceId: homeSpaceId,
        userId,
        role: "owner",
        joinedAt: Date.now(),
        isKicked: false,
      });

      // Create profile with home space
      const profileId = await ctx.db.insert("userProfiles", {
        userId,
        homeSpaceId,
        displayName: user?.name,
        email: user?.email,
      });

      profile = await ctx.db.get(profileId);
    }

    return profile;
  },
});

// Update user profile
export const updateProfile = mutation({
  args: {
    handle: v.optional(v.string()),
    displayName: v.optional(v.string()),
    avatar: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) throw new Error("Not authenticated");

    const profile = await ctx.db
      .query("userProfiles")
      .withIndex("by_user", (q) => q.eq("userId", userId))
      .first();

    if (!profile) throw new Error("Profile not found");

    // Check handle uniqueness if provided
    if (args.handle) {
      const existing = await ctx.db
        .query("userProfiles")
        .withIndex("by_handle", (q) => q.eq("handle", args.handle))
        .first();
      if (existing && existing._id !== profile._id) {
        throw new Error("Handle already taken");
      }
    }

    await ctx.db.patch(profile._id, args);
    return await ctx.db.get(profile._id);
  },
});

// Generate upload URL for avatar
export const generateUploadUrl = mutation(async (ctx) => {
  return await ctx.storage.generateUploadUrl();
});

// Update avatar after upload
export const updateAvatar = mutation({
  args: {
    storageId: v.id("_storage"),
  },
  handler: async (ctx, args) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) throw new Error("Not authenticated");

    const profile = await ctx.db
      .query("userProfiles")
      .withIndex("by_user", (q) => q.eq("userId", userId))
      .first();

    if (!profile) throw new Error("Profile not found");

    // Get the storage URL
    const url = await ctx.storage.getUrl(args.storageId);
    if (!url) throw new Error("Failed to get storage URL");

    await ctx.db.patch(profile._id, { avatar: url });
    return await ctx.db.get(profile._id);
  },
});

// Remove avatar
export const removeAvatar = mutation({
  args: {},
  handler: async (ctx) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) throw new Error("Not authenticated");

    const profile = await ctx.db
      .query("userProfiles")
      .withIndex("by_user", (q) => q.eq("userId", userId))
      .first();

    if (!profile) throw new Error("Profile not found");

    await ctx.db.patch(profile._id, { avatar: undefined });
    return await ctx.db.get(profile._id);
  },
});

// Query user presence
export const getPresence = query({
  args: { userId: v.id("users") },
  handler: async (ctx, args) => {
    const currentUserId = await getAuthUserId(ctx);
    if (!currentUserId) throw new Error("Not authenticated");

    return await ctx.db
      .query("userPresence")
      .withIndex("by_user", (q) => q.eq("userId", args.userId))
      .first();
  },
});

// Get user token by email (for internal use)
export const getUserTokenByEmail = query({
  args: { email: v.string() },
  handler: async (ctx, args) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) throw new Error("Not authenticated");

    const profile = await ctx.db
      .query("userProfiles")
      .withIndex("by_email", (q) => q.eq("email", args.email))
      .first();

    return profile?.sunoToken || null;
  },
});

// Get current user's token
export const getMyToken = query({
  args: {},
  handler: async (ctx) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) return null;

    const profile = await ctx.db
      .query("userProfiles")
      .withIndex("by_user", (q) => q.eq("userId", userId))
      .first();

    return profile?.sunoToken || null;
  },
});

// Update user token
export const updateToken = mutation({
  args: { sunoToken: v.string() },
  handler: async (ctx, args) => {
    const userId = await getAuthUserId(ctx);
    if (!userId) throw new Error("Not authenticated");

    const profile = await ctx.db
      .query("userProfiles")
      .withIndex("by_user", (q) => q.eq("userId", userId))
      .first();

    if (!profile) throw new Error("Profile not found");

    await ctx.db.patch(profile._id, { sunoToken: args.sunoToken });
    return await ctx.db.get(profile._id);
  },
});

// Internal query to get user token by userId
export const getUserTokenInternal = internalQuery({
  args: { userId: v.id("users") },
  handler: async (ctx, args) => {
    const profile = await ctx.db
      .query("userProfiles")
      .withIndex("by_user", (q) => q.eq("userId", args.userId))
      .first();

    return profile?.sunoToken || null;
  },
});
