"use server";

import crypto from "crypto";
import { ID, Permission, Role } from "node-appwrite";
import { revalidatePath } from "next/cache";

import { presentationSchema } from "@/lib/validation/presentations";
import { DATABASE_ID, TABLES } from "./schema";
import { createAdminClient } from "./server";
import { requireTenant } from "@/lib/appwrite/tenant-guard";
import { checkLimit, limitErrorMessage } from "@/lib/plans";

type ActionState = { ok: boolean; error?: string; fieldErrors?: Record<string, string[]>; id?: string };

export async function createPresentationAction(
  _prev: ActionState,
  formData: FormData,
): Promise<ActionState> {
  const ctx = await requireTenant();
  const selectedIds = formData.getAll("propertyIdsRaw") as string[];
  const raw = {
    ...Object.fromEntries(formData.entries()),
    propertyIds: JSON.stringify(selectedIds),
  };
  const parsed = presentationSchema.safeParse(raw);
  if (!parsed.success) {
    return { ok: false, fieldErrors: parsed.error.flatten().fieldErrors };
  }

  const limitCheck = await checkLimit(ctx.tenantId, ctx.settings?.plan, "presentations");
  if (!limitCheck.allowed) {
    return { ok: false, error: limitErrorMessage("presentations", limitCheck.limit, ctx.role) };
  }

  const { tablesDB } = createAdminClient();
  const data = parsed.data;
  const id = ID.unique();
  const shareToken = crypto.randomBytes(16).toString("hex");
  // Convert "YYYY-MM-DD" → end-of-day UTC so the sunum is valid the full chosen day.
  const expiresAt = data.expiresAt ? `${data.expiresAt}T23:59:59.000Z` : undefined;

  try {
    await tablesDB.createRow(
      DATABASE_ID,
      TABLES.presentations,
      id,
      {
        tenantId: ctx.tenantId,
        title: data.title,
        customerId: data.customerId || undefined,
        propertyIds: data.propertyIds,
        shareToken,
        ...(expiresAt ? { expiresAt } : {}),
        viewCount: 0,
        notes: data.notes || undefined,
        createdBy: ctx.user.id,
      },
      [
        Permission.read(Role.team(ctx.tenantId)),
        Permission.update(Role.team(ctx.tenantId)),
        Permission.delete(Role.team(ctx.tenantId, "owner")),
        Permission.delete(Role.team(ctx.tenantId, "admin")),
      ],
    );
  } catch {
    return { ok: false, error: "Sunum oluşturulamadı." };
  }

  revalidatePath("/presentations");
  return { ok: true, id };
}

export async function updatePresentationAction(
  id: string,
  _prev: ActionState,
  formData: FormData,
): Promise<ActionState> {
  await requireTenant();
  const selectedIds = formData.getAll("propertyIdsRaw") as string[];
  const raw = {
    ...Object.fromEntries(formData.entries()),
    propertyIds: JSON.stringify(selectedIds),
  };
  const parsed = presentationSchema.safeParse(raw);
  if (!parsed.success) {
    return { ok: false, fieldErrors: parsed.error.flatten().fieldErrors };
  }

  const { tablesDB } = createAdminClient();
  const data = parsed.data;

  const expiresAt = data.expiresAt ? `${data.expiresAt}T23:59:59.000Z` : undefined;

  try {
    await tablesDB.updateRow(DATABASE_ID, TABLES.presentations, id, {
      title: data.title,
      customerId: data.customerId || undefined,
      propertyIds: data.propertyIds,
      ...(expiresAt ? { expiresAt } : {}),
      notes: data.notes || undefined,
    });
  } catch {
    return { ok: false, error: "Sunum güncellenemedi." };
  }

  revalidatePath("/presentations");
  return { ok: true };
}

export async function deletePresentationAction(id: string): Promise<ActionState> {
  await requireTenant();
  const { tablesDB } = createAdminClient();

  try {
    await tablesDB.deleteRow(DATABASE_ID, TABLES.presentations, id);
  } catch {
    return { ok: false, error: "Sunum silinemedi." };
  }

  revalidatePath("/presentations");
  return { ok: true };
}

export async function incrementPresentationViewCount(id: string, currentCount: number): Promise<void> {
  const { tablesDB } = createAdminClient();
  await tablesDB.updateRow(DATABASE_ID, TABLES.presentations, id, {
    viewCount: currentCount + 1,
  }).catch(() => {});
}
