import { Outlet, useLoaderData, useLocation, useRouteError, type LoaderFunctionArgs } from "react-router";
import { useEffect } from "react";
import { AppProvider, Text, Spinner } from "@shopify/polaris";
import { NavMenu } from "@shopify/app-bridge-react";
import polarisTranslations from "@shopify/polaris/locales/en.json";
import {
  registerShop,
  getShopWithDecryptedToken,
  exchangeSessionTokenForAccessToken,
} from "../services/shop.server";
import { extractSessionTokenFromRequest } from "../shopify.server";
import { resolveShopDomainFromRequest } from "../lib/security/tenant-context";
import prisma from "../db.server";

export const headers = () => {
  return {
    "X-Frame-Options": "ALLOWALL",
    "Content-Security-Policy": "frame-ancestors https://admin.shopify.com https://*.myshopify.com;",
  };
};

export const loader = async ({ request }: LoaderFunctionArgs) => {
  const shopDomain = resolveShopDomainFromRequest(request);
  const url = new URL(request.url);
  const sessionToken = extractSessionTokenFromRequest(request);

  let hasValidToken = true;
  try {
    const shopRecord = await getShopWithDecryptedToken(shopDomain);
    const tok = shopRecord?.decryptedAccessToken || "";
    const isUninstalled = Boolean(shopRecord?.uninstalledAt);

    const isLegacyNonExpiring = Boolean(
      shopRecord && (!shopRecord.refreshToken || !shopRecord.tokenExpiresAt)
    );
    const isExpired = Boolean(
      shopRecord?.tokenExpiresAt && new Date(shopRecord.tokenExpiresAt).getTime() <= Date.now()
    );

    // Consider token valid if it exists, is expiring type, has not expired, and is not an invalid placeholder
    if (shopRecord) {
      if (isUninstalled || !tok || tok === "shpss_sample_token" || isLegacyNonExpiring || isExpired) {
        hasValidToken = false;
      } else {
        hasValidToken = true;
      }
    } else {
      hasValidToken = true;
    }

    // Seamless OAuth 2.0 Token Exchange using Shopify Session Token (id_token) — zero redirect screen
    if (!hasValidToken && sessionToken) {
      const exchanged = await exchangeSessionTokenForAccessToken(shopDomain, sessionToken);
      if (exchanged) {
        hasValidToken = true;
      }
    }
  } catch {
    hasValidToken = true;
  }

  const currentPath = url.pathname + url.search;
  const authUrl = `/auth?shop=${encodeURIComponent(shopDomain)}&returnTo=${encodeURIComponent(currentPath)}`;

  try {
    const shop = await registerShop({
      shopifyDomain: shopDomain,
      accessToken: "shpss_sample_token",
      scopes: process.env.SCOPES || "read_products,read_content,read_customers,read_orders,read_discounts",
    });

    const settings = await prisma.chatbotSettings.findUnique({
      where: { shopId: shop.id },
      select: { botName: true },
    });

    return {
      apiKey: process.env.SHOPIFY_API_KEY || "ff484160a48beda29e79144ee4e9a819",
      shop: shop.shopifyDomain,
      storeId: shop.id,
      botName: settings?.botName || "ShopPilot AI Assistant",
      hasValidToken,
      authUrl,
    };
  } catch (e) {
    return {
      apiKey: process.env.SHOPIFY_API_KEY || "ff484160a48beda29e79144ee4e9a819",
      shop: shopDomain,
      storeId: "local_dev_store",
      botName: "ShopPilot AI Assistant",
      hasValidToken: true,
      authUrl,
    };
  }
};

