import { NextResponse } from "next/server";
import { DepartmentKey } from "@prisma/client";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import {
  canAccessMarketing,
  getDefaultSocialSnapshots,
  mapBrandPulse,
  mapMarketingEmployee,
  mapMarketingInitiative,
  mapMarketingTask,
  mapSocialSnapshot,
} from "@/lib/marketing/persistence";
import { buildInsightsFromSnapshots } from "@/lib/marketing/meta";
import { marketingMockData } from "@/lib/marketing/mock";
import type { MetaSyncStatus } from "@/lib/marketing/types";

const SNAPSHOT_LOOKBACK_DAYS = 95;

function currentMonthIso(): string {
  return new Date().toISOString().slice(0, 7);
}

async function ensureMarketingKpiSeed(userId: string | undefined, userName: string | undefined) {
  const socialCount = await prisma.marketingSocialSnapshot.count({
    where: { department: DepartmentKey.marketing },
  });

  if (socialCount === 0) {
    await prisma.marketingSocialSnapshot.createMany({
      data: getDefaultSocialSnapshots().map((snapshot) => ({
        department: DepartmentKey.marketing,
        channel: snapshot.channel,
        range: snapshot.range,
        followersStart: snapshot.followersStart,
        followersEnd: snapshot.followersEnd,
        engagementRate: snapshot.engagementRate,
        reach: snapshot.reach,
        impressions: snapshot.impressions,
        capturedAt: new Date(snapshot.capturedAt),
      })),
    });
  }

  const brandCount = await prisma.marketingBrandPulse.count({
    where: { department: DepartmentKey.marketing },
  });

  if (brandCount === 0) {
    await prisma.marketingBrandPulse.create({
      data: {
        department: DepartmentKey.marketing,
        month: currentMonthIso(),
        rating1to5: marketingMockData.brandPulse.rating1to5,
        notes: marketingMockData.brandPulse.notes,
        updatedById: userId ?? null,
        updatedByName: userName ?? null,
      },
    });
  }
}

export async function GET() {
  const session = await getServerSession(authOptions);
  if (!session?.user) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  if (!canAccessMarketing(session.user.role, session.user.department)) {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  await ensureMarketingKpiSeed(session.user.id, session.user.name ?? undefined);

  const [employeesRaw, initiativesRaw, socialRaw, brandRaw, metaConnectionRaw, latestSyncRun] = await Promise.all([
    prisma.user.findMany({
      where: {
        department: DepartmentKey.marketing,
        status: "active",
      },
      select: {
        id: true,
        name: true,
        email: true,
        departmentRole: true,
        userRoles: {
          include: { role: true },
          orderBy: { assignedAt: "asc" },
          take: 1,
        },
      },
      orderBy: [{ name: "asc" }, { email: "asc" }],
    }),
    prisma.marketingInitiative.findMany({
      where: { department: DepartmentKey.marketing },
      include: {
        contributors: true,
        locations: true,
        evidenceLinks: {
          orderBy: { createdAt: "asc" },
        },
        tasks: {
          include: {
            evidenceLinks: {
              orderBy: { createdAt: "asc" },
            },
          },
          orderBy: [{ dueDate: "asc" }, { createdAt: "asc" }],
        },
        milestones: {
          include: {
            checkpoints: {
              orderBy: { createdAt: "asc" },
            },
          },
          orderBy: [{ sortOrder: "asc" }, { dueDate: "asc" }],
        },
      },
      orderBy: [{ dueDate: "asc" }, { createdAt: "desc" }],
    }),
    prisma.marketingSocialSnapshot.findMany({
      where: {
        department: DepartmentKey.marketing,
        capturedAt: {
          gte: new Date(Date.now() - SNAPSHOT_LOOKBACK_DAYS * 24 * 60 * 60 * 1000),
        },
      },
      orderBy: { capturedAt: "desc" },
      take: 400,
    }),
    prisma.marketingBrandPulse.findFirst({
      where: { department: DepartmentKey.marketing },
      orderBy: { updatedAt: "desc" },
    }),
    prisma.marketingMetaConnection.findFirst({
      where: {
        department: DepartmentKey.marketing,
        isActive: true,
      },
      orderBy: { updatedAt: "desc" },
    }),
    prisma.marketingSyncRun.findFirst({
      where: { department: DepartmentKey.marketing },
      orderBy: { createdAt: "desc" },
    }),
  ]);

  const employees = employeesRaw.map(mapMarketingEmployee);
  const initiatives = initiativesRaw.map(mapMarketingInitiative);
  const tasks = initiativesRaw.flatMap((initiative) =>
    initiative.tasks.map((task) =>
      mapMarketingTask({
        ...task,
        initiativeId: initiative.id,
      })
    )
  );
  const socialSnapshots = socialRaw.map(mapSocialSnapshot);
  const socialInsights = buildInsightsFromSnapshots(socialSnapshots);
  const brandPulse = brandRaw ? mapBrandPulse(brandRaw) : marketingMockData.brandPulse;
  let metaSyncStatus: MetaSyncStatus = "disconnected";
  if (metaConnectionRaw) {
    if (latestSyncRun?.status === "failed") {
      metaSyncStatus = "error";
    } else if (latestSyncRun?.status === "queued" || latestSyncRun?.status === "running") {
      metaSyncStatus = "syncing";
    } else {
      metaSyncStatus = "ready";
    }
  }

  return NextResponse.json({
    ok: true,
    employees,
    initiatives,
    tasks,
    socialSnapshots,
    socialInsights,
    brandPulse,
    metaConnection: metaConnectionRaw
      ? {
          id: metaConnectionRaw.id,
          accountId: metaConnectionRaw.accountId,
          pageId: metaConnectionRaw.pageId,
          pageName: metaConnectionRaw.pageName,
          isActive: metaConnectionRaw.isActive,
          lastSyncedAt: metaConnectionRaw.lastSyncedAt ? metaConnectionRaw.lastSyncedAt.toISOString() : null,
          tokenExpiresAt: metaConnectionRaw.tokenExpiresAt ? metaConnectionRaw.tokenExpiresAt.toISOString() : null,
        }
      : null,
    metaSyncStatus,
    latestSyncMessage: latestSyncRun?.message ?? null,
    latestSyncAt: latestSyncRun?.completedAt ? latestSyncRun.completedAt.toISOString() : null,
  });
}
