import "server-only";
import { prisma } from "@/lib/prisma";
import type { Prisma } from "@prisma/client";
import { getProvider } from "./providers";
import { PLATFORM_META, type PlatformKey } from "./constants";

export type SyncOutcome = { platform: string; ok: boolean; source?: string; reason?: string; followers?: number };
export type SyncSummary = { outcomes: SyncOutcome[]; changed: boolean; message: string };

function asObj(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;
}

/**
 * Ruft für jede verbundene Plattform automatisch die aktuellen Werte über die
 * jeweilige API ab (sofern Zugangsdaten hinterlegt), aktualisiert Plattform +
 * legt einen Verlaufs-Snapshot an. Ohne API-Anbindung wird der bestehende Wert
 * als Verlaufspunkt gesichert (manuelle Pflege bleibt möglich).
 */
export async function syncCreatorPlatforms(creatorId: string): Promise<SyncSummary> {
  const creator = await prisma.creator.findUnique({
    where: { id: creatorId },
    select: { id: true, avatarUrl: true, platforms: { select: { id: true, platform: true, handle: true, url: true, followers: true, metrics: true } } },
  });
  if (!creator) return { outcomes: [], changed: false, message: "Creator nicht gefunden." };

  const now = new Date();
  const outcomes: SyncOutcome[] = [];
  let changed = false;
  let newAvatar: string | null = null;

  for (const p of creator.platforms) {
    const provider = getProvider(p.platform);
    const label = PLATFORM_META[p.platform as PlatformKey]?.label ?? p.platform;

    if (!provider || !provider.configured()) {
      // Manuell: aktuellen Stand als Verlaufspunkt sichern.
      await prisma.creatorStat.create({ data: { platformId: p.id, followers: p.followers ?? 0, metrics: (p.metrics as Prisma.InputJsonValue) ?? undefined } });
      await prisma.creatorPlatform.update({ where: { id: p.id }, data: { lastSyncedAt: now } });
      outcomes.push({ platform: p.platform, ok: false, reason: provider ? "keine API-Zugangsdaten" : "manuell", followers: p.followers ?? 0 });
      continue;
    }

    const res = await provider.fetchStats({ handle: p.handle, url: p.url });
    if (!res.ok) {
      await prisma.creatorStat.create({ data: { platformId: p.id, followers: p.followers ?? 0, metrics: (p.metrics as Prisma.InputJsonValue) ?? undefined } });
      await prisma.creatorPlatform.update({ where: { id: p.id }, data: { lastSyncedAt: now } });
      outcomes.push({ platform: p.platform, ok: false, reason: res.reason, followers: p.followers ?? 0 });
      continue;
    }

    const d = res.data;
    const followers = d.followers ?? p.followers ?? 0;
    const merged = { ...asObj(p.metrics), ...(d.metrics ?? {}) };
    const metricsVal = Object.keys(merged).length ? (merged as Prisma.InputJsonValue) : undefined;

    await prisma.creatorPlatform.update({
      where: { id: p.id },
      data: { followers, liveStatus: d.liveStatus ?? false, metrics: metricsVal, lastSyncedAt: now },
    });
    await prisma.creatorStat.create({ data: { platformId: p.id, followers, metrics: metricsVal } });
    if (!creator.avatarUrl && d.avatarUrl && !newAvatar) newAvatar = d.avatarUrl;
    changed = true;
    outcomes.push({ platform: p.platform, ok: true, source: res.source, followers });
    void label;
  }

  const creatorData: Prisma.CreatorUpdateInput = {};
  if (newAvatar) creatorData.avatarUrl = newAvatar;
  if (changed) creatorData.lastActivityAt = now;
  if (Object.keys(creatorData).length) await prisma.creator.update({ where: { id: creatorId }, data: creatorData });

  return { outcomes, changed, message: buildMessage(outcomes) };
}

function buildMessage(outcomes: SyncOutcome[]): string {
  if (outcomes.length === 0) return "Keine Plattformen verbunden.";
  const auto = outcomes.filter((o) => o.ok);
  const manual = outcomes.filter((o) => !o.ok);
  const parts: string[] = [];
  if (auto.length) parts.push(`Automatisch aktualisiert: ${auto.map((o) => label(o.platform)).join(", ")}.`);
  if (manual.length) {
    const noKey = manual.filter((o) => o.reason === "keine API-Zugangsdaten").map((o) => label(o.platform));
    const other = manual.filter((o) => o.reason !== "keine API-Zugangsdaten" && o.reason !== "manuell");
    if (noKey.length) parts.push(`Ohne API-Anbindung (Verlauf gesichert): ${noKey.join(", ")}.`);
    for (const o of other) parts.push(`${label(o.platform)}: ${o.reason}.`);
  }
  return parts.join(" ");
}
function label(p: string) {
  return PLATFORM_META[p as PlatformKey]?.label ?? p;
}
