import "server-only";
import { prisma } from "@/lib/prisma";
import type { CreatorStatus } from "@prisma/client";
import { CATEGORIES, labelOf, statusMeta } from "./constants";
import { creatorInsights, creatorScore, scoreParts, type Insight, type ScoreParts } from "./score";

export { PLATFORMS, type PlatformKey } from "./constants";

// ── DTOs ───────────────────────────────────────────────────────────────────

export type Trend = { week: number | null; month: number | null; year: number | null };

export type SeriesPoint = { t: string; v: number };

export type PlatformDTO = {
  id: string;
  platform: string;
  handle: string | null;
  url: string | null;
  followers: number;
  liveStatus: boolean;
  lastSyncedAt: string | null;
  metrics: Record<string, number>;
  growth: Trend; // absolute Veränderung
  growthPct: Trend; // prozentuale Veränderung
  series: SeriesPoint[]; // Verlauf für Sparkline
};

export type CreatorNoteDTO = { id: string; body: string; authorName: string; createdAt: string };
export type CreatorEventDTO = { id: string; type: string; title: string; body: string | null; authorName: string | null; createdAt: string };
export type OnboardingItemDTO = { id: string; phase: string; label: string; done: boolean; doneAt: string | null; position: number };

export type CreatorListItem = {
  id: string;
  name: string;
  stageName: string | null;
  avatarUrl: string | null;
  status: CreatorStatus;
  category: string | null;
  categoryLabel: string | null;
  rating: number | null;
  managerId: string | null;
  managerName: string | null;
  totalFollowers: number;
  growthPct30: number | null;
  score: number;
  daysSinceActivity: number | null;
  platforms: string[];
  projectCount: number;
  nextContactAt: string | null;
  insights: Insight[];
};

export type CreatorDetail = CreatorListItem & {
  firstName: string | null;
  lastName: string | null;
  birthDate: string | null;
  age: number | null;
  country: string | null;
  language: string | null;
  timezone: string | null;
  privateEmail: string | null;
  avariaEmail: string | null;
  phone: string | null;
  discord: string | null;
  preferredContact: string | null;
  gameCategory: string | null;
  contentType: string | null;
  contactMethod: string | null;
  contactedAt: string | null;
  lastActivityAt: string | null;
  entryDate: string | null;
  blockedReason: string | null;
  notes: string | null;
  deputyId: string | null;
  deputyName: string | null;
  scoreParts: ScoreParts;
  platformRows: PlatformDTO[];
  noteEntries: CreatorNoteDTO[];
  events: CreatorEventDTO[];
  onboarding: OnboardingItemDTO[];
  projectIds: string[];
  projects: { id: string; name: string }[];
};

// ── Helfer ───────────────────────────────────────────────────────────────

const dn = (u: { name: string; displayName: string | null } | null) => (u ? u.displayName ?? u.name : null);
const iso = (d: Date | null | undefined) => (d ? d.toISOString() : null);

type StatRow = { capturedAt: Date; followers: number };

/** Basiswert vor `days` Tagen (jüngster Snapshot ≤ Cutoff, sonst ältester). */
function baseAt(stats: StatRow[], days: number): number | null {
  const cutoff = Date.now() - days * 86400000;
  let base: number | null = null;
  for (const s of stats) {
    if (s.capturedAt.getTime() <= cutoff) base = s.followers;
    else break;
  }
  if (base === null) base = stats.length ? stats[0].followers : null;
  return base;
}

function pct(cur: number, base: number | null): number | null {
  if (base === null || base <= 0) return null;
  return ((cur - base) / base) * 100;
}

function daysSince(d: Date | null): number | null {
  if (!d) return null;
  return Math.max(0, Math.floor((Date.now() - d.getTime()) / 86400000));
}

function ageFrom(d: Date | null): number | null {
  if (!d) return null;
  const now = new Date();
  let a = now.getFullYear() - d.getFullYear();
  const m = now.getMonth() - d.getMonth();
  if (m < 0 || (m === 0 && now.getDate() < d.getDate())) a--;
  return a >= 0 && a < 130 ? a : null;
}

function asMetrics(v: unknown): Record<string, number> {
  if (!v || typeof v !== "object") return {};
  const out: Record<string, number> = {};
  for (const [k, val] of Object.entries(v as Record<string, unknown>)) {
    const n = Number(val);
    if (!Number.isNaN(n)) out[k] = n;
  }
  return out;
}

