"use server";

import { revalidatePath } from "next/cache";
import { prisma } from "@/lib/prisma";
import { requireSession } from "@/lib/auth/session";
import { isPlatform, statusMeta } from "./constants";
import { syncCreatorPlatforms } from "./sync";
import type { CreatorContentType, CreatorEventType, CreatorStatus, Prisma } from "@prisma/client";

const STATUSES: CreatorStatus[] = ["OBSERVING", "CONTACTING", "CONVERSATION", "ONBOARDING", "TRIAL", "ACTIVE", "INACTIVE", "FORMER", "BLOCKED"];
const CONTENT_TYPES: CreatorContentType[] = ["STREAMER", "YOUTUBER", "SHORTFORM", "HYBRID"];

async function guardManage(): Promise<string | null> {
  const session = await requireSession();
  return session.user.permissions?.includes("creators.manage") ? session.user.id : null;
}

function parseDate(v: string | null | undefined): Date | null {
  if (!v) return null;
  const d = new Date(v);
  return Number.isNaN(d.getTime()) ? null : d;
}

type Tx = Prisma.TransactionClient;

/** Historien-Eintrag schreiben. */
async function logEvent(tx: Tx | typeof prisma, creatorId: string, type: CreatorEventType, title: string, authorId: string | null, body?: string | null) {
  await tx.creatorEvent.create({ data: { creatorId, type, title, body: body ?? null, authorId } });
}

/** Bestmögliche Auto-Synchronisierung nach dem Speichern (blockiert das Speichern nie). */
async function trySync(creatorId: string, actorId: string | null) {
  try {
    const summary = await syncCreatorPlatforms(creatorId);
    if (summary.outcomes.some((o) => o.ok)) await logEvent(prisma, creatorId, "SNAPSHOT", "Automatischer Datenabruf", actorId, summary.message);
  } catch {
    /* Netzwerk-/API-Fehler ignorieren — manuelle Werte bleiben erhalten. */
  }
}

// ── Eingabetypen ─────────────────────────────────────────────────────────

export type PlatformInput = {
  platform: string;
  handle?: string | null;
  url?: string | null;
  followers?: number | null;
  liveStatus?: boolean;
  metrics?: Record<string, number | string | null | undefined> | null;
};

export type CreatorInput = {
  name: string;
  firstName?: string | null;
  lastName?: string | null;
  stageName?: string | null;
  birthDate?: string | 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;
  status?: CreatorStatus;
  category?: string | null;
  gameCategory?: string | null;
  contentType?: CreatorContentType | null;
  contactMethod?: string | null;
  contactedAt?: string | null;
  lastActivityAt?: string | null;
  nextContactAt?: string | null;
  entryDate?: string | null;
  blockedReason?: string | null;
  rating?: number | null;
  notes?: string | null;
  managerId?: string | null;
  deputyId?: string | null;
  projectIds?: string[];
  platforms?: PlatformInput[];
};

export type CreatorResult = { id?: string; error?: string };

function cleanMetrics(m: PlatformInput["metrics"]): Prisma.InputJsonValue | undefined {
  if (!m) return undefined;
  const out: Record<string, number> = {};
  for (const [k, v] of Object.entries(m)) {
    const n = Number(v);
    if (v !== null && v !== undefined && v !== "" && !Number.isNaN(n)) out[k] = n;
  }
  return Object.keys(out).length ? out : undefined;
}

function cleanPlatforms(list: PlatformInput[] | undefined) {
  return (list ?? [])
    .filter((p) => isPlatform(p.platform))
    .map((p) => ({
      platform: p.platform,
      handle: p.handle?.trim().slice(0, 160) || null,
      url: p.url?.trim().slice(0, 500) || null,
      followers: Math.max(0, Math.round(Number(p.followers ?? 0)) || 0),
      liveStatus: Boolean(p.liveStatus),
      metrics: cleanMetrics(p.metrics),
    }));
}

async function validIds(model: "user" | "project", ids: string[] | undefined): Promise<string[]> {
  if (!ids?.length) return [];
  const rows =
    model === "user"
      ? await prisma.user.findMany({ where: { id: { in: ids } }, select: { id: true } })
      : await prisma.project.findMany({ where: { id: { in: ids } }, select: { id: true } });
  return rows.map((r) => r.id);
}

