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

/**
 * Create a new conversation log entry (voice call started)
 * Phase 6: WhatsApp & Voice Agents
 */
export const createConversationLog = mutation({
  args: {
    userId: v.string(),
    platform: v.string(),
    customerPhone: v.optional(v.string()),
    customerName: v.optional(v.string()),
    metadata: v.optional(v.any()),
  },
  handler: async (ctx, args) => {
    const now = Date.now();
    const id = await ctx.db.insert("conversation_logs", {
      userId: args.userId,
      platform: args.platform,
      customerPhone: args.customerPhone,
      customerName: args.customerName,
      messages: [],
      metadata: args.metadata,
      status: "active",
      unreadCount: 0,
      messageCount: 0,
      createdAt: now,
      updatedAt: now,
    });
    return id;
  },
});

/**
 * Add a message to a conversation log
 * Phase 6: WhatsApp & Voice Agents
 */
export const addMessage = mutation({
  args: {
    conversationId: v.string(),
    sender: v.union(
      v.literal("customer"),
      v.literal("ai_agent"),
      v.literal("admin"),
    ),
    content: v.string(),
    metadata: v.optional(v.any()),
  },
  handler: async (ctx, args) => {
    const now = Date.now();
    const messageId = await ctx.db.insert("conversation_log_messages", {
      conversationId: args.conversationId,
      sender: args.sender,
      content: args.content,
      timestamp: now,
      metadata: args.metadata,
      createdAt: now,
    });
    return messageId;
  },
});

/**
 * Update phone configuration for voice agent
 * Phase 6: WhatsApp & Voice Agents
 */
export const updatePhoneConfig = mutation({
  args: {
    id: v.id("voice_agent_phone_config"),
    connectionType: v.optional(
      v.union(v.literal("twilio_native"), v.literal("custom_sip")),
    ),
    phoneNumber: v.optional(v.string()),
    isActive: v.optional(v.boolean()),
    twilioPhoneNumber: v.optional(v.string()),
    sipUri: v.optional(v.string()),
    metadata: v.optional(v.any()),
  },
  handler: async (ctx, args) => {
    const existing = await ctx.db.get(args.id);
    if (!existing) {
      throw new Error(`Phone config ${args.id} not found`);
    }
    const { id, ...updates } = args;
    const patch: Record<string, unknown> = { updatedAt: Date.now() };
    if (updates.connectionType !== undefined)
      patch.connectionType = updates.connectionType;
    if (updates.phoneNumber !== undefined)
      patch.phoneNumber = updates.phoneNumber;
    if (updates.isActive !== undefined) patch.isActive = updates.isActive;
    if (updates.twilioPhoneNumber !== undefined)
      patch.twilioPhoneNumber = updates.twilioPhoneNumber;
    if (updates.sipUri !== undefined) patch.sipUri = updates.sipUri;
    if (updates.metadata !== undefined) patch.metadata = updates.metadata;
    await ctx.db.patch(id, patch);
    return id;
  },
});

/**
 * Create a new phone config for a voice agent
 * Phase 6: WhatsApp & Voice Agents
 */
export const createPhoneConfig = mutation({
  args: {
    userId: v.string(),
    connectionType: v.union(
      v.literal("twilio_native"),
      v.literal("custom_sip"),
    ),
    phoneNumber: v.optional(v.string()),
    isActive: v.boolean(),
    elevenlabsPhoneId: v.optional(v.string()),
    twilioPhoneNumber: v.optional(v.string()),
    twilioAccountSid: v.optional(v.string()),
    twilioAuthToken: v.optional(v.string()),
    sipUri: v.optional(v.string()),
    sipUsername: v.optional(v.string()),
    sipPassword: v.optional(v.string()),
    sipRegistrar: v.optional(v.string()),
    sipTransport: v.optional(v.string()),
    metadata: v.optional(v.any()),
  },
  handler: async (ctx, args) => {
    const now = Date.now();
    const id = await ctx.db.insert("voice_agent_phone_config", {
      userId: args.userId,
      connectionType: args.connectionType,
      phoneNumber: args.phoneNumber,
      isActive: args.isActive,
      elevenlabsPhoneId: args.elevenlabsPhoneId,
      twilioPhoneNumber: args.twilioPhoneNumber,
      twilioAccountSid: args.twilioAccountSid,
      twilioAuthToken: args.twilioAuthToken,
      sipUri: args.sipUri,
      sipUsername: args.sipUsername,
      sipPassword: args.sipPassword,
      sipRegistrar: args.sipRegistrar,
      sipTransport: args.sipTransport,
      metadata: args.metadata,
      createdAt: now,
      updatedAt: now,
    });
    return id;
  },
});

/**
 * Activate a voice agent phone config
 * Phase 6: WhatsApp & Voice Agents
 */
