import "server-only";

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

import { DATABASE_ID, TABLES, type Property, type CustomerSearch } from "./schema";
import { createAdminClient } from "./server";
import { scoreMatch } from "@/lib/scoring";

export { scoreMatch };

const SCORE_THRESHOLD = 20;

export async function matchPropertyToSearches(
  property: Property,
  tenantId: string,
  createdBy: string,
): Promise<void> {
  if (property.status !== "aktif") return;

  const { tablesDB } = createAdminClient();

  const searchesResult = await tablesDB.listRows({
    databaseId: DATABASE_ID,
    tableId: TABLES.customerSearches,
    queries: [
      Query.equal("tenantId", tenantId),
      Query.equal("isActive", true),
      Query.limit(200),
    ],
  });

  const searches = searchesResult.rows as unknown as CustomerSearch[];

  for (const search of searches) {
    const listingTypeMismatch =
      !!search.listingType && search.listingType !== property.listingType;
    const score = listingTypeMismatch ? 0 : scoreMatch(property, search);

    const existing = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.propertyMatches,
      queries: [
        Query.equal("propertyId", property.$id),
        Query.equal("searchId", search.$id),
        Query.limit(1),
      ],
    });

    const existingRow = existing.rows.length > 0 ? existing.rows[0] : null;
    const existingId = existingRow?.$id ?? null;

    if (score >= SCORE_THRESHOLD) {
      if (existingId) {
        // Preserve the existing notified status — only refresh score.
        // Without this, some Appwrite backends reset omitted fields to their
        // schema default (false), which would un-notify already-actioned matches.
        const existingNotified = (existingRow as { notified?: boolean }).notified ?? false;
        await tablesDB.updateRow(DATABASE_ID, TABLES.propertyMatches, existingId, {
          score,
          notified: existingNotified,
        });
      } else {
        await tablesDB.createRow(
          DATABASE_ID,
          TABLES.propertyMatches,
          ID.unique(),
          {
            tenantId,
            propertyId: property.$id,
            customerId: search.customerId,
            searchId: search.$id,
            notified: false,
            score,
            createdBy,
          },
          [
            Permission.read(Role.team(tenantId)),
            Permission.update(Role.team(tenantId)),
            Permission.delete(Role.team(tenantId, "owner")),
            Permission.delete(Role.team(tenantId, "admin")),
          ],
        );
      }
    } else if (existingId) {
      // Criteria changed → match no longer qualifies → remove stale record
      await tablesDB.deleteRow(DATABASE_ID, TABLES.propertyMatches, existingId);
    }
  }
}