function normalize(input: CreatorInput) {
  const status = STATUSES.includes(input.status as CreatorStatus) ? (input.status as CreatorStatus) : "OBSERVING";
  const contentType = CONTENT_TYPES.includes(input.contentType as CreatorContentType) ? (input.contentType as CreatorContentType) : null;
  return {
    name: input.name.trim().slice(0, 160),
    firstName: input.firstName?.trim().slice(0, 80) || null,
    lastName: input.lastName?.trim().slice(0, 80) || null,
    stageName: input.stageName?.trim().slice(0, 160) || null,
    birthDate: parseDate(input.birthDate),
    country: input.country?.trim().slice(0, 80) || null,
    language: input.language?.trim().slice(0, 60) || null,
    timezone: input.timezone?.trim().slice(0, 60) || null,
    privateEmail: input.privateEmail?.trim().slice(0, 190) || null,
    avariaEmail: input.avariaEmail?.trim().slice(0, 190) || null,
    phone: input.phone?.trim().slice(0, 60) || null,
    discord: input.discord?.trim().slice(0, 120) || null,
    preferredContact: input.preferredContact?.trim().slice(0, 40) || null,
    status,
    category: input.category?.trim().slice(0, 40) || null,
    gameCategory: input.gameCategory?.trim().slice(0, 40) || null,
    contentType,
    contactMethod: input.contactMethod?.trim().slice(0, 40) || null,
    contactedAt: parseDate(input.contactedAt),
    lastActivityAt: parseDate(input.lastActivityAt),
    nextContactAt: parseDate(input.nextContactAt),
    entryDate: parseDate(input.entryDate),
    blockedReason: input.blockedReason?.trim() || null,
    rating: input.rating != null ? Math.max(1, Math.min(5, Math.round(input.rating))) : null,
    notes: input.notes?.trim() || null,
  };
}

/** Standard-Onboarding-Checkliste in einen Creator kopieren (falls noch keine da). */
async function ensureOnboardingChecklist(tx: Tx, creatorId: string) {
  const existing = await tx.creatorOnboardingItem.count({ where: { creatorId } });
  if (existing > 0) return;
  const tpl = (await tx.onboardingTemplate.findFirst({ where: { isDefault: true }, include: { items: { orderBy: { position: "asc" } } } })) ??
    (await tx.onboardingTemplate.findFirst({ orderBy: { createdAt: "asc" }, include: { items: { orderBy: { position: "asc" } } } }));
  if (!tpl || tpl.items.length === 0) return;
  await tx.creatorOnboardingItem.createMany({
    data: tpl.items.map((it) => ({ creatorId, phase: it.phase, label: it.label, position: it.position })),
  });
  await logEvent(tx, creatorId, "ONBOARDING", `Onboarding-Checkliste „${tpl.name}" erstellt`, null);
}

// ── CRUD ────────────────────────────────────────────────────────────────

export async function createCreatorAction(input: CreatorInput): Promise<CreatorResult> {
  const actorId = await guardManage();
  if (!actorId) return { error: "Keine Berechtigung." };
  if (!input.name.trim()) return { error: "Name erforderlich." };

  const n = normalize(input);
  const managerId = input.managerId ? (await validIds("user", [input.managerId]))[0] ?? null : null;
  const deputyId = input.deputyId ? (await validIds("user", [input.deputyId]))[0] ?? null : null;
  const projectIds = await validIds("project", input.projectIds);
  const platforms = cleanPlatforms(input.platforms);

  const creator = await prisma.$transaction(async (tx) => {
    const created = await tx.creator.create({
      data: {
        ...n,
        managerId,
        deputyId,
        projects: { create: projectIds.map((projectId) => ({ projectId })) },
        platforms: {
          create: platforms.map((p) => ({
            platform: p.platform,
            handle: p.handle,
            url: p.url,
            followers: p.followers,
            liveStatus: p.liveStatus,
            metrics: p.metrics,
            lastSyncedAt: new Date(),
            stats: { create: { followers: p.followers, metrics: p.metrics } },
          })),
        },
      },
      select: { id: true },
    });
    await logEvent(tx, created.id, "SYSTEM", "Creator-Profil erstellt", actorId);
    await logEvent(tx, created.id, "STATUS", `Status: ${statusMeta(n.status).label}`, actorId);
    if (n.status === "ONBOARDING") await ensureOnboardingChecklist(tx, created.id);
    return created;
  });

  if (platforms.length) await trySync(creator.id, actorId); // automatischer API-Abruf für verbundene Kanäle
  revalidatePath("/creators");
  return { id: creator.id };
}