export const activatePhoneConfig = mutation({
  args: { id: v.id("voice_agent_phone_config") },
  handler: async (ctx, args) => {
    const existing = await ctx.db.get(args.id);
    if (!existing) {
      throw new Error(`Phone config ${args.id} not found`);
    }
    await ctx.db.patch(args.id, {
      isActive: true,
      updatedAt: Date.now(),
    });
    return args.id;
  },
});

/**
 * Deactivate a voice agent phone config
 * Phase 6: WhatsApp & Voice Agents
 */
export const deactivatePhoneConfig = mutation({
  args: { id: v.id("voice_agent_phone_config") },
  handler: async (ctx, args) => {
    const existing = await ctx.db.get(args.id);
    if (!existing) {
      throw new Error(`Phone config ${args.id} not found`);
    }
    await ctx.db.patch(args.id, {
      isActive: false,
      updatedAt: Date.now(),
    });
    return args.id;
  },
});

/**
 * Update voice agent settings
 * Phase 6: WhatsApp & Voice Agents
 */
export const updateSettings = mutation({
  args: {
    id: v.id("voice_agent_settings"),
    successEvaluationCriteria: v.optional(v.any()),
    dataCollectionSchema: v.optional(v.any()),
    postCallWebhookUrl: v.optional(v.string()),
    pronunciationDictId: v.optional(v.string()),
    pronunciationRules: v.optional(v.any()),
    domainAllowlist: v.optional(v.array(v.string())),
    signedUrlEnabled: v.optional(v.boolean()),
    activeWorkflowId: v.optional(v.string()),
    workflowTemplate: v.optional(v.string()),
    workflowCustomization: v.optional(v.any()),
  },
  handler: async (ctx, args) => {
    const existing = await ctx.db.get(args.id);
    if (!existing) {
      throw new Error(`Voice agent settings ${args.id} not found`);
    }
    const { id, ...fields } = args;
    const patch: Record<string, unknown> = { updatedAt: Date.now() };
    for (const [key, value] of Object.entries(fields)) {
      if (value !== undefined) patch[key] = value;
    }
    await ctx.db.patch(id, patch);
    return id;
  },
});

/**
 * Provision a voice agent — update user record with agentId + config + optional webhook token
 * Phase 6: WhatsApp & Voice Agents  (gap-fill for WU-12)
 */
export const provisionAgent = mutation({
  args: {
    userId: v.string(),
    voiceAgentId: v.string(),
    voiceAgentConfig: v.any(),
    n8nWebhookToken: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    // Find the user by prismaId (string) — users table stores legacy IDs
    const user = await ctx.db
      .query("users")
      .filter((q) => q.eq(q.field("prismaId"), args.userId))
      .first();
    if (!user) {
      throw new Error(`User ${args.userId} not found in Convex`);
    }
    const patch: Record<string, unknown> = {
      voiceAgentId: args.voiceAgentId,
      voiceAgentConfig: args.voiceAgentConfig,
      updatedAt: Date.now(),
    };
    if (args.n8nWebhookToken !== undefined) {
      patch.n8nWebhookToken = args.n8nWebhookToken;
    }
    await ctx.db.patch(user._id, patch);
    return user._id;
  },
});

/**
 * Update conversation log — for call_ended / call_failed events
 * Phase 6: WhatsApp & Voice Agents  (gap-fill for WU-12)
 */
export const updateConversationLog = mutation({
  args: {
    callId: v.string(),
    messages: v.optional(v.any()),
    status: v.optional(v.string()),
    metadata: v.optional(v.any()),
  },
  handler: async (ctx, args) => {
    // Find by callId stored in metadata
    const allLogs = await ctx.db
      .query("conversation_logs")
      .filter((q) => q.eq(q.field("platform"), "voice"))
      .collect();
    const log = allLogs.find((l) => {
      const meta = l.metadata as Record<string, unknown> | undefined;
      return meta?.callId === args.callId;
    });
    if (!log) return null;

    const patch: Record<string, unknown> = { updatedAt: Date.now() };
    if (args.messages !== undefined) patch.messages = args.messages;
    if (args.status !== undefined)
      patch.status = args.status === "ended" ? "resolved" : "open";
    if (args.metadata !== undefined) {
      patch.metadata = {
        ...((log.metadata as Record<string, unknown>) || {}),
        ...args.metadata,
      };
    }
    await ctx.db.patch(log._id, patch);
    return log._id;
  },
});

/**
 * Create a knowledge base document
 * Phase 6: WhatsApp & Voice Agents
 */
