/**
 * Leads Domain Adapter
 *
 * Routes leads, lead_activities, lead_pipeline_stages, lead_scoring_rules,
 * lead_scoring_events, lead_capture_forms, lead_nurture_sequences,
 * lead_nurture_steps, and lead_nurture_memberships CRUD to Prisma or Convex
 * based on data-source config.
 *
 * This is the largest domain adapter (~3,189 lines across 7 service files).
 * Maintains Prisma-compatible method signatures so service layer changes are minimal.
 */

import { prisma } from "@/lib/db";
import { convexQuery, convexMutation } from "@/lib/convex-client";
import { getDataSource } from "@/lib/data-source";
import {
  convexToPrismaShape,
  convexToPrismaShapeMany,
  applyPagination,
  type ConvexDoc,
  type BatchResult,
} from "./base";

const DOMAIN = "leads" as const;

const LEAD_TS_FIELDS = [
  "createdAt",
  "updatedAt",
  "convertedAt",
  "lastContactAt",
  "nextFollowUpAt",
  "firstTouchAt",
  "lastActivityAt",
  "expectedCloseAt",
  "qualifiedAt",
];
const ACTIVITY_TS_FIELDS = ["createdAt"];
const STAGE_TS_FIELDS = ["createdAt", "updatedAt"];
const SCORING_RULE_TS_FIELDS = ["createdAt", "updatedAt"];
const SCORING_EVENT_TS_FIELDS = ["createdAt"];
const CAPTURE_FORM_TS_FIELDS = ["createdAt", "updatedAt"];
const NURTURE_SEQ_TS_FIELDS = ["createdAt", "updatedAt"];
const NURTURE_STEP_TS_FIELDS = ["createdAt", "updatedAt"];
const NURTURE_MEMBERSHIP_TS_FIELDS = [
  "createdAt",
  "updatedAt",
  "nextActionAt",
  "completedAt",
  "exitedAt",
];

function isConvex(): boolean {
  return getDataSource(DOMAIN) === "convex";
}

// ═══════════════════════════════════════════════════════════════════════════
// Leads
// ═══════════════════════════════════════════════════════════════════════════