export async function updateCreatorAction(id: string, input: CreatorInput): Promise<CreatorResult> {
  const actorId = await guardManage();
  if (!actorId) return { error: "Keine Berechtigung." };
  if (!input.name.trim()) return { error: "Name erforderlich." };

  const n = normalize(input);
  const managerId = input.managerId ? (await validIds("user", [input.managerId]))[0] ?? null : null;
  const deputyId = input.deputyId ? (await validIds("user", [input.deputyId]))[0] ?? null : null;
  const projectIds = input.projectIds !== undefined ? await validIds("project", input.projectIds) : null;
  const platforms = input.platforms !== undefined ? cleanPlatforms(input.platforms) : null;

  await prisma.$transaction(async (tx) => {
    const prev = await tx.creator.findUnique({ where: { id }, select: { status: true } });
    await tx.creator.update({ where: { id }, data: { ...n, managerId, deputyId } });

    if (prev && prev.status !== n.status) {
      await logEvent(tx, id, "STATUS", `Status geändert: ${statusMeta(prev.status).label} → ${statusMeta(n.status).label}`, actorId);
      if (n.status === "ONBOARDING") await ensureOnboardingChecklist(tx, id);
    }

    if (projectIds !== null) {
      await tx.creatorProjectLink.deleteMany({ where: { creatorId: id } });
      if (projectIds.length) await tx.creatorProjectLink.createMany({ data: projectIds.map((projectId) => ({ creatorId: id, projectId })) });
    }

    if (platforms !== null) {
      const existing = await tx.creatorPlatform.findMany({ where: { creatorId: id }, select: { id: true, platform: true, followers: true } });
      const byType = new Map(existing.map((e) => [e.platform, e]));
      const keepTypes = new Set(platforms.map((p) => p.platform));

      for (const e of existing) if (!keepTypes.has(e.platform)) await tx.creatorPlatform.delete({ where: { id: e.id } });

      for (const p of platforms) {
        const ex = byType.get(p.platform);
        if (ex) {
          await tx.creatorPlatform.update({ where: { id: ex.id }, data: { handle: p.handle, url: p.url, followers: p.followers, liveStatus: p.liveStatus, metrics: p.metrics } });
          if ((ex.followers ?? 0) !== p.followers) {
            await tx.creatorStat.create({ data: { platformId: ex.id, followers: p.followers, metrics: p.metrics } });
          }
        } else {
          const created = await tx.creatorPlatform.create({ data: { creatorId: id, platform: p.platform, handle: p.handle, url: p.url, followers: p.followers, liveStatus: p.liveStatus, metrics: p.metrics, lastSyncedAt: new Date() } });
          await tx.creatorStat.create({ data: { platformId: created.id, followers: p.followers, metrics: p.metrics } });
          await logEvent(tx, id, "PLATFORM", `${p.platform} verbunden`, actorId);
        }
      }
    }
  });

  if (platforms !== null && platforms.length) await trySync(id, actorId); // Kanäle geändert → automatisch abrufen
  revalidatePath("/creators");
  return { id };
}

export async function deleteCreatorAction(id: string): Promise<CreatorResult> {
  const actorId = await guardManage();
  if (!actorId) return { error: "Keine Berechtigung." };
  await prisma.creator.delete({ where: { id } });
  revalidatePath("/creators");
  return { id };
}

/** Schneller Statuswechsel (Pipeline-Board / Profil). */
export async function changeStatusAction(id: string, status: CreatorStatus): Promise<CreatorResult> {
  const actorId = await guardManage();
  if (!actorId) return { error: "Keine Berechtigung." };
  if (!STATUSES.includes(status)) return { error: "Ungültiger Status." };
  await prisma.$transaction(async (tx) => {
    const prev = await tx.creator.findUnique({ where: { id }, select: { status: true } });
    if (!prev || prev.status === status) return;
    const data: Prisma.CreatorUpdateInput = { status };
    if (status === "CONTACTING") data.contactedAt = new Date();
    if (status === "ACTIVE" || status === "TRIAL") data.entryDate = data.entryDate ?? undefined;
    await tx.creator.update({ where: { id }, data });
    await logEvent(tx, id, "STATUS", `Status geändert: ${statusMeta(prev.status).label} → ${statusMeta(status).label}`, actorId);
    if (status === "ONBOARDING") await ensureOnboardingChecklist(tx, id);
  });
  revalidatePath("/creators");
  return { id };
}