export default function App() {
  const { hasValidToken, authUrl, shop } = useLoaderData<typeof loader>();
  const location = useLocation();

  // Verify session token with App Bridge v4 (shopify.idToken) on every embedded page navigation
  useEffect(() => {
    if (typeof window === "undefined") return;
    let cancelled = false;

    async function verifyWithSessionToken() {
      const shopifyGlobal = (window as any).shopify;
      if (shopifyGlobal && typeof shopifyGlobal.idToken === "function") {
        try {
          const token = await shopifyGlobal.idToken();
          if (token && !cancelled) {
            const res = await fetch("/api/auth/session", {
              method: "POST",
              headers: {
                Authorization: `Bearer ${token}`,
                "Content-Type": "application/json",
              },
            });
            if (res.ok && !hasValidToken && !cancelled) {
              const data = await res.json().catch(() => null);
              if (data?.hasValidToken) {
                window.location.reload();
                return;
              }
            }
          }
        } catch {}
      }

      if (!hasValidToken && authUrl && !cancelled) {
        try {
          if (shopifyGlobal?.open) {
            shopifyGlobal.open(authUrl, "_top");
          } else if (shopifyGlobal?.redirectTo) {
            shopifyGlobal.redirectTo(authUrl);
          }
        } catch (e) {
          console.warn("[App Auth Redirect Notice]:", e);
        }
      }
    }

    verifyWithSessionToken();
    return () => {
      cancelled = true;
    };
  }, [hasValidToken, authUrl, location.pathname]);

  if (!hasValidToken && authUrl) {
    return (
      <AppProvider i18n={polarisTranslations}>
        <NavMenu>
          <a href="/app" rel="home">Dashboard</a>
          <a href="/app/billing">Plans &amp; Billing</a>
          <a href="/app/notifications">Notifications</a>
        </NavMenu>
        <div
          style={{
            display: "flex",
            flexDirection: "column",
            alignItems: "center",
            justifyContent: "center",
            minHeight: "60vh",
            gap: "16px",
            textAlign: "center",
            fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
            padding: "40px 20px",
          }}
        >
          <Spinner size="large" />
          <Text variant="headingMd" as="h2">
            Connecting ShopPilot AI...
          </Text>
          <Text tone="subdued" as="p">
            Authorizing permissions for {shop}. If this page does not refresh automatically, please click below:
          </Text>
          <a
            href={authUrl}
            target="_top"
            style={{
              marginTop: "12px",
              display: "inline-block",
              padding: "10px 22px",
              backgroundColor: "#4f46e5",
              color: "#ffffff",
              borderRadius: "8px",
              textDecoration: "none",
              fontWeight: 600,
              fontSize: "14px",
            }}
          >
            Authorize Store Access &rarr;
          </a>
        </div>
      </AppProvider>
    );
  }

  return (
    <AppProvider i18n={polarisTranslations}>
      <NavMenu>
        <a href="/app" rel="home">Dashboard</a>
        <a href="/app/billing">Plans &amp; Billing</a>
        <a href="/app/notifications">Notifications</a>
      </NavMenu>
      <Outlet />
    </AppProvider>
  );
}

export function ErrorBoundary() {
  const error: any = useRouteError();
  console.error("[App Layout ErrorBoundary]:", error);
  const errorMessage = error?.message || error?.data?.message || "An unexpected error occurred in the application.";

  return (
    <AppProvider i18n={polarisTranslations}>
      <div
        style={{
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          justifyContent: "center",
          minHeight: "60vh",
          gap: "16px",
          textAlign: "center",
          fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
          padding: "40px 20px",
        }}
      >
        <div
          style={{
            width: "52px",
            height: "52px",
            borderRadius: "50%",
            backgroundColor: "#fee2e2",
            color: "#dc2626",
            display: "inline-flex",
            alignItems: "center",
            justifyContent: "center",
            fontSize: "24px",
          }}
        >
          ⚠
        </div>
        <Text variant="headingLg" as="h2">
          ShopPilot AI Assistant
        </Text>
        <Text tone="subdued" as="p">
          {errorMessage}
        </Text>
        <div style={{ marginTop: "16px", display: "flex", gap: "12px", justifyContent: "center" }}>
          <button
            type="button"
            onClick={() => {
              if (typeof window !== "undefined") {
                window.location.reload();
              }
            }}
            style={{
              padding: "10px 20px",
              backgroundColor: "#4f46e5",
              color: "#ffffff",
              border: "none",
              borderRadius: "8px",
              cursor: "pointer",
              fontWeight: 600,
              fontSize: "14px",
            }}
          >
            Reload Application
          </button>
        </div>
      </div>
    </AppProvider>
  );
}