const leads = {
  // ─── findMany ──────────────────────────────────────────────────────
  async findMany(args: {
    where?: Record<string, unknown>;
    include?: Record<string, unknown>;
    orderBy?: Record<string, string> | Record<string, string>[];
    take?: number;
    skip?: number;
    select?: Record<string, boolean>;
  }) {
    if (!isConvex()) {
      return prisma.leads.findMany(args as any);
    }

    const where = (args.where || {}) as Record<string, unknown>;
    const userId = where.userId as string | undefined;
    const status = where.status as string | undefined;
    const limit = (args.take || 100) + (args.skip || 0);

    const docs =
      (await convexQuery<ConvexDoc[]>("leads/queries:getLeads", {
        userId: userId || "",
        ...(status ? { status } : {}),
        limit,
      })) || [];

    // Apply additional client-side where filters not handled by Convex query
    let filtered = docs;
    if (where.source) {
      filtered = filtered.filter((d) => d.source === where.source);
    }
    if (where.pipelineStageId) {
      filtered = filtered.filter(
        (d) => d.pipelineStageId === where.pipelineStageId,
      );
    }
    if (where.assignedTo) {
      filtered = filtered.filter((d) => d.assignedTo === where.assignedTo);
    }
    // Handle { id: { in: [...] } }
    const idFilter = where.id;
    if (
      idFilter &&
      typeof idFilter === "object" &&
      idFilter !== null &&
      "in" in (idFilter as object)
    ) {
      const inIds = (idFilter as { in: string[] }).in;
      const idSet = new Set(inIds);
      filtered = filtered.filter((d) =>
        idSet.has((d.prismaId as string) || d._id),
      );
    }
    // Handle score range { score: { gte: X, lte: Y } }
    if (where.score && typeof where.score === "object") {
      const scoreFilter = where.score as { gte?: number; lte?: number };
      if (scoreFilter.gte !== undefined) {
        filtered = filtered.filter(
          (d) => (d.score as number) >= scoreFilter.gte!,
        );
      }
      if (scoreFilter.lte !== undefined) {
        filtered = filtered.filter(
          (d) => (d.score as number) <= scoreFilter.lte!,
        );
      }
    }
    // Handle tags: { hasSome: [...] }
    if (
      where.tags &&
      typeof where.tags === "object" &&
      "hasSome" in (where.tags as object)
    ) {
      const hasSome = (where.tags as { hasSome: string[] }).hasSome;
      filtered = filtered.filter((d) => {
        const tags = (d.tags as string[]) || [];
        return hasSome.some((t) => tags.includes(t));
      });
    }
    // Handle createdAt range
    if (where.createdAt && typeof where.createdAt === "object") {
      const dateFilter = where.createdAt as { gte?: Date; lte?: Date };
      if (dateFilter.gte) {
        const gteMs = dateFilter.gte.getTime();
        filtered = filtered.filter((d) => (d.createdAt as number) >= gteMs);
      }
      if (dateFilter.lte) {
        const lteMs = dateFilter.lte.getTime();
        filtered = filtered.filter((d) => (d.createdAt as number) <= lteMs);
      }
    }
    // Handle lastActivityAt range (for decay queries)
    if (where.lastActivityAt && typeof where.lastActivityAt === "object") {
      const dateFilter = where.lastActivityAt as { lt?: Date };
      if (dateFilter.lt) {
        const ltMs = dateFilter.lt.getTime();
        filtered = filtered.filter((d) => (d.lastActivityAt as number) < ltMs);
      }
    }
    // Handle OR (search) -- basic string matching
    if (where.OR && Array.isArray(where.OR)) {
      const orConditions = where.OR as Record<string, unknown>[];
      filtered = filtered.filter((d) =>
        orConditions.some((cond) => {
          for (const [key, val] of Object.entries(cond)) {
            if (
              val &&
              typeof val === "object" &&
              "contains" in (val as object)
            ) {
              const search = (
                (val as { contains: string }).contains || ""
              ).toLowerCase();
              const docVal = d[key];
              if (
                typeof docVal === "string" &&
                docVal.toLowerCase().includes(search)
              ) {
                return true;
              }
            }
          }
          return false;
        }),
      );
    }

    const paginated = applyPagination(filtered, args.skip, args.take);
    return convexToPrismaShapeMany(paginated, LEAD_TS_FIELDS);
  },

  // ─── findFirst ─────────────────────────────────────────────────────
  async findFirst(args: {
    where?: Record<string, unknown>;
    include?: Record<string, unknown>;
    select?: Record<string, boolean>;
  }) {
    if (!isConvex()) {
      return prisma.leads.findFirst(args as any);
    }

    const where = (args.where || {}) as Record<string, unknown>;
    const id = where.id as string | undefined;

    // Optimized path: if we have an id, use getById
    if (id) {
      try {
        const doc = await convexQuery<ConvexDoc | null>(
          "leads/queries:getById",
          { id: id as any },
        );
        if (!doc) return null;
        // Check additional where conditions (e.g., userId)
        if (where.userId && doc.userId !== where.userId) return null;
        return convexToPrismaShape(doc, LEAD_TS_FIELDS);
      } catch {
        // Fall through to list-based lookup
      }
    }

    // Fallback: fetch by userId and filter
    const userId = (where.userId as string) || "";
    const docs =
      (await convexQuery<ConvexDoc[]>("leads/queries:getLeads", {
        userId,
        limit: 1000,
      })) || [];

    const match = docs.find((doc) => {
      for (const [key, value] of Object.entries(where)) {
        if (key === "id") {
          if ((doc.prismaId || doc._id) !== value) return false;
        } else if (doc[key] !== value) {
          return false;
        }
      }
      return true;
    });

    return match ? convexToPrismaShape(match, LEAD_TS_FIELDS) : null;
  },

  // ─── findUnique ────────────────────────────────────────────────────
  async findUnique(args: {
    where: { id: string };
    include?: Record<string, unknown>;
    select?: Record<string, boolean>;
  }) {
    if (!isConvex()) {
      return prisma.leads.findUnique(args as any);
    }

    try {
      const doc = await convexQuery<ConvexDoc | null>("leads/queries:getById", {
        id: args.where.id as any,
      });
      return doc ? convexToPrismaShape(doc, LEAD_TS_FIELDS) : null;
    } catch {
      return leads.findFirst({ where: args.where });
    }
  },

  // ─── count ─────────────────────────────────────────────────────────
  async count(args?: { where?: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.leads.count(args as any);
    }

    // Reuse findMany logic for filtering, then count
    const items = await leads.findMany({
      where: args?.where,
      take: 10000,
    });
    return (items as unknown[]).length;
  },

  // ─── create ────────────────────────────────────────────────────────
  async create(args: {
    data: Record<string, unknown>;
    include?: Record<string, unknown>;
  }) {
    if (!isConvex()) {
      return prisma.leads.create(args as any);
    }

    const d = args.data;
    const convexId = await convexMutation<string>(
      "leads/mutations:createLead",
      {
        userId: d.userId as string,
        ...(d.organizationId
          ? { organizationId: d.organizationId as string }
          : {}),
        name: d.name as string,
        ...(d.phone ? { phone: d.phone as string } : {}),
        ...(d.email ? { email: d.email as string } : {}),
        ...(d.company ? { company: d.company as string } : {}),
        source: (d.source as string) || "manual",
        ...(d.interest ? { interest: d.interest as string } : {}),
        ...(d.notes ? { notes: d.notes as string } : {}),
      },
    );

    const now = new Date();
    return {
      id: (d.id as string) || convexId || "",
      userId: d.userId,
      organizationId: d.organizationId ?? null,
      name: d.name,
      phone: d.phone ?? null,
      email: d.email ?? null,
      company: d.company ?? null,
      source: d.source ?? "manual",
      campaignId: d.campaignId ?? null,
      interest: d.interest ?? null,
      notes: d.notes ?? null,
      customFields: d.customFields ?? {},
      metadata: d.metadata ?? {},
      status: d.status ?? "NEW",
      score: d.score ?? 0,
      tags: d.tags ?? [],
      language: d.language ?? "en",
      sourceChannel: d.sourceChannel ?? null,
      captureFormId: d.captureFormId ?? null,
      dealValue: d.dealValue ?? null,
      dealCurrency: d.dealCurrency ?? "QAR",
      pipelineStageId: d.pipelineStageId ?? null,
      assignedTo: d.assignedTo ?? null,
      convertedAt: null,
      lastContactAt: null,
      qualifiedAt: null,
      qualificationScore: null,
      expectedCloseAt: null,
      lostReason: null,
      firstTouchAt: d.firstTouchAt ?? now,
      lastActivityAt: d.lastActivityAt ?? now,
      touchCount: d.touchCount ?? 1,
      createdAt: now,
      updatedAt: now,
      pipelineStage: null,
    };
  },

  // ─── update ────────────────────────────────────────────────────────
  async update(args: {
    where: { id: string };
    data: Record<string, unknown>;
    include?: Record<string, unknown>;
  }) {
    if (!isConvex()) {
      return prisma.leads.update(args as any);
    }

    const d = args.data;
    const updateArgs: Record<string, unknown> = {
      id: args.where.id as any,
    };

    // Map Prisma-style fields to Convex mutation args
    if (d.name !== undefined) updateArgs.name = d.name as string;
    if (d.phone !== undefined) updateArgs.phone = d.phone as string;
    if (d.email !== undefined) updateArgs.email = d.email as string;
    if (d.company !== undefined) updateArgs.company = d.company as string;
    if (d.notes !== undefined) updateArgs.notes = d.notes as string;
    if (d.assignedTo !== undefined)
      updateArgs.assignedTo = d.assignedTo as string;
    if (d.tags !== undefined) updateArgs.tags = d.tags as string[];

    // Handle status updates
    if (d.status !== undefined) {
      await convexMutation("leads/mutations:updateLeadStatus", {
        id: args.where.id as any,
        status: d.status as string,
      });
    }

    // Handle pipeline stage changes (pipelineStage connect/disconnect)
    if (d.pipelineStage !== undefined) {
      const stageOp = d.pipelineStage as
        | { connect?: { id: string }; disconnect?: boolean }
        | undefined;
      if (stageOp && "connect" in stageOp && stageOp.connect) {
        await convexMutation("leads/mutations:movePipelineStage", {
          id: args.where.id as any,
          pipelineStageId: stageOp.connect.id,
        });
      }
    } else if (d.pipelineStageId !== undefined) {
      if (d.pipelineStageId) {
        await convexMutation("leads/mutations:movePipelineStage", {
          id: args.where.id as any,
          pipelineStageId: d.pipelineStageId as string,
        });
      }
    }

    // Score updates
    if (d.score !== undefined) {
      await convexMutation("leads/mutations:updateScore", {
        id: args.where.id as any,
        score: d.score as number,
      });
    }

    // General field updates via updateLead
    const hasGeneralFields =
      d.name !== undefined ||
      d.phone !== undefined ||
      d.email !== undefined ||
      d.company !== undefined ||
      d.notes !== undefined ||
      d.assignedTo !== undefined ||
      d.tags !== undefined;

    if (hasGeneralFields) {
      await convexMutation("leads/mutations:updateLead", updateArgs);
    }

    // Return best-effort shape
    const existing = await leads.findUnique({ where: { id: args.where.id } });
    return existing ? { ...existing, ...flattenPrismaData(d) } : null;
  },

  // ─── updateMany ────────────────────────────────────────────────────
  async updateMany(args: {
    where: Record<string, unknown>;
    data: Record<string, unknown>;
  }): Promise<BatchResult> {
    if (!isConvex()) {
      return prisma.leads.updateMany(args as any);
    }

    const where = args.where;
    const userId = where.userId as string | undefined;

    // Fetch matching leads
    const allLeads =
      (await convexQuery<ConvexDoc[]>("leads/queries:getLeads", {
        userId: userId || "",
        limit: 10000,
      })) || [];

    // Filter by where conditions
    let matching = allLeads;
    const inIds = (where.id as { in?: string[] })?.in;
    if (inIds) {
      const idSet = new Set(inIds);
      matching = matching.filter((d) =>
        idSet.has((d.prismaId as string) || d._id),
      );
    }
    if (where.pipelineStageId !== undefined) {
      matching = matching.filter(
        (d) => d.pipelineStageId === where.pipelineStageId,
      );
    }

    // Update each lead
    let updatedCount = 0;
    for (const doc of matching) {
      try {
        const updateArgs: Record<string, unknown> = {
          id: doc._id as any,
        };
        const d = args.data;
        if (d.assignedTo !== undefined)
          updateArgs.assignedTo = d.assignedTo as string;
        if (d.pipelineStageId !== undefined) {
          await convexMutation("leads/mutations:movePipelineStage", {
            id: doc._id as any,
            pipelineStageId: (d.pipelineStageId as string) || "",
          });
        }
        if (d.status !== undefined) {
          await convexMutation("leads/mutations:updateLeadStatus", {
            id: doc._id as any,
            status: d.status as string,
          });
        }

        const hasFields = Object.keys(updateArgs).length > 1;
        if (hasFields) {
          await convexMutation("leads/mutations:updateLead", updateArgs);
        }

        updatedCount++;
      } catch {
        // Continue on individual failures
      }
    }

    return { count: updatedCount };
  },

  // ─── delete ────────────────────────────────────────────────────────
  async delete(args: { where: { id: string } }) {
    if (!isConvex()) {
      return prisma.leads.delete(args as any);
    }

    await convexMutation("leads/mutations:deleteLead", {
      id: args.where.id as any,
    });

    return { id: args.where.id };
  },

  // ─── deleteMany ────────────────────────────────────────────────────
  async deleteMany(args: {
    where: Record<string, unknown>;
  }): Promise<BatchResult> {
    if (!isConvex()) {
      return prisma.leads.deleteMany(args as any);
    }

    const where = args.where;
    const userId = where.userId as string | undefined;

    const docs =
      (await convexQuery<ConvexDoc[]>("leads/queries:getLeads", {
        userId: userId || "",
        limit: 10000,
      })) || [];

    // Filter
    let matching = docs;
    const inIds = (where.id as { in?: string[] })?.in;
    if (inIds) {
      const idSet = new Set(inIds);
      matching = docs.filter((d) => idSet.has((d.prismaId as string) || d._id));
    }

    for (const doc of matching) {
      await convexMutation("leads/mutations:deleteLead", {
        id: doc._id as any,
      });
    }

    return { count: matching.length };
  },
};

