"use server";

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

import { customerSearchSchema } from "@/lib/validation/customer-searches";
import { DATABASE_ID, TABLES, type Property } from "./schema";
import { createAdminClient } from "./server";
import { requireTenant } from "@/lib/appwrite/tenant-guard";
import { matchPropertyToSearches } from "./matching";

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

function toJsonList(csv?: string | null): string | undefined {
  if (!csv || !csv.trim()) return undefined;
  const items = csv
    .split(",")
    .map((s) => s.trim())
    .filter(Boolean);
  return items.length ? JSON.stringify(items) : undefined;
}

async function syncMatchesForSearch(tenantId: string, userId: string): Promise<void> {
  const { tablesDB } = createAdminClient();
  const result = await tablesDB.listRows({
    databaseId: DATABASE_ID,
    tableId: TABLES.properties,
    queries: [
      Query.equal("tenantId", tenantId),
      Query.equal("status", "aktif"),
      Query.limit(200),
    ],
  });
  const properties = result.rows as unknown as Property[];
  for (const property of properties) {
    await matchPropertyToSearches(property, tenantId, userId).catch(() => {});
  }
}

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

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

  try {
    await tablesDB.createRow(
      DATABASE_ID,
      TABLES.customerSearches,
      ID.unique(),
      {
        tenantId: ctx.tenantId,
        customerId: data.customerId,
        listingType: data.listingType || undefined,
        propertyTypes: toJsonList(data.propertyTypes),
        roomCounts: toJsonList(data.roomCounts),
        minPrice: data.minPrice,
        maxPrice: data.maxPrice,
        minM2: data.minM2,
        maxM2: data.maxM2,
        cities: toJsonList(data.cities),
        districts: toJsonList(data.districts),
        isActive: true,
        notes: data.notes,
        priceWeight: data.priceWeight,
        m2Weight: data.m2Weight,
        locationWeight: data.locationWeight,
        roomCountWeight: data.roomCountWeight,
        propertyTypeWeight: data.propertyTypeWeight,
        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")),
      ],
    );

    await syncMatchesForSearch(ctx.tenantId, ctx.user.id);
  } catch {
    return { ok: false, error: "Arama kriteri oluşturulamadı." };
  }

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

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

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

  try {
    await tablesDB.updateRow(DATABASE_ID, TABLES.customerSearches, id, {
      customerId: data.customerId,
      listingType: data.listingType || undefined,
      propertyTypes: toJsonList(data.propertyTypes),
      roomCounts: toJsonList(data.roomCounts),
      minPrice: data.minPrice,
      maxPrice: data.maxPrice,
      minM2: data.minM2,
      maxM2: data.maxM2,
      cities: toJsonList(data.cities),
      districts: toJsonList(data.districts),
      notes: data.notes,
      priceWeight: data.priceWeight,
      m2Weight: data.m2Weight,
      locationWeight: data.locationWeight,
      roomCountWeight: data.roomCountWeight,
      propertyTypeWeight: data.propertyTypeWeight,
    });

    await syncMatchesForSearch(ctx.tenantId, ctx.user.id);
  } catch {
    return { ok: false, error: "Arama kriteri güncellenemedi." };
  }

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

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

  try {
    await tablesDB.updateRow(DATABASE_ID, TABLES.customerSearches, id, { isActive });
  } catch {
    return { ok: false, error: "Durum güncellenemedi." };
  }

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

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

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

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