"use server";

import { ID, Permission, Query, Role } from "node-appwrite";
import { InputFile } from "node-appwrite/file";

import { BUCKETS, DATABASE_ID, TABLES, type Attachment } from "./schema";
import { createAdminClient } from "./server";
import { requireTenant } from "./tenant-guard";

export type AttachmentItem = {
  id: string;
  fileId: string;
  name: string;
  size: number;
  mimeType: string;
  createdAt: string;
};

type AttachmentActionState = { ok: boolean; error?: string };

const MAX_BYTES = 20 * 1024 * 1024;

function teamFilePermissions(tenantId: string) {
  return [
    Permission.read(Role.team(tenantId)),
    Permission.update(Role.team(tenantId, "owner")),
    Permission.update(Role.team(tenantId, "admin")),
    Permission.delete(Role.team(tenantId, "owner")),
    Permission.delete(Role.team(tenantId, "admin")),
    Permission.delete(Role.team(tenantId, "member")),
  ];
}

export async function fetchAttachmentsAction(
  entityType: string,
  entityId: string,
): Promise<AttachmentItem[]> {
  let ctx;
  try {
    ctx = await requireTenant();
  } catch {
    return [];
  }

  try {
    const { tablesDB } = createAdminClient();
    const result = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.attachments,
      queries: [
        Query.equal("tenantId", ctx.tenantId),
        Query.equal("entityId", entityId),
        Query.orderAsc("$createdAt"),
        Query.limit(100),
      ],
    });

    return (result.rows as unknown as Attachment[]).map((r) => ({
      id: r.$id,
      fileId: r.fileId,
      name: r.name,
      size: r.size,
      mimeType: r.mimeType ?? "",
      createdAt: r.$createdAt,
    }));
  } catch {
    return [];
  }
}

export async function uploadAttachmentAction(
  _prev: AttachmentActionState,
  formData: FormData,
): Promise<AttachmentActionState> {
  let ctx;
  try {
    ctx = await requireTenant();
  } catch {
    return { ok: false, error: "Yetkiniz yok." };
  }

  const entityType = String(formData.get("entityType") ?? "").trim();
  const entityId = String(formData.get("entityId") ?? "").trim();
  const file = formData.get("file");

  if (!entityType || !entityId) return { ok: false, error: "Geçersiz istek." };
  if (!(file instanceof File) || file.size === 0) return { ok: false, error: "Dosya seçin." };
  if (file.size > MAX_BYTES) return { ok: false, error: "Dosya 20MB'dan büyük olamaz." };

  const { storage, tablesDB } = createAdminClient();
  let createdFileId: string | null = null;

  try {
    const buffer = Buffer.from(await file.arrayBuffer());
    const inputFile = InputFile.fromBuffer(buffer, file.name);

    const created = await storage.createFile({
      bucketId: BUCKETS.entityAttachments,
      fileId: ID.unique(),
      file: inputFile,
      permissions: teamFilePermissions(ctx.tenantId),
    });
    createdFileId = created.$id;

    await tablesDB.createRow(
      DATABASE_ID,
      TABLES.attachments,
      ID.unique(),
      {
        tenantId: ctx.tenantId,
        createdBy: ctx.user.id,
        entityType,
        entityId,
        fileId: createdFileId,
        name: file.name,
        size: file.size,
        mimeType: file.type || null,
      },
      teamFilePermissions(ctx.tenantId),
    );
  } catch (e) {
    if (createdFileId) {
      try {
        await storage.deleteFile({ bucketId: BUCKETS.entityAttachments, fileId: createdFileId });
      } catch { /* best-effort cleanup */ }
    }
    return { ok: false, error: e instanceof Error ? e.message : "Yükleme başarısız." };
  }

  return { ok: true };
}

export async function deleteAttachmentAction(
  formData: FormData,
): Promise<AttachmentActionState> {
  const attachmentId = String(formData.get("attachmentId") ?? "");
  if (!attachmentId) return { ok: false, error: "ID eksik." };

  let ctx;
  try {
    ctx = await requireTenant();
  } catch {
    return { ok: false, error: "Yetkiniz yok." };
  }

  const { storage, tablesDB } = createAdminClient();

  try {
    const existing = (await tablesDB.getRow(
      DATABASE_ID,
      TABLES.attachments,
      attachmentId,
    )) as unknown as Attachment;

    if (existing.tenantId !== ctx.tenantId) {
      return { ok: false, error: "Erişim engellendi." };
    }

    await tablesDB.deleteRow(DATABASE_ID, TABLES.attachments, attachmentId);

    try {
      await storage.deleteFile({
        bucketId: BUCKETS.entityAttachments,
        fileId: existing.fileId,
      });
    } catch { /* best-effort — DB row already deleted */ }
  } catch (e) {
    return { ok: false, error: e instanceof Error ? e.message : "Silme başarısız." };
  }

  return { ok: true };
}
