import { NextRequest, NextResponse } from "next/server"
import { getSessionUser } from "@/lib/auth"
import { query } from "@/lib/db"
import { avatarSvgUrl } from "@/lib/avatar"

function getPeriodDateRange(period: string): { start: Date; end: Date } {
  const end = new Date()
  let start: Date
  switch (period) {
    case "7days":
      start = new Date(end); start.setDate(start.getDate() - 7); break
    case "30days":
      start = new Date(end); start.setDate(start.getDate() - 30); break
    case "12months":
      start = new Date(end); start.setFullYear(start.getFullYear() - 12); break
    case "6months":
    default:
      start = new Date(end); start.setMonth(start.getMonth() - 6); break
  }
  return { start, end }
}

function getPreviousPeriodRange(period: string, currentStart: Date): { start: Date; end: Date } {
  const end = new Date(currentStart)
  const diff = end.getTime() - currentStart.getTime()
  const start = new Date(end.getTime() - diff)
  return { start, end }
}

const periodLabels: Record<string, string> = {
  "7days": "Last 7 days",
  "30days": "Last 30 days",
  "6months": "Last 6 months",
  "12months": "Last 12 months",
}

function stageToStatus(name: string): string {
  switch (name) {
    case "New": return "open"
    case "Contacted": return "contacted"
    case "Qualified":
    case "Interested":
    case "Demo Scheduled":
    case "Negotiation": return "pending"
    case "Closed Won": return "closed"
    case "Closed Lost": return "ignored"
    default: return "open"
  }
}

async function fetchLeadsInRange(start: Date, end: Date, userId?: string, isAdmin?: boolean) {
  const result = await query(
    `SELECT l.id, l.created_at, l.company_name, l.contact_name, l.email, l.phone,
            l.notes, l.assigned_to, l.score,
            ls.name AS stage_name,
            u.id AS user_id, u.first_name, u.last_name, u.email AS user_email, u.avatar_url
     FROM leads l
     JOIN lead_stages ls ON ls.id = l.stage_id
     LEFT JOIN users u ON u.id = l.assigned_to
     WHERE l.deleted_at IS NULL
       AND l.created_at >= $1 AND l.created_at <= $2
       ${isAdmin ? "" : "AND l.assigned_to = $3"}
     ORDER BY l.created_at DESC`,
    isAdmin
      ? [start.toISOString(), end.toISOString()]
      : [start.toISOString(), end.toISOString(), userId]
  )
  return result.rows.map((r: any) => ({
    ...r,
    status: stageToStatus(r.stage_name),
  }))
}

function countStatuses(leads: any[]) {
  const counts = { open: 0, contacted: 0, pending: 0, closed: 0, ignored: 0 }
  leads.forEach((l: any) => {
    const s = l.status as keyof typeof counts
    if (s in counts) counts[s]++
  })
  return counts
}

function buildMonthlyBreakdown(leads: any[], period: string, rangeOverride?: { start: Date; end: Date }) {
  const { start, end } = rangeOverride || getPeriodDateRange(period)
  const result: { label: string; total: number; open: number; contacted: number; pending: number; closed: number; ignored: number }[] = []
  const current = new Date(start)
  const isMonthly = period === "6months" || period === "12months"

  while (current <= end) {
    const label = isMonthly
      ? current.toLocaleDateString("en-US", { month: "short", year: "2-digit" })
      : current.toLocaleDateString("en-US", { month: "short", day: "numeric" })

    const ps = new Date(current)
    const pe = isMonthly
      ? new Date(current.getFullYear(), current.getMonth() + 1, 0, 23, 59, 59)
      : (() => { const d = new Date(current); d.setHours(23, 59, 59, 999); return d })()

    const inPeriod = leads.filter((l: any) => {
      const d = new Date(l.created_at)
      return d >= ps && d <= pe
    })

    const counts = countStatuses(inPeriod)
    result.push({ label, total: inPeriod.length, ...counts })

    if (isMonthly) current.setMonth(current.getMonth() + 1)
    else current.setDate(current.getDate() + 1)
  }
  return result
}

function computeTrend(current: number, previous: number): { pct: number; up: boolean } {
  if (previous === 0) return { pct: current > 0 ? 100 : 0, up: current > 0 }
  const pct = Math.round(((current - previous) / previous) * 100)
  return { pct: Math.abs(pct), up: pct >= 0 }
}

