import { defineSchema, defineTable } from "convex/server";
import { authTables } from "@convex-dev/auth/server";
import { v } from "convex/values";

// Schema for phase 002
// Note: authTables includes 'users' table with proper auth fields and indexes
const schema = defineSchema({
  ...authTables,
  // Don't redefine users - it comes from authTables with the correct schema

  userProfiles: defineTable({
    userId: v.id("users"),
    handle: v.optional(v.string()),
    displayName: v.optional(v.string()),
    avatar: v.optional(v.string()),
    homeSpaceId: v.optional(v.id("spaces")),
    sunoToken: v.optional(v.string()),
    email: v.optional(v.string()),
  })
    .index("by_user", ["userId"])
    .index("by_handle", ["handle"])
    .index("by_email", ["email"]),

  spaces: defineTable({
    name: v.string(),
    ownerId: v.id("users"),
    isHomeSpace: v.optional(v.boolean()),
    showcaseConfig: v.optional(
      v.object({
        theme: v.optional(
          v.object({
            primaryColor: v.string(),
            backgroundColor: v.string(),
            backgroundImage: v.optional(v.string()),
          })
        ),
      })
    ),
    metadata: v.optional(v.any()),
  }).index("by_owner", ["ownerId"]),

  spaceMembers: defineTable({
    spaceId: v.id("spaces"),
    userId: v.id("users"),
    role: v.union(v.literal("owner"), v.literal("member")),
    joinedAt: v.number(),
    isKicked: v.boolean(),
  })
    .index("by_space", ["spaceId"])
    .index("by_user", ["userId"])
    .index("by_space_and_user", ["spaceId", "userId"]),

  spaceInvites: defineTable({
    spaceId: v.id("spaces"),
    code: v.string(),
    createdBy: v.id("users"),
    createdAt: v.number(),
    expiresAt: v.optional(v.number()),
  })
    .index("by_space", ["spaceId"])
    .index("by_code", ["code"]),

  rooms: defineTable({
    spaceId: v.id("spaces"),
    name: v.string(),
    type: v.string(), // "chat", "canvas", "radio", etc.
    isPrivate: v.optional(v.boolean()),
    allowlist: v.optional(v.array(v.id("users"))),
    // Room background customization
    backgroundConfig: v.optional(
      v.object({
        type: v.union(v.literal("image"), v.literal("gradient"), v.literal("solid")),
        imageUrl: v.optional(v.string()),
        gradientStart: v.optional(v.string()),
        gradientEnd: v.optional(v.string()),
        solidColor: v.optional(v.string()),
      })
    ),
    // Radio room configuration
    radioConfig: v.optional(
      v.object({
        prompt: v.string(),
        atomReferences: v.optional(v.array(v.id("atoms"))),
        autoGenerate: v.boolean(),
        queueTargetLength: v.number(),
      })
    ),
    // Room playback state
    playbackState: v.optional(
      v.object({
        currentTrackId: v.optional(v.id("atoms")),
        isPlaying: v.boolean(),
        position: v.number(),
        timestamp: v.number(),
        queue: v.array(v.id("atoms")),
        queueIndex: v.number(),
        volume: v.number(),
        repeat: v.union(v.literal("none"), v.literal("one"), v.literal("all")),
        shuffle: v.boolean(),
        radioMode: v.union(
          v.literal("OFF"),
          v.literal("PROMPT"),
          v.literal("AUTO")
        ),
        radioPrompt: v.optional(v.string()),
        // Radio-specific fields for server-driven playback
        startedAt: v.optional(v.number()),
        trackDuration: v.optional(v.number()),
        generatingNewSongs: v.optional(v.boolean()),
        // Scheduled job ID for the next track advance
        nextAdvanceJobId: v.optional(v.id("_scheduled_functions")),
      })
    ),
    // Room leader (when set, room playback follows this user's playback)
    roomLeaderId: v.optional(v.id("users")),
  }).index("by_space", ["spaceId"]),

  messages: defineTable({
    roomId: v.id("rooms"),
    userId: v.id("users"),
    content: v.string(),
    timestamp: v.number(),
    mentions: v.optional(v.array(v.union(v.id("users"), v.literal("suno"), v.literal("orphy")))),
    reactions: v.optional(
      v.array(
        v.object({
          emoji: v.string(),
          userId: v.id("users"),
        })
      )
    ),
    // Assistant fields
    isAssistantMessage: v.optional(v.boolean()),
    atomReferences: v.optional(v.array(v.id("atoms"))),
    assistantStatus: v.optional(
      v.union(
        v.literal("processing"),
        v.literal("completed"),
        v.literal("failed")
      )
    ),
    // Threading
    replyToId: v.optional(v.id("messages")),
  })
    .index("by_room", ["roomId"])
    .index("by_room_and_timestamp", ["roomId", "timestamp"])
    .index("by_reply_to", ["replyToId"]),

  atoms: defineTable({
    type: v.union(
      v.literal("song"),
      v.literal("video"),
      v.literal("image"),
      v.literal("lyrics"),
      v.literal("webview"),
      v.literal("midi") // NEW: MIDI atom type
    ),
    ownerId: v.id("users"),
    spaceId: v.id("spaces"),
    metadata: v.any(),
    status: v.union(
      v.literal("pending"),
      v.literal("processing"),
      v.literal("streaming"),
      v.literal("completed"),
      v.literal("failed")
    ),
    progress: v.number(),
    createdAt: v.number(),
    updatedAt: v.number(),
    // Engagement metrics
    likeCount: v.optional(v.number()),
    playCount: v.optional(v.number()),
    // Track which users liked this atom
    likedBy: v.optional(v.array(v.id("users"))),
  })
    .index("by_space", ["spaceId"])
    .index("by_owner", ["ownerId"])
    .index("by_status", ["status"])
    .index("by_space_and_type", ["spaceId", "type"]),

  // Provenance: Operations table
  operations: defineTable({
    type: v.union(
      v.literal("generate"),
      v.literal("cover"),
      v.literal("stem"),
      v.literal("midi"),
      v.literal("remix"),
      v.literal("mashup"),
      v.literal("style_transfer"),
      v.literal("upload"),
      v.literal("continue")
    ),
    parameters: v.optional(v.any()),
    createdAt: v.number(),
    createdBy: v.id("users"),
  })
    .index("by_type", ["type"])
    .index("by_user", ["createdBy"]),

  // Provenance: Operation Atoms table (links operations to atoms)
  operationAtoms: defineTable({
    operationId: v.id("operations"),
    atomId: v.id("atoms"),
    direction: v.union(v.literal("input"), v.literal("output")),
    role: v.optional(v.string()),
  })
    .index("by_operation", ["operationId"])
    .index("by_atom", ["atomId"])
    .index("by_atom_and_direction", ["atomId", "direction"])
    .index("by_operation_and_direction", ["operationId", "direction"]),

  userPresence: defineTable({
    userId: v.id("users"),
    spaceId: v.id("spaces"),
    roomId: v.optional(v.id("rooms")),
    status: v.union(
      v.literal("online"),
      v.literal("idle"),
      v.literal("offline")
    ),
    lastSeen: v.number(),
  })
    .index("by_user", ["userId"])
    .index("by_space", ["spaceId"])
    .index("by_room", ["roomId"]),

  userPlaybackStates: defineTable({
    userId: v.id("users"),
    roomId: v.id("rooms"),
    currentTrackId: v.optional(v.id("atoms")),
    isPlaying: v.boolean(),
    position: v.number(),
    timestamp: v.number(), // When position was recorded
    volume: v.number(),
    followMode: v.union(
      v.literal("NONE"),
      v.literal("ROOM"),
      v.literal("USER")
    ),
    followingUserId: v.optional(v.id("users")),
    lastUpdated: v.number(),
  })
    .index("by_user", ["userId"])
    .index("by_room", ["roomId"])
    .index("by_user_and_room", ["userId", "roomId"]),

  radioGenerationJobs: defineTable({
    roomId: v.id("rooms"),
    prompt: v.string(),
    status: v.union(
      v.literal("pending"),
      v.literal("generating"),
      v.literal("completed"),
      v.literal("failed")
    ),
    generatedAtomIds: v.optional(v.array(v.id("atoms"))),
    createdAt: v.number(),
    completedAt: v.optional(v.number()),
    error: v.optional(v.string()),
  })
    .index("by_room", ["roomId"])
    .index("by_status", ["status"])
    .index("by_room_and_status", ["roomId", "status"]),
});

export default schema;