// ═══════════════════════════════════════════════════════════════════════════
// Lead Activities
// ═══════════════════════════════════════════════════════════════════════════

const leadActivities = {
  async findMany(args: {
    where?: Record<string, unknown>;
    orderBy?: Record<string, string> | Record<string, string>[];
    take?: number;
    skip?: number;
  }) {
    if (!isConvex()) {
      return prisma.lead_activities.findMany(args as any);
    }

    const where = (args.where || {}) as Record<string, unknown>;
    const leadId = where.leadId as string | undefined;

    if (!leadId) return [];

    const limit = (args.take || 100) + (args.skip || 0);
    const docs =
      (await convexQuery<ConvexDoc[]>("leads/queries:getActivities", {
        leadId,
        limit,
      })) || [];

    // Apply additional filters
    let filtered = docs;
    if (where.type) {
      filtered = filtered.filter((d) => d.type === where.type);
    }
    if (where.userId) {
      filtered = filtered.filter((d) => d.userId === where.userId);
    }

    const paginated = applyPagination(filtered, args.skip, args.take);
    return convexToPrismaShapeMany(paginated, ACTIVITY_TS_FIELDS);
  },

  async create(args: { data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_activities.create(args as any);
    }

    const d = args.data;
    const convexId = await convexMutation<string>(
      "leads/mutations:addActivity",
      {
        leadId: d.leadId as string,
        userId: d.userId as string,
        type: d.type as string,
        title: d.title as string,
        ...(d.description ? { description: d.description as string } : {}),
        ...(d.metadata !== undefined ? { metadata: d.metadata } : {}),
      },
    );

    return {
      id: (d.id as string) || convexId || "",
      leadId: d.leadId,
      userId: d.userId,
      type: d.type,
      title: d.title,
      description: d.description ?? null,
      metadata: d.metadata ?? null,
      createdAt: new Date(),
    };
  },

  async count(args?: { where?: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_activities.count(args as any);
    }

    const where = (args?.where || {}) as Record<string, unknown>;
    const leadId = where.leadId as string | undefined;
    if (!leadId) return 0;

    const docs =
      (await convexQuery<ConvexDoc[]>("leads/queries:getActivities", {
        leadId,
        limit: 10000,
      })) || [];

    let filtered = docs;
    if (where.type) {
      filtered = filtered.filter((d) => d.type === where.type);
    }

    return filtered.length;
  },
};