type PlatformWithStats = {
  followers: number | null;
  metrics: unknown;
  stats: StatRow[];
};

/** Aggregiertes Wachstum & Score über alle Plattformen eines Creators. */
function derive(platforms: PlatformWithStats[], rating: number | null, lastActivityAt: Date | null) {
  const totalFollowers = platforms.reduce((s, p) => s + (p.followers ?? 0), 0);
  let base30 = 0;
  let base7 = 0;
  let has30 = false;
  let has7 = false;
  for (const p of platforms) {
    const cur = p.followers ?? 0;
    const b30 = baseAt(p.stats, 30);
    const b7 = baseAt(p.stats, 7);
    if (b30 !== null) { base30 += b30; has30 = true; } else base30 += cur;
    if (b7 !== null) { base7 += b7; has7 = true; } else base7 += cur;
  }
  const growthPct30 = has30 ? pct(totalFollowers, base30) : null;
  const growthPct7 = has7 ? pct(totalFollowers, base7) : null;

  // Engagement aus Instagram-Kennzahl, falls vorhanden.
  let engagement: number | null = null;
  for (const p of platforms) {
    const m = asMetrics(p.metrics);
    if (m.engagement != null) engagement = m.engagement;
  }

  const dsa = daysSince(lastActivityAt);
  const score = creatorScore({ growthPct30, daysSinceActivity: dsa, rating, engagement });
  return { totalFollowers, growthPct30, growthPct7, daysSinceActivity: dsa, engagement, score };
}

// ── Listen-Query ─────────────────────────────────────────────────────────

export async function getCreators(): Promise<CreatorListItem[]> {
  const rows = await prisma.creator.findMany({
    orderBy: [{ status: "asc" }, { name: "asc" }],
    select: {
      id: true,
      name: true,
      stageName: true,
      avatarUrl: true,
      status: true,
      category: true,
      rating: true,
      managerId: true,
      nextContactAt: true,
      lastActivityAt: true,
      manager: { select: { name: true, displayName: true } },
      platforms: {
        select: { platform: true, followers: true, metrics: true, stats: { orderBy: { capturedAt: "asc" }, select: { capturedAt: true, followers: true } } },
      },
      _count: { select: { projects: true } },
    },
  });

  return rows.map((c) => {
    const d = derive(c.platforms, c.rating, c.lastActivityAt);
    const categoryLabel = labelOf(CATEGORIES, c.category);
    const insights = creatorInsights(c.stageName ?? c.name, {
      growthPct7: d.growthPct7,
      growthPct30: d.growthPct30,
      daysSinceActivity: d.daysSinceActivity,
      category: c.category,
      categoryLabel,
      status: c.status,
      score: d.score,
    });
    return {
      id: c.id,
      name: c.name,
      stageName: c.stageName,
      avatarUrl: c.avatarUrl,
      status: c.status,
      category: c.category,
      categoryLabel,
      rating: c.rating,
      managerId: c.managerId,
      managerName: dn(c.manager),
      totalFollowers: d.totalFollowers,
      growthPct30: d.growthPct30,
      score: d.score,
      daysSinceActivity: d.daysSinceActivity,
      platforms: c.platforms.map((p) => p.platform),
      projectCount: c._count.projects,
      nextContactAt: iso(c.nextContactAt),
      insights,
    };
  });
}

// ── Detail-Query ───────────────────────────────────────────────────────────

