"use server";

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

import { propertySchema } from "@/lib/validation/properties";
import { DATABASE_ID, TABLES, type Property } from "./schema";
import { createAdminClient } from "./server";
import { requireTenant } from "@/lib/appwrite/tenant-guard";
import { matchPropertyToSearches } from "./matching";
import { checkLimit, limitErrorMessage } from "@/lib/plans";

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

export async function createPropertyAction(
  _prev: ActionState,
  formData: FormData,
): Promise<ActionState> {
  const ctx = await requireTenant();
  const raw = Object.fromEntries(formData.entries());
  const parsed = propertySchema.safeParse(raw);
  if (!parsed.success) {
    return { ok: false, fieldErrors: parsed.error.flatten().fieldErrors };
  }

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

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

  try {
    const row = await tablesDB.createRow(
      DATABASE_ID,
      TABLES.properties,
      id,
      {
        tenantId: ctx.tenantId,
        title: data.title,
        description: data.description,
        propertyType: data.propertyType,
        listingType: data.listingType,
        status: data.status ?? "aktif",
        price: data.price,
        currency: data.currency ?? "TRY",
        roomCount: data.roomCount,
        grossM2: data.grossM2,
        netM2: data.netM2,
        floor: data.floor,
        totalFloors: data.totalFloors,
        buildingAge: data.buildingAge,
        city: data.city,
        district: data.district,
        neighborhood: data.neighborhood,
        address: data.address,
        mapLat: data.mapLat,
        mapLng: data.mapLng,
        featuresJson: data.featuresJson,
        imageIds: data.imageIds,
        createdBy: ctx.user.id,
        assigneeId: data.assigneeId,
      },
      [
        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")),
      ],
    );

    await matchPropertyToSearches(row as unknown as Property, ctx.tenantId, ctx.user.id).catch(
      () => {},
    );
  } catch {
    return { ok: false, error: "İlan oluşturulamadı." };
  }

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

export async function updatePropertyAction(
  id: string,
  _prev: ActionState,
  formData: FormData,
): Promise<ActionState> {
  const ctx = await requireTenant();
  const raw = Object.fromEntries(formData.entries());
  const parsed = propertySchema.safeParse(raw);
  if (!parsed.success) {
    return { ok: false, fieldErrors: parsed.error.flatten().fieldErrors };
  }

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

  try {
    const row = await tablesDB.updateRow(DATABASE_ID, TABLES.properties, id, {
      title: data.title,
      description: data.description,
      propertyType: data.propertyType,
      listingType: data.listingType,
      status: data.status,
      price: data.price,
      currency: data.currency,
      roomCount: data.roomCount,
      grossM2: data.grossM2,
      netM2: data.netM2,
      floor: data.floor,
      totalFloors: data.totalFloors,
      buildingAge: data.buildingAge,
      city: data.city,
      district: data.district,
      neighborhood: data.neighborhood,
      address: data.address,
      mapLat: data.mapLat,
      mapLng: data.mapLng,
      featuresJson: data.featuresJson,
      imageIds: data.imageIds,
      assigneeId: data.assigneeId,
    });

    await matchPropertyToSearches(row as unknown as Property, ctx.tenantId, ctx.user.id).catch(
      () => {},
    );
  } catch {
    return { ok: false, error: "İlan güncellenemedi." };
  }

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

export async function updatePropertyImagesAction(
  propertyId: string,
  imageIds: string[],
): Promise<ActionState> {
  await requireTenant();
  const { tablesDB } = createAdminClient();

  try {
    await tablesDB.updateRow(DATABASE_ID, TABLES.properties, propertyId, {
      imageIds: JSON.stringify(imageIds),
    });
  } catch {
    return { ok: false, error: "Fotoğraflar kaydedilemedi." };
  }

  revalidatePath(`/properties/${propertyId}`);
  return { ok: true };
}

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

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

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