// ═══════════════════════════════════════════════════════════════════════════
// Lead Pipeline Stages
// ═══════════════════════════════════════════════════════════════════════════

const leadPipelineStages = {
  async findMany(args: {
    where?: Record<string, unknown>;
    include?: Record<string, unknown>;
    orderBy?: Record<string, string> | Record<string, string>[];
    take?: number;
    skip?: number;
  }) {
    if (!isConvex()) {
      return prisma.lead_pipeline_stages.findMany(args as any);
    }

    const where = (args.where || {}) as Record<string, unknown>;
    const userId = where.userId as string | undefined;

    if (!userId) return [];

    const docs =
      (await convexQuery<ConvexDoc[]>("leads/queries:getPipelineStages", {
        userId,
      })) || [];

    // Apply additional filters
    let filtered = docs;
    if (where.isDefault !== undefined) {
      filtered = filtered.filter((d) => d.isDefault === where.isDefault);
    }

    const paginated = applyPagination(filtered, args.skip, args.take);
    return convexToPrismaShapeMany(paginated, STAGE_TS_FIELDS);
  },

  async findFirst(args: {
    where?: Record<string, unknown>;
    include?: Record<string, unknown>;
    orderBy?: Record<string, string> | Record<string, string>[];
    select?: Record<string, boolean>;
  }) {
    if (!isConvex()) {
      return prisma.lead_pipeline_stages.findFirst(args as any);
    }

    const where = (args.where || {}) as Record<string, unknown>;
    const userId = where.userId as string | undefined;

    if (!userId) return null;

    const docs =
      (await convexQuery<ConvexDoc[]>("leads/queries:getPipelineStages", {
        userId,
      })) || [];

    // Apply orderBy if present
    let sorted = docs;
    if (args.orderBy && !Array.isArray(args.orderBy)) {
      const [field, dir] = Object.entries(args.orderBy)[0];
      sorted = [...docs].sort((a, b) => {
        const av = a[field] as number;
        const bv = b[field] as number;
        return dir === "desc" ? bv - av : av - bv;
      });
    }

    const match = sorted.find((doc) => {
      for (const [key, value] of Object.entries(where)) {
        if (key === "id") {
          if ((doc.prismaId || doc._id) !== value) return false;
        } else if (doc[key] !== value) {
          return false;
        }
      }
      return true;
    });

    return match ? convexToPrismaShape(match, STAGE_TS_FIELDS) : null;
  },

  async count(args?: { where?: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_pipeline_stages.count(args as any);
    }

    const where = (args?.where || {}) as Record<string, unknown>;
    const userId = where.userId as string | undefined;
    if (!userId) return 0;

    const docs =
      (await convexQuery<ConvexDoc[]>("leads/queries:getPipelineStages", {
        userId,
      })) || [];

    return docs.length;
  },

  async create(args: { data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_pipeline_stages.create(args as any);
    }

    const d = args.data;
    // Convex doesn't have a dedicated createPipelineStage mutation yet;
    // fall back to prisma for now. TODO: Add Convex mutation
    return prisma.lead_pipeline_stages.create(args as any);
  },

  async update(args: { where: { id: string }; data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_pipeline_stages.update(args as any);
    }

    // No dedicated Convex mutation for pipeline stage updates yet
    return prisma.lead_pipeline_stages.update(args as any);
  },

  async updateMany(args: {
    where: Record<string, unknown>;
    data: Record<string, unknown>;
  }): Promise<BatchResult> {
    if (!isConvex()) {
      return prisma.lead_pipeline_stages.updateMany(args as any);
    }

    // No dedicated Convex mutation; fall back to Prisma
    return prisma.lead_pipeline_stages.updateMany(args as any);
  },

  async delete(args: { where: { id: string } }) {
    if (!isConvex()) {
      return prisma.lead_pipeline_stages.delete(args as any);
    }

    return prisma.lead_pipeline_stages.delete(args as any);
  },
};