export async function getCreator(id: string): Promise<CreatorDetail | null> {
  const c = await prisma.creator.findUnique({
    where: { id },
    include: {
      manager: { select: { name: true, displayName: true } },
      deputy: { select: { name: true, displayName: true } },
      platforms: {
        orderBy: { platform: "asc" },
        include: { stats: { orderBy: { capturedAt: "asc" }, select: { capturedAt: true, followers: true } } },
      },
      noteEntries: { orderBy: { createdAt: "desc" }, include: { author: { select: { name: true, displayName: true } } } },
      events: { orderBy: { createdAt: "desc" }, take: 60, include: { author: { select: { name: true, displayName: true } } } },
      onboardingItems: { orderBy: [{ position: "asc" }] },
      projects: { select: { project: { select: { id: true, name: true } } } },
    },
  });
  if (!c) return null;

  const d = derive(c.platforms, c.rating, c.lastActivityAt);
  const categoryLabel = labelOf(CATEGORIES, c.category);
  const insights = creatorInsights(c.stageName ?? c.name, {
    growthPct7: d.growthPct7,
    growthPct30: d.growthPct30,
    daysSinceActivity: d.daysSinceActivity,
    category: c.category,
    categoryLabel,
    status: c.status,
    score: d.score,
  });

  const platformRows: PlatformDTO[] = c.platforms.map((p) => {
    const cur = p.followers ?? 0;
    const b = { week: baseAt(p.stats, 7), month: baseAt(p.stats, 30), year: baseAt(p.stats, 365) };
    return {
      id: p.id,
      platform: p.platform,
      handle: p.handle,
      url: p.url,
      followers: cur,
      liveStatus: p.liveStatus,
      lastSyncedAt: iso(p.lastSyncedAt),
      metrics: asMetrics(p.metrics),
      growth: {
        week: b.week === null ? null : cur - b.week,
        month: b.month === null ? null : cur - b.month,
        year: b.year === null ? null : cur - b.year,
      },
      growthPct: { week: pct(cur, b.week), month: pct(cur, b.month), year: pct(cur, b.year) },
      series: p.stats.map((s) => ({ t: s.capturedAt.toISOString(), v: s.followers })),
    };
  });

  return {
    id: c.id,
    name: c.name,
    stageName: c.stageName,
    avatarUrl: c.avatarUrl,
    status: c.status,
    category: c.category,
    categoryLabel,
    rating: c.rating,
    managerId: c.managerId,
    managerName: dn(c.manager),
    totalFollowers: d.totalFollowers,
    growthPct30: d.growthPct30,
    score: d.score,
    daysSinceActivity: d.daysSinceActivity,
    platforms: c.platforms.map((p) => p.platform),
    projectCount: c.projects.length,
    nextContactAt: iso(c.nextContactAt),
    insights,
    firstName: c.firstName,
    lastName: c.lastName,
    birthDate: iso(c.birthDate),
    age: ageFrom(c.birthDate),
    country: c.country,
    language: c.language,
    timezone: c.timezone,
    privateEmail: c.privateEmail,
    avariaEmail: c.avariaEmail,
    phone: c.phone,
    discord: c.discord,
    preferredContact: c.preferredContact,
    gameCategory: c.gameCategory,
    contentType: c.contentType,
    contactMethod: c.contactMethod,
    contactedAt: iso(c.contactedAt),
    lastActivityAt: iso(c.lastActivityAt),
    entryDate: iso(c.entryDate),
    blockedReason: c.blockedReason,
    notes: c.notes,
    deputyId: c.deputyId,
    deputyName: dn(c.deputy),
    scoreParts: scoreParts({ growthPct30: d.growthPct30, daysSinceActivity: d.daysSinceActivity, rating: c.rating, engagement: d.engagement }),
    platformRows,
    noteEntries: c.noteEntries.map((n) => ({ id: n.id, body: n.body, authorName: dn(n.author) ?? "System", createdAt: n.createdAt.toISOString() })),
    events: c.events.map((e) => ({ id: e.id, type: e.type, title: e.title, body: e.body, authorName: dn(e.author), createdAt: e.createdAt.toISOString() })),
    onboarding: c.onboardingItems.map((o) => ({ id: o.id, phase: o.phase, label: o.label, done: o.done, doneAt: iso(o.doneAt), position: o.position })),
    projectIds: c.projects.map((p) => p.project.id),
    projects: c.projects.map((p) => p.project),
  };
}

// ── Optionen (Formulare) ─────────────────────────────────────────────────

export async function getCreatorOptions() {
  const [users, projects, templates] = await Promise.all([
    prisma.user.findMany({ where: { status: { not: "SUSPENDED" } }, orderBy: { name: "asc" }, select: { id: true, name: true, displayName: true } }),
    prisma.project.findMany({ orderBy: { name: "asc" }, select: { id: true, name: true } }),
    prisma.onboardingTemplate.findMany({ orderBy: { createdAt: "asc" }, select: { id: true, name: true, isDefault: true } }),
  ]);
  return {
    managers: users.map((u) => ({ id: u.id, name: u.displayName ?? u.name })),
    projects,
    templates,
  };
}

// ── Internes Dashboard / Insights ──────────────────────────────────────────