/** Manuelle Datenaktualisierung: ruft die verbundenen APIs ab (bzw. sichert manuelle Werte als Verlaufspunkt). */
export async function refreshCreatorDataAction(id: string): Promise<{ id?: string; error?: string; message?: string }> {
  const actorId = await guardManage();
  if (!actorId) return { error: "Keine Berechtigung." };
  const summary = await syncCreatorPlatforms(id);
  await logEvent(prisma, id, "SNAPSHOT", "Statistiken aktualisiert", actorId, summary.message);
  revalidatePath("/creators");
  return { id, message: summary.message };
}

// ── Notizen ──────────────────────────────────────────────────────────────

export type NoteResult = { id?: string; error?: string; note?: { id: string; body: string; authorName: string; createdAt: string } };

export async function addCreatorNoteAction(creatorId: string, body: string): Promise<NoteResult> {
  const session = await requireSession();
  if (!session.user.permissions?.includes("creators.view")) return { error: "Keine Berechtigung." };
  const text = body.trim();
  if (!text) return { error: "Leere Notiz." };
  const note = await prisma.creatorNote.create({
    data: { creatorId, authorId: session.user.id, body: text.slice(0, 4000) },
    select: { id: true, body: true, createdAt: true, author: { select: { name: true, displayName: true } } },
  });
  await logEvent(prisma, creatorId, "NOTE", "Notiz hinzugefügt", session.user.id, text.slice(0, 200));
  revalidatePath("/creators");
  return {
    note: {
      id: note.id,
      body: note.body,
      authorName: note.author ? note.author.displayName ?? note.author.name : "System",
      createdAt: note.createdAt.toISOString(),
    },
  };
}

export async function deleteCreatorNoteAction(noteId: string): Promise<{ error?: string }> {
  const session = await requireSession();
  const note = await prisma.creatorNote.findUnique({ where: { id: noteId }, select: { authorId: true } });
  if (!note) return { error: "Nicht gefunden." };
  const canManage = Boolean(session.user.permissions?.includes("creators.manage"));
  if (note.authorId !== session.user.id && !canManage) return { error: "Keine Berechtigung." };
  await prisma.creatorNote.delete({ where: { id: noteId } });
  revalidatePath("/creators");
  return {};
}

// ── Kontakt-Log ────────────────────────────────────────────────────────────

export async function logContactAction(creatorId: string, method: string, body: string): Promise<{ error?: string }> {
  const actorId = await guardManage();
  if (!actorId) return { error: "Keine Berechtigung." };
  await prisma.$transaction(async (tx) => {
    await tx.creator.update({ where: { id: creatorId }, data: { contactMethod: method.slice(0, 40) || null } });
    await logEvent(tx, creatorId, "CONTACT", `Kontakt via ${method || "—"}`, actorId, body.trim().slice(0, 1000) || null);
  });
  revalidatePath("/creators");
  return {};
}

// ── Onboarding ─────────────────────────────────────────────────────────────

export async function toggleOnboardingItemAction(itemId: string): Promise<{ error?: string; done?: boolean }> {
  const actorId = await guardManage();
  if (!actorId) return { error: "Keine Berechtigung." };
  const item = await prisma.creatorOnboardingItem.findUnique({ where: { id: itemId }, select: { id: true, done: true, label: true, creatorId: true } });
  if (!item) return { error: "Nicht gefunden." };
  const done = !item.done;
  await prisma.creatorOnboardingItem.update({ where: { id: itemId }, data: { done, doneAt: done ? new Date() : null } });
  if (done) await logEvent(prisma, item.creatorId, "ONBOARDING", `Erledigt: ${item.label}`, actorId);
  revalidatePath("/creators");
  return { done };
}

export async function applyOnboardingTemplateAction(creatorId: string): Promise<{ error?: string }> {
  const actorId = await guardManage();
  if (!actorId) return { error: "Keine Berechtigung." };
  await prisma.$transaction((tx) => ensureOnboardingChecklist(tx, creatorId));
  revalidatePath("/creators");
  return {};
}
