/**
 * Lead CRM Service
 * Core CRUD, pipeline, activities, stats, and export for leads
 *
 * Wired to use leads adapter for Convex migration (strangler fig pattern).
 * All prisma.leads.*, prisma.lead_activities.*, and prisma.lead_pipeline_stages.*
 * calls are routed through the adapter. prisma.users.* calls remain direct.
 */

import { prisma } from '@/lib/db';
import { logger } from '@/lib/logger';
import { createId } from '@paralleldrive/cuid2';
import type {
  LeadInput,
  LeadOutput,
  LeadUpdateInput,
  LeadBulkInput,
  LeadFilters,
  LeadStats,
  LeadExportOptions,
  LeadActivityInput,
  LeadActivityOutput,
  PipelineStageInput,
  PipelineStageOutput,
  PipelineView,
  LeadGrade,
  LeadActivityType,
} from '@/lib/types/lead-crm.types';
import { getLeadGrade, DEFAULT_PIPELINE_STAGES } from '@/lib/types/lead-crm.types';
/** JSON-compatible input value (replaces InputJsonValue) */
type InputJsonValue = string | number | boolean | null | InputJsonValue[] | { [key: string]: InputJsonValue };
/** Represents JSON null (replaces JsonNull) */
const JsonNull = null;

import {
  leadsAdapter,
  leadActivitiesAdapter,
  leadPipelineStagesAdapter,
} from '@/lib/adapters/leads';

const log = logger.scope('LeadCRMService');

// ═══════════════════════════════════════════════════════════════════════
// Lead CRUD
// ═══════════════════════════════════════════════════════════════════════

export async function createLead(userId: string, input: LeadInput): Promise<LeadOutput> {
  // Auto-create default pipeline stages if user has none
  const existingStages = await leadPipelineStagesAdapter.count({ where: { userId } });
  if (existingStages === 0) {
    await createDefaultPipelineStages(userId);
  }

  // Find default stage
  const defaultStage = await leadPipelineStagesAdapter.findFirst({
    where: { userId, isDefault: true },
  });

  const id = createId();
  const now = new Date();

  const lead = await leadsAdapter.create({
    data: {
      id,
      userId,
      name: input.name,
      phone: input.phone ?? null,
      email: input.email ?? null,
      company: input.company ?? null,
      source: input.source,
      campaignId: input.campaignId ?? null,
      interest: input.interest ?? null,
      notes: input.notes ?? null,
      customFields: (input.customFields ?? {}) as InputJsonValue,
      metadata: {} as InputJsonValue,
      tags: input.tags ?? [],
      language: input.language ?? 'en',
      sourceChannel: input.sourceChannel ?? null,
      dealValue: input.dealValue ?? null,
      dealCurrency: input.dealCurrency ?? 'QAR',
      pipelineStageId: defaultStage?.id ?? null,
      firstTouchAt: now,
      lastActivityAt: now,
      touchCount: 1,
      updatedAt: now,
    },
    include: { pipelineStage: true },
  });

  // Log creation activity
  await addActivityInternal(lead.id, userId, {
    type: 'NOTE',
    title: 'Lead created',
    description: `Lead "${lead.name}" created from source: ${lead.source}`,
  });

  log.info('Lead created', { leadId: lead.id, userId });
  return mapLeadToOutput(lead);
}

export async function getLeadById(userId: string, leadId: string): Promise<LeadOutput | null> {
  const lead = await leadsAdapter.findFirst({
    where: { id: leadId, userId },
    include: {
      pipelineStage: true,
      activities: { orderBy: { createdAt: 'desc' }, take: 10 },
    },
  });
  if (!lead) return null;
  return mapLeadToOutput(lead);
}