export const createKBDocument = mutation({
  args: {
    userId: v.string(),
    prismaId: v.optional(v.string()),
    filename: v.string(),
    originalName: v.string(),
    mimeType: v.string(),
    fileSize: v.number(),
    storagePath: v.string(),
    title: v.optional(v.union(v.string(), v.null())),
    description: v.optional(v.union(v.string(), v.null())),
    category: v.string(),
    status: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    const now = Date.now();
    const id = await ctx.db.insert("knowledge_base_documents", {
      userId: args.userId,
      prismaId: args.prismaId,
      filename: args.filename,
      originalName: args.originalName,
      mimeType: args.mimeType,
      fileSize: args.fileSize,
      storagePath: args.storagePath,
      title: args.title ?? undefined,
      description: args.description ?? undefined,
      category: args.category,
      status: (args.status as "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED") || "PENDING",
      chunkCount: 0,
      createdAt: now,
      updatedAt: now,
    });
    return id;
  },
});

/**
 * Update a knowledge base document's metadata
 * Phase 6: WhatsApp & Voice Agents
 */
export const updateKBDocument = mutation({
  args: {
    id: v.string(),
    title: v.optional(v.string()),
    description: v.optional(v.string()),
    category: v.optional(v.string()),
    status: v.optional(v.string()),
    chunkCount: v.optional(v.number()),
    processingError: v.optional(v.string()),
    processedAt: v.optional(v.number()),
    embeddingModel: v.optional(v.string()),
    embeddingId: v.optional(v.string()),
    aiDescription: v.optional(v.string()),
    pineconeNamespace: v.optional(v.string()),
    mediaType: v.optional(v.string()),
    mediaUrl: v.optional(v.string()),
    thumbnailUrl: v.optional(v.string()),
    duration: v.optional(v.number()),
    width: v.optional(v.number()),
    height: v.optional(v.number()),
    geminiFileName: v.optional(v.string()),
    geminiUploadedAt: v.optional(v.number()),
    deletedAt: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    // Try as Convex _id first, fall back to prismaId scan
    let doc = null;
    try {
      doc = await ctx.db.get(args.id as any);
    } catch {
      /* not a valid Convex ID */
    }
    if (!doc) {
      doc = await ctx.db
        .query("knowledge_base_documents")
        .filter((q) => q.eq(q.field("prismaId"), args.id))
        .first();
    }
    if (!doc) throw new Error(`KB document ${args.id} not found`);

    const { id: _id, ...fields } = args;
    const patch: Record<string, unknown> = { updatedAt: Date.now() };
    for (const [key, value] of Object.entries(fields)) {
      if (value !== undefined) patch[key] = value;
    }
    await ctx.db.patch(doc._id, patch);
    return doc._id;
  },
});

/**
 * Delete a knowledge base document
 * Phase 6: WhatsApp & Voice Agents
 */
export const deleteKBDocument = mutation({
  args: { id: v.string() },
  handler: async (ctx, args) => {
    // Try as Convex _id first, fall back to prismaId scan
    let doc = null;
    try {
      doc = await ctx.db.get(args.id as any);
    } catch {
      /* not a valid Convex ID */
    }
    if (!doc) {
      doc = await ctx.db
        .query("knowledge_base_documents")
        .filter((q) => q.eq(q.field("prismaId"), args.id))
        .first();
    }
    if (!doc) throw new Error(`KB document ${args.id} not found`);

    await ctx.db.delete(doc._id);
    return doc._id;
  },
});

/**
 * Create knowledge base settings for a user
 * Phase 6: WhatsApp & Voice Agents
 */
export const createKBSettings = mutation({
  args: {
    userId: v.string(),
    prismaId: v.optional(v.string()),
    isEnabled: v.optional(v.boolean()),
    onboardingCompleted: v.optional(v.boolean()),
    maxChunksPerQuery: v.optional(v.number()),
    similarityThreshold: v.optional(v.number()),
  },
  handler: async (ctx, args) => {
    const now = Date.now();
    const id = await ctx.db.insert("knowledge_base_settings", {
      userId: args.userId,
      prismaId: args.prismaId,
      isEnabled: args.isEnabled ?? true,
      onboardingCompleted: args.onboardingCompleted ?? false,
      maxChunksPerQuery: args.maxChunksPerQuery ?? 5,
      similarityThreshold: args.similarityThreshold ?? 0.7,
      createdAt: now,
      updatedAt: now,
    });
    return id;
  },
});

/**
 * Update knowledge base settings
 * Phase 6: WhatsApp & Voice Agents
 */