// ═══════════════════════════════════════════════════════════════════════════
// Lead Scoring Rules
// ═══════════════════════════════════════════════════════════════════════════

const leadScoringRules = {
  async findMany(args: {
    where?: Record<string, unknown>;
    orderBy?: Record<string, string> | Record<string, string>[];
  }) {
    if (!isConvex()) {
      return prisma.lead_scoring_rules.findMany(args as any);
    }

    // No dedicated Convex query for scoring rules yet; fall back to Prisma
    return prisma.lead_scoring_rules.findMany(args as any);
  },

  async findFirst(args: { where?: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_scoring_rules.findFirst(args as any);
    }

    return prisma.lead_scoring_rules.findFirst(args as any);
  },

  async create(args: { data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_scoring_rules.create(args as any);
    }

    return prisma.lead_scoring_rules.create(args as any);
  },

  async update(args: { where: { id: string }; data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_scoring_rules.update(args as any);
    }

    return prisma.lead_scoring_rules.update(args as any);
  },

  async delete(args: { where: { id: string } }) {
    if (!isConvex()) {
      return prisma.lead_scoring_rules.delete(args as any);
    }

    return prisma.lead_scoring_rules.delete(args as any);
  },
};

// ═══════════════════════════════════════════════════════════════════════════
// Lead Scoring Events
// ═══════════════════════════════════════════════════════════════════════════