export async function updateLead(userId: string, leadId: string, input: LeadUpdateInput): Promise<LeadOutput | null> {
  const existing = await leadsAdapter.findFirst({ where: { id: leadId, userId } });
  if (!existing) return null;

  const data: Record<string, unknown> = {
    ...(input.name !== undefined && { name: input.name }),
    ...(input.phone !== undefined && { phone: input.phone }),
    ...(input.email !== undefined && { email: input.email }),
    ...(input.company !== undefined && { company: input.company }),
    ...(input.status !== undefined && { status: input.status }),
    ...(input.interest !== undefined && { interest: input.interest }),
    ...(input.notes !== undefined && { notes: input.notes }),
    ...(input.customFields !== undefined && { customFields: input.customFields as InputJsonValue }),
    ...(input.tags !== undefined && { tags: input.tags }),
    ...(input.assignedTo !== undefined && { assignedTo: input.assignedTo }),
    ...(input.pipelineStageId !== undefined && { pipelineStage: input.pipelineStageId ? { connect: { id: input.pipelineStageId } } : { disconnect: true } }),
    ...(input.dealValue !== undefined && { dealValue: input.dealValue }),
    ...(input.dealCurrency !== undefined && { dealCurrency: input.dealCurrency }),
    ...(input.expectedCloseAt !== undefined && { expectedCloseAt: input.expectedCloseAt }),
    ...(input.lostReason !== undefined && { lostReason: input.lostReason }),
    ...(input.language !== undefined && { language: input.language }),
    updatedAt: new Date(),
  };

  // Log status change
  if (input.status && input.status !== existing.status) {
    await addActivityInternal(leadId, userId, {
      type: 'STATUS_CHANGE',
      title: `Status changed to ${input.status}`,
      metadata: { from: existing.status, to: input.status },
    });
    if (input.status === 'converted') {
      (data as Record<string, unknown>).convertedAt = new Date();
    }
  }

  // Log stage change
  if (input.pipelineStageId && input.pipelineStageId !== existing.pipelineStageId) {
    await addActivityInternal(leadId, userId, {
      type: 'STAGE_CHANGE',
      title: 'Pipeline stage changed',
      metadata: { from: existing.pipelineStageId, to: input.pipelineStageId },
    });
  }

  const lead = await leadsAdapter.update({
    where: { id: leadId },
    data: data as Record<string, unknown>,
    include: { pipelineStage: true },
  });

  return mapLeadToOutput(lead as Record<string, unknown>);
}

export async function deleteLead(userId: string, leadId: string): Promise<boolean> {
  const existing = await leadsAdapter.findFirst({ where: { id: leadId, userId } });
  if (!existing) return false;

  await leadsAdapter.delete({ where: { id: leadId } });
  log.info('Lead deleted', { leadId, userId });
  return true;
}

export async function listLeads(
  userId: string,
  filters: LeadFilters & { page?: number; limit?: number; sortBy?: string; sortOrder?: 'asc' | 'desc' },
): Promise<{ leads: LeadOutput[]; total: number; page: number; limit: number; totalPages: number }> {
  const page = filters.page ?? 1;
  const limit = Math.min(filters.limit ?? 20, 100);
  const skip = (page - 1) * limit;
  const sortBy = filters.sortBy ?? 'createdAt';
  const sortOrder = filters.sortOrder ?? 'desc';

  const where: Record<string, unknown> = { userId };

  if (filters.status) where.status = filters.status;
  if (filters.source) where.source = filters.source;
  if (filters.pipelineStageId) where.pipelineStageId = filters.pipelineStageId;
  if (filters.assignedTo) where.assignedTo = filters.assignedTo;
  if (filters.minScore !== undefined || filters.maxScore !== undefined) {
    const scoreFilter: Record<string, number> = {};
    if (filters.minScore !== undefined) scoreFilter.gte = filters.minScore;
    if (filters.maxScore !== undefined) scoreFilter.lte = filters.maxScore;
    where.score = scoreFilter;
  }
  if (filters.tags && filters.tags.length > 0) {
    where.tags = { hasSome: filters.tags };
  }
  if (filters.dateFrom || filters.dateTo) {
    const dateFilter: Record<string, Date> = {};
    if (filters.dateFrom) dateFilter.gte = filters.dateFrom;
    if (filters.dateTo) dateFilter.lte = filters.dateTo;
    where.createdAt = dateFilter;
  }
  if (filters.search) {
    where.OR = [
      { name: { contains: filters.search, mode: 'insensitive' } },
      { email: { contains: filters.search, mode: 'insensitive' } },
      { phone: { contains: filters.search, mode: 'insensitive' } },
      { company: { contains: filters.search, mode: 'insensitive' } },
    ];
  }

  const [leads, total] = await Promise.all([
    leadsAdapter.findMany({
      where: where as Record<string, unknown>,
      include: { pipelineStage: true },
      orderBy: { [sortBy]: sortOrder },
      skip,
      take: limit,
    }),
    leadsAdapter.count({ where: where as Record<string, unknown> }),
  ]);

  return {
    leads: leads.map(mapLeadToOutput),
    total,
    page,
    limit,
    totalPages: Math.ceil(total / limit),
  };
}

