import { eq, and, isNull, desc, gte, lte, ilike, or } from "drizzle-orm";
import { db } from "@/db";
import { leads, activities, reminders, quotes, clientTranscripts } from "@/db/schema";

// Get all leads
export async function getAllLeads(limit: number = 100, offset: number = 0) {
  return await db
    .select()
    .from(leads)
    .orderBy(desc(leads.updated_at))
    .limit(limit)
    .offset(offset);
}

// Get lead by ID
export async function getLeadById(id: string) {
  const [lead] = await db
    .select()
    .from(leads)
    .where(eq(leads.id, id));
  return lead;
}

// Get leads by stage
export async function getLeadsByStage(stage: string) {
  return await db
    .select()
    .from(leads)
    .where(eq(leads.status, stage))
    .orderBy(desc(leads.last_contact_date));
}

// Get leads needing follow-up
export async function getLeadsNeedingFollowUp(daysAgo: number = 7) {
  const cutoffDate = new Date();
  cutoffDate.setDate(cutoffDate.getDate() - daysAgo);

  return await db
    .select()
    .from(leads)
    .where(
      or(
        isNull(leads.last_contact_date),
        lte(leads.last_contact_date, cutoffDate)
      )
    )
    .orderBy(leads.created_at);
}

// Get activity log
export async function getActivityLog(leadId: string) {
  return await db
    .select()
    .from(activities)
    .where(eq(activities.lead_id, leadId))
    .orderBy(desc(activities.activity_date));
}

// Get upcoming reminders
export async function getUpcomingReminders(leadId: string) {
  return await db
    .select()
    .from(reminders)
    .where(and(eq(reminders.lead_id, leadId), isNull(reminders.completed_at)))
    .orderBy(reminders.due_date);
}

// Get overdue reminders
export async function getOverdueReminders() {
  const now = new Date();
  return await db
    .select()
    .from(reminders)
    .where(and(lte(reminders.due_date, now), isNull(reminders.completed_at)))
    .orderBy(reminders.due_date);
}

// Create activity and auto-update last_contact_date
export async function createActivity(data: {
  lead_id: string;
  type: string;
  activity_date: Date | string;
  duration_minutes?: number;
  notes: string;
}) {
  const activityDate =
    typeof data.activity_date === "string"
      ? new Date(data.activity_date)
      : data.activity_date;

  const [activity] = await db
    .insert(activities)
    .values({
      lead_id: data.lead_id,
      type: data.type,
      activity_date: activityDate,
      duration_minutes: data.duration_minutes,
      notes: data.notes,
    })
    .returning();

  // Auto-update lead.last_contact_date
  await db
    .update(leads)
    .set({ last_contact_date: activityDate, updated_at: new Date() })
    .where(eq(leads.id, data.lead_id));

  return activity;
}

// Update lead stage
export async function updateLeadStage(leadId: string, stage: string) {
  const [updated] = await db
    .update(leads)
    .set({ status: stage, updated_at: new Date() })
    .where(eq(leads.id, leadId))
    .returning();
  return updated;
}

// Update lead
export async function updateLead(
  leadId: string,
  data: Partial<{
    name: string;
    email: string;
    phone: string;
    company: string;
    notes: string;
    next_action: string;
    next_action_date: Date | string;
  }>
) {
  const updateData: Record<string, any> = { updated_at: new Date() };

  if (data.name !== undefined) updateData.name = data.name;
  if (data.email !== undefined) updateData.email = data.email;
  if (data.phone !== undefined) updateData.phone = data.phone;
  if (data.company !== undefined) updateData.company = data.company;
  if (data.notes !== undefined) updateData.notes = data.notes;
  if (data.next_action !== undefined) updateData.next_action = data.next_action;
  if (data.next_action_date !== undefined) {
    updateData.next_action_date =
      typeof data.next_action_date === "string"
        ? new Date(data.next_action_date)
        : data.next_action_date;
  }

  const [updated] = await db
    .update(leads)
    .set(updateData)
    .where(eq(leads.id, leadId))
    .returning();
  return updated;
}

// Search leads
export async function searchLeads(query: string) {
  return await db
    .select()
    .from(leads)
    .where(
      or(
        ilike(leads.name, `%${query}%`),
        ilike(leads.email, `%${query}%`),
        ilike(leads.company, `%${query}%`)
      )
    )
    .orderBy(desc(leads.updated_at));
}

// Create reminder
export async function createReminder(data: {
  lead_id: string;
  title: string;
  description?: string;
  due_date: Date | string;
}) {
  const dueDate =
    typeof data.due_date === "string" ? new Date(data.due_date) : data.due_date;

  const [reminder] = await db
    .insert(reminders)
    .values({
      lead_id: data.lead_id,
      title: data.title,
      description: data.description,
      due_date: dueDate,
    })
    .returning();
  return reminder;
}

// Complete reminder
export async function completeReminder(reminderId: string) {
  const [updated] = await db
    .update(reminders)
    .set({ completed_at: new Date() })
    .where(eq(reminders.id, reminderId))
    .returning();
  return updated;
}

// Get quotes by lead
export async function getQuotesByLeadId(leadId: string) {
  return await db
    .select()
    .from(quotes)
    .where(eq(quotes.lead_id, leadId))
    .orderBy(desc(quotes.created_at));
}

// Get transcript log for a lead — call_date DESC (D-05)
// Returns all fields including full content (Phase 21 reads them in bulk).
export async function getTranscripts(leadId: string) {
  return await db
    .select()
    .from(clientTranscripts)
    .where(eq(clientTranscripts.lead_id, leadId))
    .orderBy(desc(clientTranscripts.call_date));
}

// Get transcripts linked to a client (post lead→client conversion).
// Returns all fields — used by admin DocumentsTab and public TranscriptsSection.
export async function getTranscriptsByClientId(clientId: string) {
  return await db
    .select()
    .from(clientTranscripts)
    .where(eq(clientTranscripts.client_id, clientId))
    .orderBy(desc(clientTranscripts.call_date));
}