const leadScoringEvents = {
  async findMany(args: {
    where?: Record<string, unknown>;
    orderBy?: Record<string, string> | Record<string, string>[];
    take?: number;
  }) {
    if (!isConvex()) {
      return prisma.lead_scoring_events.findMany(args as any);
    }

    // No dedicated Convex query for scoring events yet; fall back to Prisma
    return prisma.lead_scoring_events.findMany(args as any);
  },

  async create(args: { data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_scoring_events.create(args as any);
    }

    // The updateScore mutation handles scoring events creation in Convex
    return prisma.lead_scoring_events.create(args as any);
  },
};

// ═══════════════════════════════════════════════════════════════════════════
// Lead Capture Forms
// ═══════════════════════════════════════════════════════════════════════════

const leadCaptureForms = {
  async findMany(args: {
    where?: Record<string, unknown>;
    orderBy?: Record<string, string> | Record<string, string>[];
  }) {
    if (!isConvex()) {
      return prisma.lead_capture_forms.findMany(args as any);
    }

    // No dedicated Convex query for capture forms yet; fall back to Prisma
    return prisma.lead_capture_forms.findMany(args as any);
  },

  async findFirst(args: { where?: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_capture_forms.findFirst(args as any);
    }

    return prisma.lead_capture_forms.findFirst(args as any);
  },

  async findUnique(args: { where: { id: string } }) {
    if (!isConvex()) {
      return prisma.lead_capture_forms.findUnique(args as any);
    }

    return prisma.lead_capture_forms.findUnique(args as any);
  },

  async create(args: { data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_capture_forms.create(args as any);
    }

    return prisma.lead_capture_forms.create(args as any);
  },

  async update(args: { where: { id: string }; data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_capture_forms.update(args as any);
    }

    return prisma.lead_capture_forms.update(args as any);
  },

  async delete(args: { where: { id: string } }) {
    if (!isConvex()) {
      return prisma.lead_capture_forms.delete(args as any);
    }

    return prisma.lead_capture_forms.delete(args as any);
  },
};

