import { authenticate, unauthenticated } from "../shopify.server";

const jsonResponse = (data, status = 200) => {
  return new Response(JSON.stringify(data), {
    status,
    headers: {
      "Content-Type": "application/json",
      "Access-Control-Allow-Origin": "*",
      "Cache-Control": "no-store",
    },
  });
};

async function ensureDefinition(admin) {
  console.log(">>> [DEBUG] Triggering Metaobject Definition Creation...");
  const mutation = `#graphql
    mutation CreateMetaobjectDefinition($definition: MetaobjectDefinitionCreateInput!) {
      metaobjectDefinitionCreate(definition: $definition) {
        metaobjectDefinition { type }
        userErrors { field message }
      }
    }
  `;

  const variables = {
    definition: {
      name: "Product Review",
      type: "product_review",
      access: { admin: "MERCHANT_READ_WRITE", storefront: "PUBLIC_READ" },
      capabilities: { publishable: { enabled: true } },
      fieldDefinitions: [
        { name: "Product ID", key: "product_id", type: "single_line_text_field", required: true },
        { name: "Customer Name", key: "customer_name", type: "single_line_text_field" },
        { name: "Review Content", key: "content", type: "multi_line_text_field" },
        { name: "Rating", key: "rating", type: "single_line_text_field" }
      ]
    }
  };

  const response = await admin.graphql(mutation, { variables });
  const result = await response.json();
  console.log(">>> [DEBUG] Creation Result:", JSON.stringify(result));
  return result;
}

export const loader = async ({ request }) => {
  try {
    const { admin, session } = await authenticate.public.appProxy(request);
    const url = new URL(request.url);
    const productId = url.searchParams.get("productId");

    if (!productId) return jsonResponse([]);

    const query = `#graphql
      query getReviews($query: String!) {
        metaobjects(first: 50, type: "product_review", query: $query) {
          edges { node { fields { key value } } }
        }
      }
    `;

    const response = await admin.graphql(query, {
      variables: { query: `product_id:${productId}` },
    });

    const data = await response.json();

    // Check for "No definition" error
    const isMissing = data.errors?.some(e => e.message.toLowerCase().includes("metaobject definition")) || !data.data?.metaobjects;
    if (isMissing) {
      console.log(">>> [DEBUG] Loader: Definition missing. Attempting to create...");
      await ensureDefinition(admin);
      return jsonResponse([]);
    }

    const reviews = (data.data?.metaobjects?.edges || []).map((edge) => {
      const fields = {};
      edge.node.fields.forEach((f) => { fields[f.key] = f.value; });
      return {
        name: fields.customer_name || "Anonymous",
        review: fields.content || "",
        rating: fields.rating || "5",
      };
    });

    return jsonResponse(reviews);
  } catch (err) {
    console.error(">>> [ERROR] Loader:", err.message);
    return jsonResponse([]);
  }
};

export const action = async ({ request }) => {
  try {
    console.log(">>> [DEBUG] Action: Review Submission Started");
    const { admin, session } = await authenticate.public.appProxy(request);
    const url = new URL(request.url);
    const customerId = url.searchParams.get("logged_in_customer_id");

    if (!customerId) return jsonResponse({ error: "Please log in to leave a review." });

    const formData = await request.formData();
    const productId = formData.get("productId");
    const name = formData.get("name");
    const review = formData.get("review");

    // 1. Purchase Check
    const orderQuery = `#graphql
      query getOrders($query: String!) {
        orders(first: 10, query: $query) {
          edges { node { lineItems(first: 20) { edges { node { product { id } } } } } }
        }
      }
    `;

    const orderResponse = await admin.graphql(orderQuery, {
      variables: { query: `customer_id:${customerId}` }
    });

    const orderData = await orderResponse.json();
    const hasPurchased = (orderData.data?.orders?.edges || []).some(o =>
      o.node.lineItems.edges.some(i => i.node.product?.id?.includes(productId))
    );

    if (!hasPurchased) {
      console.log(">>> [DEBUG] Action: No purchase history found for Customer ID:", customerId);
      return jsonResponse({ error: "Only verified buyers can leave a review. (Note: It may take a few minutes for new orders to sync)" });
    }

    // 2. Save Review
    const saveMutation = `#graphql
      mutation create($m: MetaobjectCreateInput!) { metaobjectCreate(metaobject: $m) { metaobject { id } userErrors { field message } } }
    `;

    const saveResponse = await admin.graphql(saveMutation, {
      variables: {
        m: {
          type: "product_review",
          fields: [
            { key: "product_id", value: String(productId) },
            { key: "customer_name", value: String(name) },
            { key: "content", value: String(review) },
            { key: "rating", value: "5" }
          ]
        }
      }
    });

    const result = await saveResponse.json();
    console.log(">>> [DEBUG] Save Result:", JSON.stringify(result));

    // Check for "No definition" error
    const isMissing = result.errors?.some(e => e.message.toLowerCase().includes("metaobject definition")) ||
      result.data?.metaobjectCreate === null;

    if (isMissing) {
      console.log(">>> [DEBUG] Action: Definition missing. Creating structure...");
      const createResult = await ensureDefinition(admin);
      const creationError = createResult.data?.metaobjectDefinitionCreate?.userErrors?.[0]?.message;

      if (creationError && !creationError.includes("already exists")) {
        return jsonResponse({ error: "Storefront permissions need update. Please open the App Admin page once to fix." });
      }
      return jsonResponse({ error: "SUCCESS: Database structure created! Please click Submit Review one last time to save your review." });
    }

    const errors = result.data?.metaobjectCreate?.userErrors;
    if (errors && errors.length > 0) {
      return jsonResponse({ error: errors[0].message });
    }

    console.log(">>> [DEBUG] Action: Review Saved Successfully!");
    return jsonResponse({ success: true });
  } catch (err) {
    console.error(">>> [ERROR] Action Exception:", err.message);
    return jsonResponse({ error: "Connection issue. Please refresh the page and try again." });
  }
};