export const updateKBSettings = mutation({
  args: {
    id: v.string(),
    isEnabled: v.optional(v.boolean()),
    onboardingCompleted: v.optional(v.boolean()),
    maxChunksPerQuery: v.optional(v.number()),
    similarityThreshold: v.optional(v.number()),
    welcomeMessage: v.optional(v.string()),
    customInstructions: v.optional(v.string()),
    geminiFileSearchStoreId: v.optional(v.string()),
    geminiFileSearchStoreName: v.optional(v.string()),
  },
  handler: async (ctx, args) => {
    // Try as Convex _id first, fall back to prismaId scan
    let doc = null;
    try {
      doc = await ctx.db.get(args.id as any);
    } catch {
      /* not a valid Convex ID */
    }
    if (!doc) {
      doc = await ctx.db
        .query("knowledge_base_settings")
        .filter((q) => q.eq(q.field("prismaId"), args.id))
        .first();
    }
    if (!doc) throw new Error(`KB settings ${args.id} not found`);

    const { id: _id, ...fields } = args;
    const patch: Record<string, unknown> = { updatedAt: Date.now() };
    for (const [key, value] of Object.entries(fields)) {
      if (value !== undefined) patch[key] = value;
    }
    await ctx.db.patch(doc._id, patch);
    return doc._id;
  },
});

/**
 * Create a knowledge base FAQ entry
 * Phase 6: WhatsApp & Voice Agents
 */
export const createKBFAQ = mutation({
  args: {
    userId: v.string(),
    prismaId: v.optional(v.string()),
    questionEn: v.string(),
    questionAr: v.optional(v.union(v.string(), v.null())),
    answerEn: v.string(),
    answerAr: v.optional(v.union(v.string(), v.null())),
    category: v.optional(v.string()),
    priority: v.optional(v.number()),
    isActive: v.optional(v.boolean()),
  },
  handler: async (ctx, args) => {
    const now = Date.now();
    const id = await ctx.db.insert("knowledge_base_faqs", {
      userId: args.userId,
      prismaId: args.prismaId,
      questionEn: args.questionEn,
      questionAr: args.questionAr ?? undefined,
      answerEn: args.answerEn,
      answerAr: args.answerAr ?? undefined,
      category: args.category ?? "general",
      priority: args.priority ?? 0,
      isActive: args.isActive ?? true,
      createdAt: now,
      updatedAt: now,
    });
    return id;
  },
});

/**
 * Update a knowledge base FAQ entry
 * Phase 6: WhatsApp & Voice Agents
 */
export const updateKBFAQ = mutation({
  args: {
    id: v.string(),
    questionEn: v.optional(v.string()),
    questionAr: v.optional(v.string()),
    answerEn: v.optional(v.string()),
    answerAr: v.optional(v.string()),
    category: v.optional(v.string()),
    priority: v.optional(v.number()),
    isActive: v.optional(v.boolean()),
  },
  handler: async (ctx, args) => {
    // Try as Convex _id first, fall back to prismaId scan
    let doc = null;
    try {
      doc = await ctx.db.get(args.id as any);
    } catch {
      /* not a valid Convex ID */
    }
    if (!doc) {
      doc = await ctx.db
        .query("knowledge_base_faqs")
        .filter((q) => q.eq(q.field("prismaId"), args.id))
        .first();
    }
    if (!doc) throw new Error(`KB FAQ ${args.id} not found`);

    const { id: _id, ...fields } = args;
    const patch: Record<string, unknown> = { updatedAt: Date.now() };
    for (const [key, value] of Object.entries(fields)) {
      if (value !== undefined) patch[key] = value;
    }
    await ctx.db.patch(doc._id, patch);
    return doc._id;
  },
});

/**
 * Delete a knowledge base FAQ entry
 * Phase 6: WhatsApp & Voice Agents
 */
export const deleteKBFAQ = mutation({
  args: { id: v.string() },
  handler: async (ctx, args) => {
    // Try as Convex _id first, fall back to prismaId scan
    let doc = null;
    try {
      doc = await ctx.db.get(args.id as any);
    } catch {
      /* not a valid Convex ID */
    }
    if (!doc) {
      doc = await ctx.db
        .query("knowledge_base_faqs")
        .filter((q) => q.eq(q.field("prismaId"), args.id))
        .first();
    }
    if (!doc) throw new Error(`KB FAQ ${args.id} not found`);

    await ctx.db.delete(doc._id);
    return doc._id;
  },
});

/**
 * Create a knowledge base chunk
 * Phase 6: WhatsApp & Voice Agents
 */
export const createKBChunk = mutation({
  args: {
    documentId: v.string(),
    content: v.string(),
    chunkIndex: v.number(),
    embedding: v.optional(v.any()),
    metadata: v.optional(v.any()),
  },
  handler: async (ctx, args) => {
    const now = Date.now();
    const id = await ctx.db.insert("knowledge_base_chunks", {
      documentId: args.documentId,
      content: args.content,
      chunkIndex: args.chunkIndex,
      embedding: args.embedding,
      metadata: args.metadata,
      createdAt: now,
    });
    return id;
  },
});