export async function bulkAction(userId: string, input: LeadBulkInput): Promise<number> {
  const { leadIds, action, value } = input;

  // Verify ownership
  const ownedLeads = await leadsAdapter.findMany({
    where: { id: { in: leadIds }, userId },
    select: { id: true },
  });
  const ownedIds = (ownedLeads as { id: string }[]).map((l) => l.id);
  if (ownedIds.length === 0) return 0;

  switch (action) {
    case 'assign':
      await leadsAdapter.updateMany({ where: { id: { in: ownedIds } }, data: { assignedTo: value ?? null, updatedAt: new Date() } });
      break;
    case 'move_stage':
      await leadsAdapter.updateMany({ where: { id: { in: ownedIds } }, data: { pipelineStageId: value ?? null, updatedAt: new Date() } });
      break;
    case 'add_tag':
      if (value) {
        for (const id of ownedIds) {
          const lead = await leadsAdapter.findUnique({ where: { id }, select: { tags: true } }) as { tags: string[] } | null;
          if (lead && !lead.tags.includes(value)) {
            await leadsAdapter.update({ where: { id }, data: { tags: [...lead.tags, value], updatedAt: new Date() } });
          }
        }
      }
      break;
    case 'remove_tag':
      if (value) {
        for (const id of ownedIds) {
          const lead = await leadsAdapter.findUnique({ where: { id }, select: { tags: true } }) as { tags: string[] } | null;
          if (lead) {
            await leadsAdapter.update({ where: { id }, data: { tags: lead.tags.filter((t) => t !== value), updatedAt: new Date() } });
          }
        }
      }
      break;
    case 'delete':
      await leadsAdapter.deleteMany({ where: { id: { in: ownedIds } } });
      break;
  }

  log.info('Bulk action completed', { action, count: ownedIds.length, userId });
  return ownedIds.length;
}

// ═══════════════════════════════════════════════════════════════════════
// Pipeline
// ═══════════════════════════════════════════════════════════════════════

export async function getPipelineView(userId: string): Promise<PipelineView> {
  const stages = await leadPipelineStagesAdapter.findMany({
    where: { userId },
    orderBy: { sortOrder: 'asc' },
    include: {
      leads: {
        orderBy: { updatedAt: 'desc' },
        include: { pipelineStage: true },
      },
    },
  }) as Record<string, unknown>[];

  const totalLeads = stages.reduce((sum, s) => sum + ((s.leads as unknown[]) || []).length, 0);
  const totalDealValue = stages.reduce(
    (sum, s) => sum + ((s.leads as Record<string, unknown>[]) || []).reduce((sv, l) => sv + ((l.dealValue as number) ?? 0), 0),
    0,
  );

  return {
    stages: stages.map((s) => ({
      ...mapStageToOutput(s),
      leadsCount: ((s.leads as unknown[]) || []).length,
      leads: ((s.leads as Record<string, unknown>[]) || []).map(mapLeadToOutput),
    })),
    totalLeads,
    totalDealValue,
  };
}

export async function createPipelineStage(userId: string, input: PipelineStageInput): Promise<PipelineStageOutput> {
  const maxOrder = await leadPipelineStagesAdapter.findFirst({
    where: { userId },
    orderBy: { sortOrder: 'desc' },
    select: { sortOrder: true },
  }) as { sortOrder: number } | null;

  const stage = await leadPipelineStagesAdapter.create({
    data: {
      id: createId(),
      userId,
      name: input.name,
      nameAr: input.nameAr ?? null,
      color: input.color ?? '#6366f1',
      sortOrder: input.sortOrder ?? (maxOrder ? maxOrder.sortOrder + 1 : 0),
      isDefault: input.isDefault ?? false,
      isWon: input.isWon ?? false,
      isLost: input.isLost ?? false,
    },
  });

  return mapStageToOutput(stage as Record<string, unknown>);
}

