import { MeiliSearch } from "meilisearch";

const LISTINGS_INDEX = "listings";

let meilisearchClient: MeiliSearch | null = null;

/**
 * Get or create Meilisearch client using env:
 * - MEILISEARCH_HOST (e.g. https://search.navana-realestate.com)
 * - MEILISEARCH_MASTER_KEY
 */
export function getMeilisearchClient(): MeiliSearch | null {
  if (meilisearchClient) {
    return meilisearchClient;
  }

  const host = process.env.MEILISEARCH_HOST || "http://localhost:7700";
  const masterKey = process.env.MEILISEARCH_MASTER_KEY;

  if (!masterKey) {
    console.warn(
      "[Meilisearch] MEILISEARCH_MASTER_KEY not set. Sync disabled."
    );
    return null;
  }

  try {
    meilisearchClient = new MeiliSearch({
      host,
      apiKey: masterKey,
    });
    return meilisearchClient;
  } catch (error) {
    console.error("[Meilisearch] Client init failed:", error);
    return null;
  }
}

/**
 * Index name for listings (property collection).
 */
export function getListingsIndexName(): string {
  return LISTINGS_INDEX;
}

function extractTypeSlugs(attrs: any, entry: any): string[] {
  const types = attrs?.types ?? entry?.types;
  const data = types?.data;
  if (!data) {
    const legacy = attrs?.propertyType ?? entry?.propertyType;
    return legacy && typeof legacy === "string" ? [legacy] : [];
  }
  const arr = Array.isArray(data) ? data : [data];
  const slugs = arr
    .map((t: any) => {
      const a = t?.attributes ?? t;
      return a?.slug ?? t?.slug;
    })
    .filter((s: unknown) => typeof s === "string" && s.length > 0) as string[];
  if (slugs.length > 0) return slugs;
  const legacy = attrs?.propertyType ?? entry?.propertyType;
  return legacy && typeof legacy === "string" ? [legacy] : [];
}

/**
 * Transform a Strapi property/listing entry to the Meilisearch document shape.
 * Indexed: id, title, slug, price, area, location, category, typeSlugs, thumbnail, status, statusPriority.
 */
export function listingToMeilisearchDoc(entry: any): Record<string, unknown> {
  const attrs = entry?.attributes ?? entry;
  const loc = attrs?.location ?? entry?.location;
  const locData = loc && typeof loc === "object" ? loc : null;
  const locationName =
    locData && typeof locData === "object"
      ? locData.name ?? (typeof locData === "string" ? locData : null)
      : null;
  const locationSlug =
    locData && typeof locData === "object"
      ? locData.slug ?? null
      : null;
  const locationValue = locationName ?? locationSlug ?? null;
  const cardImage = attrs?.cardImage ?? entry?.cardImage;
  const thumbnailUrl =
    cardImage?.data?.attributes?.url ??
    cardImage?.url ??
    (typeof cardImage === "string" ? cardImage : null);

  const typeSlugs = extractTypeSlugs(attrs, entry);
  const legacyType = attrs?.propertyType ?? entry?.propertyType ?? null;

  return {
    id: String(entry?.id ?? attrs?.id ?? entry?.documentId),
    title: attrs?.title ?? entry?.title ?? "",
    slug: attrs?.slug ?? entry?.slug ?? "",
    price: attrs?.price ?? entry?.price ?? null,
    area: attrs?.unitSize ?? entry?.unitSize ?? null,
    location: locationValue,
    locationSlug,
    category: typeSlugs[0] ?? legacyType ?? null,
    typeSlugs,
    thumbnail: thumbnailUrl,
    status: attrs?.propertyStatus ?? entry?.propertyStatus ?? null,
    statusPriority: attrs?.statusPriority ?? entry?.statusPriority ?? null,
  };
}

/**
 * Add or update a single listing in the "listings" index.
 */
export async function indexListing(doc: Record<string, unknown>): Promise<boolean> {
  const client = getMeilisearchClient();
  if (!client) return false;

  try {
    const index = client.index(LISTINGS_INDEX);
    await index.addDocuments([doc]);
    await new Promise((r) => setTimeout(r, 100));
    return true;
  } catch (error) {
    console.error("[Meilisearch] indexListing failed:", error);
    return false;
  }
}

/**
 * Remove a listing from the "listings" index by id.
 */
export async function removeListing(documentId: string | number): Promise<boolean> {
  const client = getMeilisearchClient();
  if (!client) return false;

  try {
    const index = client.index(LISTINGS_INDEX);
    await index.deleteDocument(String(documentId));
    await new Promise((r) => setTimeout(r, 100));
    return true;
  } catch (error) {
    console.error("[Meilisearch] removeListing failed:", error);
    return false;
  }
}

/**
 * Bulk add/update listings in the "listings" index.
 */
export async function indexListings(docs: Record<string, unknown>[]): Promise<boolean> {
  const client = getMeilisearchClient();
  if (!client) return false;

  if (docs.length === 0) return true;

  try {
    const index = client.index(LISTINGS_INDEX);
    await index.addDocuments(docs);
    await new Promise((r) => setTimeout(r, 200));
    return true;
  } catch (error) {
    console.error("[Meilisearch] indexListings failed:", error);
    return false;
  }
}