export async function GET(request: NextRequest) {
  try {
    const user = await getSessionUser()
    if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 })

    const isAdmin = user.role === "admin" || user.role === "super_admin"

    const { searchParams } = new URL(request.url)
    const period = searchParams.get("period") || "6months"
    const yearParam = searchParams.get("year")
    let start: Date, end: Date, prevRange: { start: Date; end: Date }
    if (yearParam) {
      const y = parseInt(yearParam)
      start = new Date(y, 0, 1)
      end = new Date(y, 11, 31, 23, 59, 59)
      prevRange = { start: new Date(y - 1, 0, 1), end: new Date(y - 1, 11, 31, 23, 59, 59) }
    } else {
      const r = getPeriodDateRange(period)
      start = r.start; end = r.end
      prevRange = getPreviousPeriodRange(period, start)
    }

    const [currentLeads, prevLeads] = await Promise.all([
      fetchLeadsInRange(start, end, user.id, isAdmin),
      fetchLeadsInRange(prevRange.start, prevRange.end, user.id, isAdmin),
    ])

    const currentCounts = countStatuses(currentLeads)
    const prevCounts = countStatuses(prevLeads)

    const totalLeads = currentLeads.length
    const closedLeads = currentCounts.closed
    const conversionRate = totalLeads > 0 ? Math.round((closedLeads / totalLeads) * 100) : 0

    const mappedLeads = currentLeads.map((r: any) => ({
      id: r.id,
      companyName: r.company_name || "",
      contactName: r.contact_name,
      email: r.email || "",
      phone: r.phone || "",
      source: "",
      description: r.notes || "",
      status: r.status,
      assignedUserId: r.assigned_to,
      assignedUser: r.assigned_to ? {
        id: r.user_id,
        name: `${r.first_name} ${r.last_name}`,
        email: r.user_email,
        avatar: avatarSvgUrl(`${r.first_name} ${r.last_name}`),
      } : null,
      createdAt: r.created_at,
      updatedAt: r.updated_at,
    }))

    const monthlyBreakdown = buildMonthlyBreakdown(currentLeads, period, yearParam ? { start, end } : undefined)

    const trends = {
      totalLeads: computeTrend(currentCounts.open + currentCounts.contacted + currentCounts.pending + currentCounts.closed + currentCounts.ignored,
        prevCounts.open + prevCounts.contacted + prevCounts.pending + prevCounts.closed + prevCounts.ignored),
      openLeads: computeTrend(currentCounts.open, prevCounts.open),
      contactedLeads: computeTrend(currentCounts.contacted, prevCounts.contacted),
      pendingLeads: computeTrend(currentCounts.pending, prevCounts.pending),
      closedLeads: computeTrend(currentCounts.closed, prevCounts.closed),
      conversionRate: computeTrend(conversionRate,
        prevLeads.length > 0 ? Math.round((prevCounts.closed / prevLeads.length) * 100) : 0),
    }

    const stats = {
      totalLeads,
      openLeads: currentCounts.open,
      contactedLeads: currentCounts.contacted,
      pendingLeads: currentCounts.pending,
      closedLeads,
      ignoredLeads: currentCounts.ignored,
      conversionRate,
      monthlyBreakdown,
      leadsPerMonth: monthlyBreakdown.map((m: any) => ({ label: m.label, leads: m.total, closed: m.closed })),
      trends,
      recentLeads: mappedLeads.slice(0, 10),
      statusDistribution: [
        { name: "Open", value: currentCounts.open, color: "#3b82f6" },
        { name: "Contacted", value: currentCounts.contacted, color: "#f59e0b" },
        { name: "Pending", value: currentCounts.pending, color: "#8b5cf6" },
        { name: "Closed", value: currentCounts.closed, color: "#10b981" },
        { name: "Ignored", value: currentCounts.ignored, color: "#6B7280" },
      ],
      periodLabel: periodLabels[period] ?? "Selected period",
    }

    return NextResponse.json(stats)
  } catch (error) {
    console.error("Dashboard API error:", error)
    return NextResponse.json({ error: "Failed to load dashboard stats" }, { status: 500 })
  }
}