// ═══════════════════════════════════════════════════════════════════════════
// Lead Nurture Sequences
// ═══════════════════════════════════════════════════════════════════════════

const leadNurtureSequences = {
  async findMany(args: {
    where?: Record<string, unknown>;
    include?: Record<string, unknown>;
    orderBy?: Record<string, string> | Record<string, string>[];
  }) {
    if (!isConvex()) {
      return prisma.lead_nurture_sequences.findMany(args as any);
    }

    // No dedicated Convex query for nurture sequences yet; fall back to Prisma
    return prisma.lead_nurture_sequences.findMany(args as any);
  },

  async findFirst(args: {
    where?: Record<string, unknown>;
    include?: Record<string, unknown>;
  }) {
    if (!isConvex()) {
      return prisma.lead_nurture_sequences.findFirst(args as any);
    }

    return prisma.lead_nurture_sequences.findFirst(args as any);
  },

  async create(args: {
    data: Record<string, unknown>;
    include?: Record<string, unknown>;
  }) {
    if (!isConvex()) {
      return prisma.lead_nurture_sequences.create(args as any);
    }

    return prisma.lead_nurture_sequences.create(args as any);
  },

  async update(args: {
    where: { id: string };
    data: Record<string, unknown>;
    include?: Record<string, unknown>;
  }) {
    if (!isConvex()) {
      return prisma.lead_nurture_sequences.update(args as any);
    }

    return prisma.lead_nurture_sequences.update(args as any);
  },

  async delete(args: { where: { id: string } }) {
    if (!isConvex()) {
      return prisma.lead_nurture_sequences.delete(args as any);
    }

    return prisma.lead_nurture_sequences.delete(args as any);
  },
};

