import { prisma } from "@/lib/prisma";
import { getDateRange, DateRange } from "./date-utils";

export type DealStage = "lead" | "qualified" | "proposal" | "negotiation" | "closed_won" | "closed_lost";
export type DealStatus = "open" | "won" | "lost";
export type CrmSource = "hubspot" | "salesforce" | "highlevel" | "manual";

/**
 * Get CRM deals for a brand with optional filters.
 */
export async function getDeals(
  brandId: string,
  range: DateRange = "30d",
  filters?: { status?: DealStatus; stage?: DealStage; source?: CrmSource }
) {
  const { start, end } = getDateRange(range);

  return prisma.crmDeal.findMany({
    where: {
      brandId,
      createdAt: { gte: start, lte: end },
      ...(filters?.status ? { status: filters.status } : {}),
      ...(filters?.stage ? { stage: filters.stage } : {}),
      ...(filters?.source ? { source: filters.source } : {}),
    },
    include: {
      conversion: true,
    },
    orderBy: { createdAt: "desc" },
  });
}

/**
 * Get CRM pipeline summary for a brand.
 */
export async function getPipelineSummary(brandId: string, range: DateRange = "30d") {
  const deals = await getDeals(brandId, range);

  const pipeline: Record<string, { count: number; value: number }> = {};
  const stages = ["lead", "qualified", "proposal", "negotiation", "closed_won", "closed_lost"];
  for (const stage of stages) {
    const stageDeals = deals.filter((d) => d.stage === stage);
    pipeline[stage] = {
      count: stageDeals.length,
      value: Math.round(stageDeals.reduce((s, d) => s + d.value, 0)),
    };
  }

  const totalValue = Math.round(deals.reduce((s, d) => s + d.value, 0));
  const wonValue = Math.round(deals.filter((d) => d.status === "won").reduce((s, d) => s + d.value, 0));
  const openValue = Math.round(deals.filter((d) => d.status === "open").reduce((s, d) => s + d.value, 0));
  const wonCount = deals.filter((d) => d.status === "won").length;
  const lostCount = deals.filter((d) => d.status === "lost").length;
  const winRate = wonCount + lostCount > 0 ? Math.round((wonCount / (wonCount + lostCount)) * 100) : 0;

  // By source
  const bySource: Record<string, { count: number; value: number }> = {};
  for (const d of deals) {
    if (!bySource[d.source]) bySource[d.source] = { count: 0, value: 0 };
    bySource[d.source].count++;
    bySource[d.source].value += d.value;
  }

  return {
    totalDeals: deals.length,
    totalValue,
    wonValue,
    openValue,
    wonCount,
    lostCount,
    winRate,
    pipeline,
    bySource,
    avgDealValue: deals.length > 0 ? Math.round(totalValue / deals.length) : 0,
  };
}

/**
 * Create or update a CRM deal.
 */
export async function upsertDeal(data: {
  brandId: string;
  externalId?: string;
  source?: CrmSource;
  contactName?: string;
  contactEmail?: string;
  dealName: string;
  value?: number;
  stage?: DealStage;
  status?: DealStatus;
  closeDate?: Date;
  conversionId?: string;
}) {
  if (data.externalId) {
    const existing = await prisma.crmDeal.findFirst({
      where: { brandId: data.brandId, externalId: data.externalId },
    });
    if (existing) {
      return prisma.crmDeal.update({
        where: { id: existing.id },
        data: {
          dealName: data.dealName,
          value: data.value,
          stage: data.stage,
          status: data.status,
          closeDate: data.closeDate,
          contactName: data.contactName,
          contactEmail: data.contactEmail,
        },
      });
    }
  }

  return prisma.crmDeal.create({
    data: {
      brandId: data.brandId,
      externalId: data.externalId,
      source: data.source ?? "manual",
      contactName: data.contactName,
      contactEmail: data.contactEmail,
      dealName: data.dealName,
      value: data.value ?? 0,
      stage: data.stage ?? "lead",
      status: data.status ?? "open",
      closeDate: data.closeDate,
      conversionId: data.conversionId,
    },
  });
}