export async function updatePipelineStage(userId: string, stageId: string, input: Partial<PipelineStageInput>): Promise<PipelineStageOutput | null> {
  const existing = await leadPipelineStagesAdapter.findFirst({ where: { id: stageId, userId } });
  if (!existing) return null;

  const stage = await leadPipelineStagesAdapter.update({
    where: { id: stageId },
    data: {
      ...(input.name !== undefined && { name: input.name }),
      ...(input.nameAr !== undefined && { nameAr: input.nameAr }),
      ...(input.color !== undefined && { color: input.color }),
      ...(input.sortOrder !== undefined && { sortOrder: input.sortOrder }),
      ...(input.isDefault !== undefined && { isDefault: input.isDefault }),
      ...(input.isWon !== undefined && { isWon: input.isWon }),
      ...(input.isLost !== undefined && { isLost: input.isLost }),
    },
  });

  return mapStageToOutput(stage as Record<string, unknown>);
}

export async function deletePipelineStage(userId: string, stageId: string): Promise<boolean> {
  const existing = await leadPipelineStagesAdapter.findFirst({ where: { id: stageId, userId } });
  if (!existing) return false;

  // Unlink leads from this stage
  await leadsAdapter.updateMany({ where: { pipelineStageId: stageId }, data: { pipelineStageId: null, updatedAt: new Date() } });
  await leadPipelineStagesAdapter.delete({ where: { id: stageId } });
  return true;
}

export async function listPipelineStages(userId: string): Promise<PipelineStageOutput[]> {
  const stages = await leadPipelineStagesAdapter.findMany({
    where: { userId },
    orderBy: { sortOrder: 'asc' },
    include: { _count: { select: { leads: true } } },
  }) as Record<string, unknown>[];

  return stages.map((s) => ({
    ...mapStageToOutput(s),
    leadsCount: (s._count as { leads: number })?.leads ?? 0,
  }));
}

export async function reorderPipelineStages(userId: string, stages: { id: string; sortOrder: number }[]): Promise<boolean> {
  await Promise.all(
    stages.map((s) =>
      leadPipelineStagesAdapter.updateMany({
        where: { id: s.id, userId },
        data: { sortOrder: s.sortOrder },
      }),
    ),
  );
  return true;
}

export async function moveLead(userId: string, leadId: string, stageId: string): Promise<LeadOutput | null> {
  const existing = await leadsAdapter.findFirst({ where: { id: leadId, userId } }) as Record<string, unknown> | null;
  if (!existing) return null;

  const stage = await leadPipelineStagesAdapter.findFirst({ where: { id: stageId, userId } }) as Record<string, unknown> | null;
  if (!stage) return null;

  await addActivityInternal(leadId, userId, {
    type: 'STAGE_CHANGE',
    title: `Moved to "${stage.name}"`,
    metadata: { from: existing.pipelineStageId as string, to: stageId },
  });

  const updateData: Record<string, unknown> = {
    pipelineStageId: stageId,
    updatedAt: new Date(),
  };
  if (stage.isWon) { updateData.status = 'won'; updateData.convertedAt = new Date(); }
  if (stage.isLost) { updateData.status = 'lost'; }

  const lead = await leadsAdapter.update({
    where: { id: leadId },
    data: updateData,
    include: { pipelineStage: true },
  });

  return mapLeadToOutput(lead as Record<string, unknown>);
}

// ═══════════════════════════════════════════════════════════════════════
// Activities
// ═══════════════════════════════════════════════════════════════════════

export async function getActivities(
  leadId: string,
  page = 1,
  limit = 20,
): Promise<{ activities: LeadActivityOutput[]; total: number }> {
  const skip = (page - 1) * limit;
  const [activities, total] = await Promise.all([
    leadActivitiesAdapter.findMany({
      where: { leadId },
      orderBy: { createdAt: 'desc' },
      skip,
      take: limit,
    }),
    leadActivitiesAdapter.count({ where: { leadId } }),
  ]);

  return {
    activities: (activities as Record<string, unknown>[]).map(mapActivityToOutput),
    total,
  };
}

export async function addActivity(userId: string, leadId: string, input: LeadActivityInput): Promise<LeadActivityOutput> {
  // Verify lead ownership
  const lead = await leadsAdapter.findFirst({ where: { id: leadId, userId } });
  if (!lead) throw new Error('Lead not found');

  return addActivityInternal(leadId, userId, input);
}