// ═══════════════════════════════════════════════════════════════════════════
// Lead Nurture Steps
// ═══════════════════════════════════════════════════════════════════════════

const leadNurtureSteps = {
  async create(args: { data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_nurture_steps.create(args as any);
    }

    return prisma.lead_nurture_steps.create(args as any);
  },

  async deleteMany(args: {
    where: Record<string, unknown>;
  }): Promise<BatchResult> {
    if (!isConvex()) {
      return prisma.lead_nurture_steps.deleteMany(args as any);
    }

    return prisma.lead_nurture_steps.deleteMany(args as any);
  },
};

// ═══════════════════════════════════════════════════════════════════════════
// Lead Nurture Memberships
// ═══════════════════════════════════════════════════════════════════════════

const leadNurtureMemberships = {
  async findMany(args: {
    where?: Record<string, unknown>;
    include?: Record<string, unknown>;
    take?: number;
  }) {
    if (!isConvex()) {
      return prisma.lead_nurture_memberships.findMany(args as any);
    }

    // No dedicated Convex query yet; fall back to Prisma
    return prisma.lead_nurture_memberships.findMany(args as any);
  },

  async findUnique(args: { where: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_nurture_memberships.findUnique(args as any);
    }

    return prisma.lead_nurture_memberships.findUnique(args as any);
  },

  async create(args: { data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_nurture_memberships.create(args as any);
    }

    return prisma.lead_nurture_memberships.create(args as any);
  },

  async update(args: { where: { id: string }; data: Record<string, unknown> }) {
    if (!isConvex()) {
      return prisma.lead_nurture_memberships.update(args as any);
    }

    return prisma.lead_nurture_memberships.update(args as any);
  },

  async upsert(args: {
    where: Record<string, unknown>;
    create: Record<string, unknown>;
    update: Record<string, unknown>;
  }) {
    if (!isConvex()) {
      return prisma.lead_nurture_memberships.upsert(args as any);
    }

    return prisma.lead_nurture_memberships.upsert(args as any);
  },
};

// ═══════════════════════════════════════════════════════════════════════════
// Utility Helpers
// ═══════════════════════════════════════════════════════════════════════════

/**
 * Flatten Prisma relation-style data (e.g., { pipelineStage: { connect: { id } } })
 * into a simple object for merging with existing records.
 */
function flattenPrismaData(
  data: Record<string, unknown>,
): Record<string, unknown> {
  const result: Record<string, unknown> = {};
  for (const [key, value] of Object.entries(data)) {
    if (value !== undefined) {
      // Skip relation objects (connect/disconnect)
      if (
        typeof value === "object" &&
        value !== null &&
        !Array.isArray(value) &&
        !(value instanceof Date)
      ) {
        const obj = value as Record<string, unknown>;
        if ("connect" in obj || "disconnect" in obj || "increment" in obj) {
          continue; // Skip Prisma relation operations
        }
      }
      result[key] = value;
    }
  }
  return result;
}

// ═══════════════════════════════════════════════════════════════════════════
// Namespace Exports
// ═══════════════════════════════════════════════════════════════════════════

export const leadsAdapter = leads;
export const leadActivitiesAdapter = leadActivities;
export const leadPipelineStagesAdapter = leadPipelineStages;
export const leadScoringRulesAdapter = leadScoringRules;
export const leadScoringEventsAdapter = leadScoringEvents;
export const leadCaptureFormsAdapter = leadCaptureForms;
export const leadNurtureSequencesAdapter = leadNurtureSequences;
export const leadNurtureStepsAdapter = leadNurtureSteps;
export const leadNurtureMembershipsAdapter = leadNurtureMemberships;
