import { MeiliSearch } from "meilisearch";

// Meilisearch client singleton
let meilisearchClient: MeiliSearch | null = null;

// Index name for properties
const PROPERTIES_INDEX = "properties";

/**
 * Get or create Meilisearch client
 */
export const 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_MASTER_KEY not set. Meilisearch sync will be disabled."
    );
    return null;
  }

  try {
    meilisearchClient = new MeiliSearch({
      host,
      apiKey: masterKey,
    });
    return meilisearchClient;
  } catch (error) {
    console.error("Failed to initialize Meilisearch client:", error);
    return null;
  }
};

/**
 * Initialize Meilisearch index with settings
 */
export const initMeilisearchIndex = async (): Promise<boolean> => {
  const client = getMeilisearchClient();
  if (!client) {
    return false;
  }

  try {
    const index = client.index(PROPERTIES_INDEX);

    // Configure index settings
    await index.updateSearchableAttributes(["title", "address"]);
    await index.updateFilterableAttributes([
      "propertyType",
      "propertyStatus",
      "locationSlug",
    ]);
    await index.updateSortableAttributes(["displayOrder", "createdAt"]);

    // Wait for task to complete
    await new Promise((resolve) => setTimeout(resolve, 100));

    return true;
  } catch (error) {
    console.error("Failed to initialize Meilisearch index:", error);
    return false;
  }
};

/**
 * Transform Strapi property data to Meilisearch document format
 */
export const transformPropertyToMeilisearchDoc = (property: any): any => {
  return {
    id: String(property.id),
    title: property.title || "",
    address: property.address || "",
    slug: property.slug || "",
    propertyType: property.propertyType || "",
    propertyStatus: property.propertyStatus || "",
    locationSlug: property.location?.slug || null,
    locationName: property.location?.name || null,
    createdAt: property.createdAt || new Date().toISOString(),
  };
};

/**
 * Sync a property to Meilisearch
 */
export const syncPropertyToMeilisearch = async (
  property: any
): Promise<boolean> => {
  const client = getMeilisearchClient();
  if (!client) {
    return false;
  }

  try {
    const index = client.index(PROPERTIES_INDEX);
    const doc = transformPropertyToMeilisearchDoc(property);

    await index.addDocuments([doc]);

    // Wait for task to complete (optional, but ensures data is indexed)
    await new Promise((resolve) => setTimeout(resolve, 100));

    return true;
  } catch (error) {
    console.error("Failed to sync property to Meilisearch:", error);
    return false;
  }
};

/**
 * Delete a property from Meilisearch
 */
export const deletePropertyFromMeilisearch = async (
  propertyId: string | number
): Promise<boolean> => {
  const client = getMeilisearchClient();
  if (!client) {
    return false;
  }

  try {
    const index = client.index(PROPERTIES_INDEX);
    await index.deleteDocument(String(propertyId));

    // Wait for task to complete
    await new Promise((resolve) => setTimeout(resolve, 100));

    return true;
  } catch (error) {
    console.error("Failed to delete property from Meilisearch:", error);
    return false;
  }
};

/**
 * Sync multiple properties to Meilisearch (for initial sync)
 */
export const syncPropertiesToMeilisearch = async (
  properties: any[]
): Promise<boolean> => {
  const client = getMeilisearchClient();
  if (!client) {
    return false;
  }

  try {
    const index = client.index(PROPERTIES_INDEX);
    const docs = properties.map(transformPropertyToMeilisearchDoc);

    await index.addDocuments(docs);

    // Wait for task to complete
    await new Promise((resolve) => setTimeout(resolve, 200));

    return true;
  } catch (error) {
    console.error("Failed to sync properties to Meilisearch:", error);
    return false;
  }
};