async function addActivityInternal(
  leadId: string,
  userId: string,
  input: LeadActivityInput & { metadata?: Record<string, unknown> },
): Promise<LeadActivityOutput> {
  const activity = await leadActivitiesAdapter.create({
    data: {
      id: createId(),
      leadId,
      userId,
      type: input.type as LeadActivityType,
      title: input.title,
      description: input.description ?? null,
      metadata: input.metadata ? (input.metadata as InputJsonValue) : JsonNull,
    },
  });

  // Update lead touch tracking
  await leadsAdapter.update({
    where: { id: leadId },
    data: {
      lastActivityAt: new Date(),
      lastContactAt: ['CALL', 'EMAIL', 'MEETING', 'WHATSAPP'].includes(input.type) ? new Date() : undefined,
      touchCount: { increment: 1 },
      updatedAt: new Date(),
    },
  });

  return mapActivityToOutput(activity);
}

// ═══════════════════════════════════════════════════════════════════════
// Stats & Export
// ═══════════════════════════════════════════════════════════════════════

export async function getStats(userId: string): Promise<LeadStats> {
  const leads = await leadsAdapter.findMany({
    where: { userId },
    select: { status: true, source: true, pipelineStageId: true, score: true, dealValue: true },
  }) as { status: string; source: string; pipelineStageId: string | null; score: number; dealValue: number | null }[];

  const total = leads.length;
  const byStatus: Record<string, number> = {};
  const bySource: Record<string, number> = {};
  const byStage: Record<string, number> = {};
  let totalScore = 0;
  let convertedCount = 0;
  let totalDealValue = 0;

  for (const lead of leads) {
    byStatus[lead.status] = (byStatus[lead.status] ?? 0) + 1;
    bySource[lead.source] = (bySource[lead.source] ?? 0) + 1;
    if (lead.pipelineStageId) {
      byStage[lead.pipelineStageId] = (byStage[lead.pipelineStageId] ?? 0) + 1;
    }
    totalScore += lead.score;
    if (lead.status === 'converted' || lead.status === 'won') convertedCount++;
    totalDealValue += lead.dealValue ?? 0;
  }

  return {
    total,
    byStatus,
    bySource,
    byStage,
    averageScore: total > 0 ? Math.round(totalScore / total) : 0,
    conversionRate: total > 0 ? Math.round((convertedCount / total) * 10000) / 100 : 0,
    totalDealValue,
  };
}

export async function exportLeads(
  userId: string,
  options: LeadExportOptions,
): Promise<{ data: string; contentType: string; filename: string }> {
  const result = await listLeads(userId, { ...options.filters, limit: 10000, page: 1 });

  if (options.format === 'json') {
    return {
      data: JSON.stringify(result.leads, null, 2),
      contentType: 'application/json',
      filename: `leads-export-${Date.now()}.json`,
    };
  }

  // CSV export
  const headers = ['ID', 'Name', 'Email', 'Phone', 'Company', 'Source', 'Status', 'Score', 'Deal Value', 'Tags', 'Created'];
  const rows = result.leads.map((l) => [
    l.id,
    l.name,
    l.email ?? '',
    l.phone ?? '',
    l.company ?? '',
    l.source,
    l.status,
    String(l.score),
    String(l.dealValue ?? 0),
    l.tags.join(';'),
    l.createdAt.toISOString(),
  ]);

  const csv = [headers.join(','), ...rows.map((r) => r.map((v) => `"${String(v).replace(/"/g, '""')}"`).join(','))].join('\n');

  return {
    data: csv,
    contentType: 'text/csv',
    filename: `leads-export-${Date.now()}.csv`,
  };
}

export async function getConversionFunnel(userId: string): Promise<{ stageName: string; count: number; percentage: number }[]> {
  const stages = await leadPipelineStagesAdapter.findMany({
    where: { userId },
    orderBy: { sortOrder: 'asc' },
    include: { _count: { select: { leads: true } } },
  }) as Record<string, unknown>[];

  const totalLeads = stages.reduce((sum, s) => sum + ((s._count as { leads: number })?.leads ?? 0), 0);

  return stages.map((s) => ({
    stageName: s.name as string,
    count: (s._count as { leads: number })?.leads ?? 0,
    percentage: totalLeads > 0 ? Math.round(((s._count as { leads: number })?.leads ?? 0) / totalLeads * 10000) / 100 : 0,
  }));
}

// ═══════════════════════════════════════════════════════════════════════
// Helpers
// ═══════════════════════════════════════════════════════════════════════

