import { ShopifyAdminClient } from "../lib/shopify/admin";
import { getTenantByDomain } from "../lib/security/tenant-context";
import { verifyAndGetCustomer } from "./customer.server";
import { UnauthorizedError } from "../lib/security/errors";
import { logger } from "../lib/security/logger";
import prisma from "../db.server";

export interface OrderQueryOptions {
  shopDomain: string;
  customerAccessToken: string;
  orderId?: string;
}

/**
 * Formats a Shopify order object into a rich, structured user-facing update response.
 */
export function formatOrderResponse(o: any, cleanOrder: string): string {
  const orderName = o.name || `#${cleanOrder}`;
  const orderDate = o.createdAt
    ? new Date(o.createdAt).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" })
    : "Recent";
  const financialStatus = (o.displayFinancialStatus || "PAID").toUpperCase();
  const rawFulfillment = (o.displayFulfillmentStatus || "UNFULFILLED").toUpperCase();

  // Format fulfillment status
  let fulfillmentLabel = "Processing / Unfulfilled";
  if (rawFulfillment === "FULFILLED") fulfillmentLabel = "Fulfilled / Shipped";
  else if (rawFulfillment === "IN_TRANSIT") fulfillmentLabel = "In Transit";
  else if (rawFulfillment === "OUT_FOR_DELIVERY") fulfillmentLabel = "Out for Delivery";
  else if (rawFulfillment === "DELIVERED") fulfillmentLabel = "Delivered";
  else if (rawFulfillment === "ATTEMPTED_DELIVERY") fulfillmentLabel = "Delivery Attempted";
  else if (rawFulfillment === "PARTIALLY_FULFILLED") fulfillmentLabel = "Partially Fulfilled";
  else if (rawFulfillment === "RESTOCKED") fulfillmentLabel = "Restocked / Returned";

  if (o.cancelledAt) {
    fulfillmentLabel = `Cancelled (${o.cancelReason || "Customer Request"})`;
  }

  const currency = o.totalPriceSet?.presentmentMoney?.currencyCode || "USD";
  const totalAmount = o.totalPriceSet?.presentmentMoney?.amount || "0.00";

  const lines: string[] = [
    `<i class="fa fa-box"></i> **Order ${orderName} Details & Status:**\n`,
    `• **Order Date:** ${orderDate}`,
    `• **Fulfillment Status:** ${fulfillmentLabel}`,
    `• **Payment Status:** ${financialStatus}`,
    `• **Total:** $${totalAmount} ${currency}`,
  ];

  // Tracking Information
  const fulfillments = o.fulfillments || [];
  const allTracking: Array<{ company?: string; number?: string; url?: string }> = [];
  for (const f of fulfillments) {
    if (f.trackingInfo && Array.isArray(f.trackingInfo)) {
      allTracking.push(...f.trackingInfo);
    }
  }

  if (allTracking.length > 0) {
    lines.push(`\n<i class="fa fa-truck"></i> **Shipment & Tracking Information:**`);
    for (const t of allTracking) {
      if (t.number) {
        const carrier = t.company ? ` (${t.company})` : "";
        if (t.url) {
          lines.push(`• **Tracking:** [${t.number}${carrier}](${t.url})`);
        } else {
          lines.push(`• **Tracking:** ${t.number}${carrier}`);
        }
      }
    }
  }

  // Shipping Address Destination
  if (o.shippingAddress) {
    const addr = o.shippingAddress;
    const destParts = [addr.city, addr.province || addr.provinceCode, addr.zip, addr.country || addr.countryCodeV2].filter(Boolean);
    if (destParts.length > 0) {
      lines.push(`• **Delivery Address:** ${destParts.join(", ")}`);
    }
  }

  // Items Ordered
  const items = o.lineItems?.edges || [];
  if (items.length > 0) {
    lines.push(`\n**Items Ordered:**`);
    for (const itemEdge of items) {
      const item = itemEdge.node;
      const variantInfo = item.variantTitle && item.variantTitle !== "Default Title" ? ` (${item.variantTitle})` : "";
      const price = item.originalUnitPriceSet?.presentmentMoney?.amount
        ? ` - $${item.originalUnitPriceSet.presentmentMoney.amount}`
        : "";
      lines.push(`• ${item.title}${variantInfo} × ${item.quantity}${price}`);
    }
  }

  return lines.join("\n");
}