export type DashboardData = {
  counts: { total: number; active: number; observing: number; onboarding: number; blocked: number };
  totalReach: number;
  avgScore: number;
  topGrowth: { id: string; name: string; growthPct30: number; totalFollowers: number }[];
  mostActive: { id: string; name: string; score: number; totalFollowers: number }[];
  atRisk: { id: string; name: string; reason: string }[];
  pipeline: { status: string; label: string; color: string; count: number }[];
  managers: { id: string; name: string; total: number; observing: number; onboarding: number; active: number }[];
};

export async function getCreatorDashboard(list: CreatorListItem[]): Promise<DashboardData> {
  const total = list.length;
  const totalReach = list.reduce((s, c) => s + c.totalFollowers, 0);
  const avgScore = total ? Math.round(list.reduce((s, c) => s + c.score, 0) / total) : 0;

  const topGrowth = list
    .filter((c) => c.growthPct30 != null)
    .sort((a, b) => (b.growthPct30 ?? 0) - (a.growthPct30 ?? 0))
    .slice(0, 5)
    .map((c) => ({ id: c.id, name: c.stageName ?? c.name, growthPct30: Math.round(c.growthPct30 ?? 0), totalFollowers: c.totalFollowers }));

  const mostActive = [...list]
    .sort((a, b) => b.score - a.score)
    .slice(0, 5)
    .map((c) => ({ id: c.id, name: c.stageName ?? c.name, score: c.score, totalFollowers: c.totalFollowers }));

  const atRisk = list
    .map((c) => {
      const warn = c.insights.find((i) => i.tone === "bad");
      return warn ? { id: c.id, name: c.stageName ?? c.name, reason: warn.text } : null;
    })
    .filter((x): x is { id: string; name: string; reason: string } => x !== null)
    .slice(0, 6);

  const byStatus = new Map<string, number>();
  for (const c of list) byStatus.set(c.status, (byStatus.get(c.status) ?? 0) + 1);
  const pipeline = statusList().map((s) => ({ status: s.value, label: s.label, color: s.color, count: byStatus.get(s.value) ?? 0 }));

  // Manager-Übersicht
  const mgr = new Map<string, { id: string; name: string; total: number; observing: number; onboarding: number; active: number }>();
  for (const c of list) {
    if (!c.managerId) continue;
    const e = mgr.get(c.managerId) ?? { id: c.managerId, name: c.managerName ?? "—", total: 0, observing: 0, onboarding: 0, active: 0 };
    e.total++;
    if (c.status === "OBSERVING") e.observing++;
    if (c.status === "ONBOARDING") e.onboarding++;
    if (c.status === "ACTIVE") e.active++;
    mgr.set(c.managerId, e);
  }

  return {
    counts: {
      total,
      active: list.filter((c) => c.status === "ACTIVE").length,
      observing: list.filter((c) => c.status === "OBSERVING").length,
      onboarding: list.filter((c) => c.status === "ONBOARDING").length,
      blocked: list.filter((c) => c.status === "BLOCKED").length,
    },
    totalReach,
    avgScore,
    topGrowth,
    mostActive,
    atRisk,
    pipeline,
    managers: [...mgr.values()].sort((a, b) => b.total - a.total),
  };
}

// kleine Helferliste, ohne Client-Import-Kette im Server-Modul
function statusList() {
  return [
    { value: "OBSERVING", label: statusMeta("OBSERVING").label, color: statusMeta("OBSERVING").color },
    { value: "CONTACTING", label: statusMeta("CONTACTING").label, color: statusMeta("CONTACTING").color },
    { value: "CONVERSATION", label: statusMeta("CONVERSATION").label, color: statusMeta("CONVERSATION").color },
    { value: "ONBOARDING", label: statusMeta("ONBOARDING").label, color: statusMeta("ONBOARDING").color },
    { value: "TRIAL", label: statusMeta("TRIAL").label, color: statusMeta("TRIAL").color },
    { value: "ACTIVE", label: statusMeta("ACTIVE").label, color: statusMeta("ACTIVE").color },
    { value: "INACTIVE", label: statusMeta("INACTIVE").label, color: statusMeta("INACTIVE").color },
    { value: "FORMER", label: statusMeta("FORMER").label, color: statusMeta("FORMER").color },
    { value: "BLOCKED", label: statusMeta("BLOCKED").label, color: statusMeta("BLOCKED").color },
  ];
}