async function createDefaultPipelineStages(userId: string): Promise<void> {
  await Promise.all(
    DEFAULT_PIPELINE_STAGES.map((stage, index) =>
      leadPipelineStagesAdapter.create({
        data: {
          id: createId(),
          userId,
          name: stage.name,
          nameAr: stage.nameAr ?? null,
          color: stage.color ?? '#6366f1',
          sortOrder: index,
          isDefault: stage.isDefault ?? false,
          isWon: stage.isWon ?? false,
          isLost: stage.isLost ?? false,
        },
      }),
    ),
  );
  log.info('Default pipeline stages created', { userId });
}

function mapLeadToOutput(lead: Record<string, unknown>): LeadOutput {
  const l = lead as Record<string, unknown>;
  return {
    id: l.id as string,
    userId: l.userId as string,
    organizationId: (l.organizationId as string) ?? null,
    name: l.name as string,
    phone: (l.phone as string) ?? null,
    email: (l.email as string) ?? null,
    company: (l.company as string) ?? null,
    source: l.source as string,
    campaignId: (l.campaignId as string) ?? null,
    interest: (l.interest as string) ?? null,
    notes: (l.notes as string) ?? null,
    customFields: (l.customFields as Record<string, unknown>) ?? {},
    metadata: (l.metadata as Record<string, unknown>) ?? {},
    status: l.status as string,
    score: l.score as number,
    convertedAt: (l.convertedAt as Date) ?? null,
    lastContactAt: (l.lastContactAt as Date) ?? null,
    assignedTo: (l.assignedTo as string) ?? null,
    pipelineStageId: (l.pipelineStageId as string) ?? null,
    dealValue: (l.dealValue as number) ?? null,
    dealCurrency: (l.dealCurrency as string) ?? null,
    expectedCloseAt: (l.expectedCloseAt as Date) ?? null,
    lostReason: (l.lostReason as string) ?? null,
    qualifiedAt: (l.qualifiedAt as Date) ?? null,
    qualificationScore: (l.qualificationScore as number) ?? null,
    tags: (l.tags as string[]) ?? [],
    language: (l.language as string) ?? null,
    captureFormId: (l.captureFormId as string) ?? null,
    sourceChannel: (l.sourceChannel as string) ?? null,
    firstTouchAt: (l.firstTouchAt as Date) ?? null,
    lastActivityAt: (l.lastActivityAt as Date) ?? null,
    touchCount: (l.touchCount as number) ?? 0,
    createdAt: l.createdAt as Date,
    updatedAt: l.updatedAt as Date,
    pipelineStage: l.pipelineStage ? mapStageToOutput(l.pipelineStage as Record<string, unknown>) : undefined,
    activities: l.activities ? (l.activities as Record<string, unknown>[]).map(mapActivityToOutput) : undefined,
    grade: getLeadGrade(l.score as number) as LeadGrade,
  };
}

function mapStageToOutput(stage: Record<string, unknown>): PipelineStageOutput {
  const s = stage as Record<string, unknown>;
  return {
    id: s.id as string,
    userId: s.userId as string,
    name: s.name as string,
    nameAr: (s.nameAr as string) ?? null,
    color: (s.color as string) ?? '#6366f1',
    sortOrder: s.sortOrder as number,
    isDefault: s.isDefault as boolean,
    isWon: s.isWon as boolean,
    isLost: s.isLost as boolean,
    createdAt: s.createdAt as Date,
    updatedAt: s.updatedAt as Date,
  };
}

function mapActivityToOutput(activity: Record<string, unknown>): LeadActivityOutput {
  const a = activity as Record<string, unknown>;
  return {
    id: a.id as string,
    leadId: a.leadId as string,
    userId: a.userId as string,
    type: a.type as LeadActivityType,
    title: a.title as string,
    description: (a.description as string) ?? null,
    metadata: (a.metadata as Record<string, unknown>) ?? null,
    createdAt: a.createdAt as Date,
  };
}

// Alias for backward compatibility
export const getLeads = listLeads;
export const LeadCRM = {
  getLeads: listLeads,
  createLead,
  getLeadById,
  updateLead,
  deleteLead,
  listLeads,
  bulkAction,
  getPipelineView,
  getStats,
  exportLeads,
  getConversionFunnel,
};