/**
 * Fetches orders strictly tied to an authenticated customer identity.
 * NO FAKE/MOCK DATA: Strictly returns real Shopify order records.
 */
export async function getCustomerOrdersService({ shopDomain, customerAccessToken, orderId }: OrderQueryOptions) {
  const tenant = await getTenantByDomain(shopDomain);
  const adminClient = new ShopifyAdminClient({ shopifyDomain: shopDomain });

  // 1. Verify customer identity via Customer Account API / signed session
  let customerSession: any = null;
  try {
    customerSession = await verifyAndGetCustomer(shopDomain, customerAccessToken);
  } catch (authErr) {
    // If specific orderId requested, allow secure track
    if (orderId) {
      return trackOrderSecurelyService({
        shopDomain,
        orderNumber: orderId,
        customerAccessToken,
      });
    }
    throw authErr;
  }

  try {
    if (orderId) {
      const cleanOrderId = orderId.replace(/^#/, "").trim();
      const result = await adminClient.findOrderByNumber(cleanOrderId);
      const order = result?.order;

      if (!order) {
        return {
          success: false,
          reply: `<i class="fa fa-box"></i> We could not find order **#${cleanOrderId}** in Shopify. Please verify your order number.`,
          intent: "order_status",
        };
      }

      const reply = formatOrderResponse(order, cleanOrderId);
      return {
        success: true,
        reply,
        intent: "order_status",
        orderInfo: {
          orderNumber: order.name,
          status: order.displayFulfillmentStatus || "Processing",
          financialStatus: order.displayFinancialStatus || "Paid",
          total: order.totalPriceSet?.presentmentMoney?.amount || "0.00",
        },
      };
    }

    // Fetch customer's orders
    let orders: any[] = [];
    if (customerSession?.shopifyCustomerId) {
      orders = await adminClient.getCustomerOrders(customerSession.shopifyCustomerId).catch(() => []);
    }

    if (orders.length === 0 && customerSession?.email) {
      const custByEmail = await adminClient.findCustomerByEmail(customerSession.email).catch(() => null);
      const custNode = custByEmail?.customers?.edges?.[0]?.node;
      if (custNode?.id) {
        orders = await adminClient.getCustomerOrders(custNode.id).catch(() => []);
      }
    }

    if (orders.length === 0) {
      const searchRes = await adminClient.getOrders(20).catch(() => null);
      const allOrders = searchRes?.orders?.edges || [];
      const sessionEmail = (customerSession?.email || "").toLowerCase().trim();
      const sessionCustId = (customerSession?.shopifyCustomerId || "").split("/").pop();
      const sessionName = `${customerSession?.firstName || ""} ${customerSession?.lastName || ""}`.toLowerCase().replace(/[^a-z0-9]/g, "");

      orders = allOrders.filter((e: any) => {
        const oCustId = (e.node?.customer?.id || "").split("/").pop();
        const oEmail = (e.node?.email || e.node?.customer?.email || "").toLowerCase().trim();
        const oName = `${e.node?.customer?.firstName || ""} ${e.node?.customer?.lastName || ""}`.toLowerCase().replace(/[^a-z0-9]/g, "");

        if (sessionCustId && oCustId && sessionCustId === oCustId) return true;
        if (sessionEmail && oEmail && sessionEmail === oEmail) return true;
        if (sessionName && sessionName.length >= 3 && oName === sessionName) return true;
        return false;
      });
    }

    if (orders.length === 0) {
      return {
        success: true,
        reply: `<i class="fa fa-box"></i> **Order History for ${customerSession?.email || "Your Account"}:**\n\nYou currently have no past orders associated with your store account. To track a specific order, please reply with your **Order Number** (e.g. #1002).`,
        intent: "order_status",
      };
    }

    const summary = orders
      .map(
        (e: any) =>
          `• **${e.node?.name || "Order"}:** ${e.node?.displayFulfillmentStatus || "Processing"} ($${e.node?.totalPriceSet?.presentmentMoney?.amount || "0.00"} ${e.node?.totalPriceSet?.presentmentMoney?.currencyCode || "USD"})`
      )
      .join("\n");

    return {
      success: true,
      reply: `<i class="fa fa-box"></i> **Your Recent Orders:**\n\n${summary}\n\nTo see detailed items or tracking for a specific order, reply with the order number (e.g. **${orders[0]?.node?.name || "#1002"}**).`,
      intent: "order_status",
    };
  } catch (err: any) {
    logger.error("getCustomerOrdersService exception", err);
    return {
      success: false,
      reply: `Unable to retrieve your order details from Shopify right now. Please try again in a moment.`,
      intent: "order_status",
    };
  }
}

/**
 * Safe Order Cancellation Workflow with explicit confirmation check and audit log.
 */
export async function cancelOrderService({
  shopDomain,
  customerAccessToken,
  orderId,
  confirmed,
  sessionId,
}: {
  shopDomain: string;
  customerAccessToken: string;
  orderId: string;
  confirmed: boolean;
  sessionId?: string;
}) {
  const tenant = await getTenantByDomain(shopDomain);
  const customerSession = await verifyAndGetCustomer(shopDomain, customerAccessToken);

  // Require explicit confirmation
  if (!confirmed) {
    return {
      requiresConfirmation: true,
      reply: `⚠️ Are you sure you want to cancel order **${orderId}**? This action cannot be undone. Please reply 'yes' to confirm.`,
      intent: "general_qa",
    };
  }

  try {
    const adminClient = new ShopifyAdminClient({ shopifyDomain: shopDomain });
    const cancelResult = await adminClient.cancelOrder(orderId, "CUSTOMER", true);
    const userErrors = cancelResult.orderCancel?.userErrors || [];

    if (userErrors.length > 0) {
      const errorMsg = userErrors[0].message;
      await prisma.auditLog.create({
        data: {
          shopId: tenant.shopId,
          sessionId,
          action: "cancel_order",
          resource: "Order",
          resourceId: orderId,
          status: "FAILED",
          metadata: { errorMsg, customerId: customerSession.shopifyCustomerId },
        },
      });

      return {
        success: false,
        reply: `Unable to cancel order: ${errorMsg}`,
        intent: "general_qa",
      };
    }
  } catch (e: any) {
    await prisma.auditLog.create({
      data: {
        shopId: tenant.shopId,
        sessionId,
        action: "cancel_order",
        resource: "Order",
        resourceId: orderId,
        status: "FAILED",
        metadata: { error: e.message, customerId: customerSession.shopifyCustomerId },
      },
    });

    return {
      success: false,
      reply: `Unable to process order cancellation with Shopify at this time: ${e.message}`,
      intent: "general_qa",
    };
  }

  // Create Audit Log entry
  await prisma.auditLog.create({
    data: {
      shopId: tenant.shopId,
      sessionId,
      action: "cancel_order",
      resource: "Order",
      resourceId: orderId,
      status: "SUCCESS",
      metadata: { customerId: customerSession.shopifyCustomerId, confirmed: true },
    },
  });

  return {
    success: true,
    reply: `Order **${orderId}** has been successfully cancelled. A confirmation email has been sent to ${customerSession.email || "your email"}.`,
    intent: "general_qa",
  };
}

/**
 * Securely fetches order status and real-time tracking from Shopify.
 * Enforces order number + customer email/zip/phone verification.
 * ZERO TOLERANCE: Never invents fake order status or fake tracking numbers.
 */
export async function trackOrderSecurelyService({
  shopDomain,
  orderNumber,
  emailOrZip,
  customerAccessToken,
}: {
  shopDomain: string;
  orderNumber: string;
  emailOrZip?: string;
  customerAccessToken?: string;
}) {
  await getTenantByDomain(shopDomain);
  const cleanOrder = (orderNumber || "").trim().replace(/^#/, "");
  const cleanAuth = (emailOrZip || "").trim().toLowerCase();

  if (!cleanOrder) {
    return {
      success: false,
      reply: '<i class="fa fa-box"></i> To check your order status, please provide your **Order Number** (e.g. #1001) along with your **Email Address** or **Shipping ZIP code**.',
      intent: "order_status",
    };
  }

  try {
    const adminClient = new ShopifyAdminClient({ shopifyDomain: shopDomain });
    const orderRes = await adminClient.findOrderByNumber(cleanOrder).catch(() => null);

    if (orderRes && orderRes.order) {
      const o = orderRes.order;

      // Extract all candidate authorization fields from the authentic Shopify order
      const candidateEmails: string[] = [
        o.email,
        o.contactEmail,
        o.customer?.email,
        o.customer?.contactEmail,
        o.shippingAddress?.email,
        o.billingAddress?.email,
      ]
        .filter(Boolean)
        .map((e: string) => String(e).toLowerCase().trim());

      const candidateZips: string[] = [
        o.shippingAddress?.zip,
        o.billingAddress?.zip,
        o.customer?.defaultAddress?.zip,
      ]
        .filter(Boolean)
        .map((z: string) => String(z).toLowerCase().replace(/\s+/g, ""));

      const candidatePhones: string[] = [
        o.phone,
        o.customer?.phone,
        o.shippingAddress?.phone,
        o.billingAddress?.phone,
      ]
        .filter(Boolean)
        .map((p: string) => String(p).replace(/[^\d]/g, ""));

      // Enrich candidate verification data directly from customer profile if customer ID exists
      if (o.customer?.id) {
        try {
          const custRes = await adminClient.getCustomer(o.customer.id);
          const cust = custRes?.customer;
          if (cust) {
            if (cust.email) {
              const cEm = String(cust.email).toLowerCase().trim();
              if (!candidateEmails.includes(cEm)) {
                candidateEmails.push(cEm);
              }
            }
            if (cust.defaultAddress?.zip) {
              const cZip = String(cust.defaultAddress.zip).toLowerCase().replace(/\s+/g, "");
              if (!candidateZips.includes(cZip)) {
                candidateZips.push(cZip);
              }
            }
            if (cust.phone) {
              const cPh = String(cust.phone).replace(/[^\d]/g, "");
              if (cPh && !candidatePhones.includes(cPh)) {
                candidatePhones.push(cPh);
              }
            }
          }
        } catch (custErr) {}
      }

      const cleanAuthLower = cleanAuth.toLowerCase().trim();
      const cleanAuthNoSpaces = cleanAuthLower.replace(/\s+/g, "");
      const cleanAuthDigits = cleanAuth.replace(/[^\d]/g, "");

      let isVerified = false;

      // 1. Authenticated customer session check
      if (customerAccessToken) {
        try {
          const customerSession = await verifyAndGetCustomer(shopDomain, customerAccessToken).catch(() => null);
          if (customerSession) {
            const sessionEmail = (customerSession.email || "").toLowerCase().trim();
            const sessionCustId = (customerSession.shopifyCustomerId || "").split("/").pop();
            const orderCustId = (o.customer?.id || "").split("/").pop();

            if (
              (sessionEmail && candidateEmails.includes(sessionEmail)) ||
              (sessionCustId && orderCustId && sessionCustId === orderCustId)
            ) {
              isVerified = true;
            }
          }
        } catch (authErr) {}
      }

      // 2. Exact verification against candidate emails, zips, or phones
      if (!isVerified && cleanAuthLower) {
        const isInputEmail = cleanAuthLower.includes("@");

        if (isInputEmail) {
          // A. Exact email check against candidate fields on the order or linked customer
          for (const em of candidateEmails) {
            if (em && em === cleanAuthLower) {
              isVerified = true;
              break;
            }
          }

          // B. If not matched directly, search customer account in Shopify
          if (!isVerified) {
            try {
              const custRes = await adminClient.findCustomerByEmail(cleanAuthLower);
              const custNode = custRes?.customers?.edges?.[0]?.node;
              if (custNode) {
                const custEmail = (custNode.email || "").toLowerCase().trim();
                const orderCustId = (o.customer?.id || "").split("/").pop();
                const foundCustId = (custNode.id || "").split("/").pop();

                if (custEmail === cleanAuthLower && orderCustId && foundCustId && orderCustId === foundCustId) {
                  isVerified = true;
                }

                if (!isVerified && custNode.orders?.edges?.length) {
                  const hasMatchingOrder = custNode.orders.edges.some((e: any) => {
                    const oName = String(e.node?.name || "").replace(/^#/, "").trim().toLowerCase();
                    const oNum = String(e.node?.orderNumber || "").trim().toLowerCase();
                    const oId = String(e.node?.id || "").split("/").pop()?.trim().toLowerCase();
                    return oName === cleanOrder.toLowerCase() || oNum === cleanOrder.toLowerCase() || oId === cleanOrder.toLowerCase();
                  });
                  if (hasMatchingOrder) {
                    isVerified = true;
                  }
                }
              }
            } catch (custCheckErr) {}
          }

          // C. Protected Customer Data Fallback: Match customer first/last name with email username prefix
          if (!isVerified) {
            const emailUserClean = cleanAuthLower.split("@")[0].toLowerCase().replace(/[^a-z0-9]/g, "");
            const custFirst = (o.customer?.firstName || "").toLowerCase().replace(/[^a-z0-9]/g, "");
            const custLast = (o.customer?.lastName || "").toLowerCase().replace(/[^a-z0-9]/g, "");
            const custFullName = (o.customer?.displayName || o.customer?.name || `${custFirst}${custLast}`).toLowerCase().replace(/[^a-z0-9]/g, "");
            const shipName = (o.shippingAddress?.name || "").toLowerCase().replace(/[^a-z0-9]/g, "");
            const billName = (o.billingAddress?.name || "").toLowerCase().replace(/[^a-z0-9]/g, "");

            const nameCandidates = [
              `${custFirst}${custLast}`,
              `${custLast}${custFirst}`,
              custFullName,
              shipName,
              billName,
            ].filter((n) => n && n.length >= 3);

            if (nameCandidates.includes(emailUserClean)) {
              isVerified = true;
            }
          }
        } else {
          // Exact ZIP / Postal Code check (spaces removed, case-insensitive)
          for (const zp of candidateZips) {
            if (zp && (zp === cleanAuthNoSpaces || zp.replace(/[^\w]/g, "") === cleanAuthNoSpaces.replace(/[^\w]/g, ""))) {
              isVerified = true;
              break;
            }
          }

          // Phone number check (if at least 7 digits)
          if (!isVerified && cleanAuthDigits.length >= 7) {
            for (const ph of candidatePhones) {
              if (ph && (ph === cleanAuthDigits || ph.endsWith(cleanAuthDigits) || cleanAuthDigits.endsWith(ph))) {
                isVerified = true;
                break;
              }
            }
          }
        }
      }

      // If user provided an order number but no verification credentials yet, prompt them clearly
      if (!cleanAuth && !isVerified) {
        return {
          success: false,
          reply: `<i class="fa fa-lock"></i> Found order **#${cleanOrder}**! For security verification, please provide the **Email Address** or **Shipping ZIP Code** used for this order.`,
          intent: "order_status",
        };
      }

      if (isVerified) {
        const reply = formatOrderResponse(o, cleanOrder);
        return {
          success: true,
          reply,
          intent: "order_status",
          orderInfo: o,
        };
      } else {
        return {
          success: false,
          reply: `<i class="fa fa-lock"></i> Authorization verification failed. The email address or postal code provided does not match order **#${cleanOrder}**. Please verify your details.`,
          intent: "order_status",
        };
      }
    }
  } catch (e: any) {
    logger.error("trackOrderSecurelyService error", e);
  }

  // Fail truthfully if order not found in Shopify
  return {
    success: false,
    reply: `<i class="fa fa-box"></i> We could not find order **#${cleanOrder}** in Shopify. Please verify the order number and your email address or shipping ZIP code.`,
    intent: "order_status",
  };
}
