import type { ActionFunctionArgs, LoaderFunctionArgs } from "react-router";
import { useLoaderData, useActionData, Form } from "react-router";
import { useEffect } from "react";
import {
  Page,
  Layout,
  Card,
  Text,
  BlockStack,
  InlineGrid,
  InlineStack,
  Badge,
  Banner,
  Button,
  ProgressBar,
  Box,
  List,
  Divider,
} from "@shopify/polaris";
import { authenticate } from "../shopify.server";
import { registerShop } from "../services/shop.server";
import { createShopifyAppSubscription } from "../services/shopify-billing.server";
import { SubscriptionService } from "../services/subscription.server";
import { PLAN_CONFIGS, ACTIVE_PLAN_TIERS, FEATURE_MATRIX_ROWS } from "../lib/billing-plans";
import prisma from "../db.server";
import { PlanTier } from "@prisma/client";
import { FAIcon } from "../components/FAIcon";

export const loader = async ({ request }: LoaderFunctionArgs) => {
  const { session } = await authenticate.admin(request);
  const shop = await registerShop({
    shopifyDomain: session.shop,
    accessToken: session.accessToken || "shpss_sample_token",
    scopes: (session as any).scope || "read_products,read_content",
  });

  const url = new URL(request.url);
  const chargeId = url.searchParams.get("charge_id") || url.searchParams.get("chargeId");
  const planParam = url.searchParams.get("plan");

  let activationNotice: { title: string; message: string; tone: "success" | "critical" } | null = null;

  // Handle Return Callback from Shopify Billing Approval Screen
  if (chargeId && planParam) {
    try {
      const normalizedPlan = (planParam.toUpperCase() as PlanTier);
      await SubscriptionService.transitionSubscriptionPlan({
        shopId: shop.id,
        newPlan: normalizedPlan,
        shopifySubscriptionId: chargeId,
      });

      activationNotice = {
        title: "Shopify Subscription Activated",
        message: `Your store has successfully subscribed to the ${normalizedPlan} Plan via Shopify Billing.`,
        tone: "success",
      };
    } catch (err: any) {
      console.error("[Shopify Billing] Error activating plan on return callback:", err);
      activationNotice = {
        title: "Subscription Activation Error",
        message: err.message || "Failed to finalize subscription with Shopify.",
        tone: "critical",
      };
    }
  }

  const subscription = await prisma.subscription.findFirst({
    where: { shopId: shop.id, status: "ACTIVE" },
    orderBy: { createdAt: "desc" },
  });

  const { getPlansDictionary, getActivePlans } = await import("../services/plan-config.server");
  const plansDict = await getPlansDictionary();
  const activePlans = await getActivePlans();

  const currentPlan = (subscription?.plan || "FREE") as string;
  const currentPlanConfig = plansDict[currentPlan] || PLAN_CONFIGS[currentPlan as PlanTier] || PLAN_CONFIGS.FREE;
  const currentUsage = currentPlanConfig.aiMonthlyLimit ? (subscription?.currentUsage || 0) : 0;
  const aiMonthlyLimit = currentPlanConfig.aiMonthlyLimit;
  const usagePercentage = aiMonthlyLimit ? Math.min(100, Math.round((currentUsage / aiMonthlyLimit) * 100)) : 0;

  return {
    shop: session.shop,
    currentPlan,
    currentPlanConfig,
    currentUsage,
    aiMonthlyLimit,
    usagePercentage,
    activePlans,
    plansDict,
    activationNotice,
  };
};

export const action = async ({ request }: ActionFunctionArgs) => {
  const { session } = await authenticate.admin(request);
  const formData = await request.formData();
  const plan = formData.get("plan") as string;

  const { getPlanByIdOrKey } = await import("../services/plan-config.server");
  const planConfig = await getPlanByIdOrKey(plan);

  if (planConfig && planConfig.isActive === false) {
    return { success: false, message: `The ${planConfig.displayName || plan} plan is currently inactive and cannot be selected.` };
  }

  const targetConfig = planConfig || PLAN_CONFIGS[plan as PlanTier];
  if (!plan || !targetConfig) {
    return { success: false, message: "Invalid plan selected." };
  }

  // Free Tier ($0) - Instant transition without Shopify charge
  if (targetConfig.price === 0) {
    const shop = await registerShop({
      shopifyDomain: session.shop,
      accessToken: session.accessToken || "shpss_sample_token",
      scopes: (session as any).scope || "read_products,read_content",
    });
    await SubscriptionService.transitionSubscriptionPlan({
      shopId: shop.id,
      newPlan: "FREE",
      shopifySubscriptionId: `gid://shopify/AppSubscription/free_${Date.now()}`,
    });

    return {
      success: true,
      plan: "FREE",
      message: "Downgraded to Free tier successfully.",
    };
  }

  // Paid Tier (Starter, Pro, etc.) - Create Shopify GraphQL App Subscription
  const origin = new URL(request.url).origin;
  const returnUrl = `${origin}/app/billing?shop=${session.shop}&plan=${plan}`;

  const shopifySub = await createShopifyAppSubscription({
    shopDomain: session.shop,
    planName: targetConfig.displayName || plan,
    planKey: plan,
    price: targetConfig.price,
    returnUrl,
    trialDays: 7,
    isTest: process.env.NODE_ENV !== "production",
  });

  if (!shopifySub.success || !shopifySub.confirmationUrl) {
    return {
      success: false,
      message: shopifySub.error || "Failed to initiate charge with Shopify Billing API.",
    };
  }

  return {
    success: true,
    confirmationUrl: shopifySub.confirmationUrl,
    plan,
    isRedirect: true,
  };
};

export default function BillingPage() {
  const {
    shop,
    currentPlan,
    currentPlanConfig,
    currentUsage,
    aiMonthlyLimit,
    usagePercentage,
    activePlans,
    plansDict,
    activationNotice,
  } = useLoaderData<typeof loader>();
  const actionData = useActionData<typeof action>();

  // Redirect top window when Shopify confirmation URL is provided
  useEffect(() => {
    if (actionData?.confirmationUrl) {
      try {
        if (window.top) {
          window.top.location.href = actionData.confirmationUrl;
        } else {
          window.location.href = actionData.confirmationUrl;
        }
      } catch (e) {
        window.location.href = actionData.confirmationUrl;
      }
    }
  }, [actionData]);

  const displayPlans = activePlans && activePlans.length > 0 ? activePlans : [];

  return (
    <Page
      title="SaaS Plans & Subscription Billing"
      subtitle="Official Shopify App Store billing with 7-day free trial on paid plans."
    >
      <BlockStack gap="500">
        {activationNotice && (
          <Banner title={activationNotice.title} tone={activationNotice.tone}>
            <p>{activationNotice.message}</p>
          </Banner>
        )}

        {actionData?.message && (
          <Banner title={actionData.success ? "Notice" : "Billing Error"} tone={actionData.success ? "success" : "critical"}>
            <p>{actionData.message}</p>
          </Banner>
        )}

        {actionData?.confirmationUrl && (
          <Banner title="Redirecting to Shopify Billing..." tone="info">
            <p>
              Please complete charge confirmation on Shopify's secure portal:{" "}
              <a href={actionData.confirmationUrl} target="_top" style={{ fontWeight: "bold" }}>
                Click here if not redirected automatically
              </a>
            </p>
          </Banner>
        )}

        {/* Current Plan & Usage Progress */}
        <Layout>
          <Layout.Section>
            <Card padding="500">
              <BlockStack gap="400">
                <InlineGrid columns="1fr auto">
                  <Text as="h2" variant="headingMd">
                    <FAIcon name="credit-card" style={{ color: "#4F46E5", marginRight: "8px" }} /> Current Store Plan
                  </Text>
                  <Badge tone={currentPlan === "FREE" ? "info" : "success"}>
                    {`${currentPlanConfig.displayName.toUpperCase()} (${currentPlanConfig.billingInterval === "ONE_TIME" ? "One-time" : "Monthly"})`}
                  </Badge>
                </InlineGrid>

                {aiMonthlyLimit !== null ? (
                  <BlockStack gap="200">
                    <InlineGrid columns="1fr auto">
                      <Text as="p" variant="bodyMd">
                        AI Usage: <strong>{currentUsage.toLocaleString()} / {aiMonthlyLimit.toLocaleString()}</strong> requests
                      </Text>
                      <Text as="p" variant="bodySm" tone="subdued">
                        {usagePercentage}% used
                      </Text>
                    </InlineGrid>
                    <ProgressBar progress={usagePercentage} tone={usagePercentage >= 90 ? "critical" : "primary"} />

                    {usagePercentage >= 90 && (
                      <Banner title="Approaching AI Usage Limit" tone="warning">
                        <p>You have reached {usagePercentage}% of your monthly AI requests quota. Upgrading your plan will provide higher request limits.</p>
                      </Banner>
                    )}
                  </BlockStack>
                ) : (
                  <InlineGrid columns="1fr auto">
                    <Text as="p" variant="bodyMd">
                      AI Usage: <strong>N/A</strong> (OpenAI & AI features not included in this plan)
                    </Text>
                    <Text as="p" variant="bodySm" tone="subdued">
                      Upgrade to Pro for AI features
                    </Text>
                  </InlineGrid>
                )}
              </BlockStack>
            </Card>
          </Layout.Section>

          {/* Pricing Grid Cards */}
          <Layout.Section>
            <InlineGrid columns={{ xs: 1, sm: 1, md: 3 }} gap="400">
              {displayPlans.map((config: any) => {
                const p = config.planKey || config.name;
                const isCurrent = currentPlan === p;
                const isOneTime = config.billingInterval === "ONE_TIME";

                return (
                  <Card key={p} padding="500">
                    <BlockStack gap="400">
                      <BlockStack gap="100">
                        <InlineStack align="space-between">
                          <Text as="h3" variant="headingSm">
                            {config.displayName}
                          </Text>
                          {isCurrent && <Badge tone="info">Current Plan</Badge>}
                        </InlineStack>

                        <Text as="p" variant="headingXl" fontWeight="bold">
                          ${config.price}
                          <Text as="span" variant="bodySm" tone="subdued">
                            {isOneTime ? " one-time purchase" : "/month"}
                          </Text>
                        </Text>
                      </BlockStack>

                      <Text as="p" variant="bodySm" tone="subdued">
                        {config.description}
                      </Text>

                      <Divider />

                      <Box paddingBlock="100">
                        <Text as="p" variant="bodySm" fontWeight="semibold">
                          Includes:
                        </Text>
                        <List type="bullet">
                          {(config.features || []).map((f: string, idx: number) => (
                            <List.Item key={idx}>{f}</List.Item>
                          ))}
                        </List>
                      </Box>

                      <Form method="post">
                        <input type="hidden" name="plan" value={p} />
                        <Button
                          submit
                          variant={isCurrent ? "secondary" : "primary"}
                          disabled={isCurrent}
                          fullWidth
                        >
                          {isCurrent
                            ? "Current Plan"
                            : config.price === 0
                            ? "Downgrade to Free"
                            : `Subscribe ($${config.price}/mo)`}
                        </Button>
                      </Form>
                    </BlockStack>
                  </Card>
                );
              })}
            </InlineGrid>
          </Layout.Section>

          {/* Comparison Matrix Table */}
          <Layout.Section>
            <Card padding="500">
              <BlockStack gap="400">
                <BlockStack gap="100">
                  <Text as="h2" variant="headingMd">
                    <FAIcon name="table-columns" style={{ color: "#4F46E5", marginRight: "8px" }} /> Plan Feature Matrix & Entitlements
                  </Text>
                  <Text as="p" variant="bodySm" tone="subdued">
                    Single source of truth comparison across all 3 tiers. Permissions are strictly enforced on the server.
                  </Text>
                </BlockStack>

                <div style={{ overflowX: "auto" }}>
                  <table style={{ width: "100%", borderCollapse: "collapse", textAlign: "left", fontSize: "14px" }}>
                    <thead>
                      <tr style={{ borderBottom: "2px solid #E5E7EB" }}>
                        <th style={{ padding: "12px 16px", fontWeight: "600" }}>Feature</th>
                        <th style={{ padding: "12px 16px", fontWeight: "600", textAlign: "center" }}>
                          {plansDict?.FREE?.displayName || "Free"} {plansDict?.FREE?.price ? `($${plansDict.FREE.price})` : ""}
                        </th>
                        <th style={{ padding: "12px 16px", fontWeight: "600", textAlign: "center" }}>
                          {plansDict?.STARTER?.displayName || "Starter"} {plansDict?.STARTER?.price ? `($${plansDict.STARTER.price}/mo)` : ""}
                        </th>
                        <th style={{ padding: "12px 16px", fontWeight: "600", textAlign: "center" }}>
                          {plansDict?.PRO?.displayName || "Pro"} {plansDict?.PRO?.price ? `($${plansDict.PRO.price}/mo)` : ""}
                        </th>
                      </tr>
                    </thead>
                    <tbody>
                      {FEATURE_MATRIX_ROWS.map((row, idx) => (
                        <tr
                          key={idx}
                          style={{
                            borderBottom: "1px solid #F3F4F6",
                            backgroundColor: idx % 2 === 0 ? "#FFFFFF" : "#F9FAFB",
                          }}
                        >
                          <td style={{ padding: "10px 16px", fontWeight: "500" }}>{row.feature}</td>
                          <td style={{ padding: "10px 16px", textAlign: "center" }}>
                            {typeof row.free === "string" ? (
                              <strong>{row.free === "$5 one-time" || row.free === "Free" ? (plansDict?.FREE?.price === 0 ? "Free" : `$${plansDict?.FREE?.price || 0} One-Time`) : row.free}</strong>
                            ) : row.free ? (
                              <span style={{ color: "#10B981", display: "inline-flex", alignItems: "center", gap: "4px" }}><FAIcon name="circle-check" /> YES</span>
                            ) : (
                              <span style={{ color: "#EF4444", display: "inline-flex", alignItems: "center", gap: "4px" }}><FAIcon name="circle-xmark" /> NO</span>
                            )}
                          </td>
                          <td style={{ padding: "10px 16px", textAlign: "center" }}>
                            {typeof row.starter === "string" ? (
                              <span>{row.starter}</span>
                            ) : row.starter ? (
                              <span style={{ color: "#10B981", display: "inline-flex", alignItems: "center", gap: "4px" }}><FAIcon name="circle-check" /> YES</span>
                            ) : (
                              <span style={{ color: "#EF4444", display: "inline-flex", alignItems: "center", gap: "4px" }}><FAIcon name="circle-xmark" /> NO</span>
                            )}
                          </td>
                          <td style={{ padding: "10px 16px", textAlign: "center" }}>
                            {typeof row.pro === "string" ? (
                              <strong>{row.pro}</strong>
                            ) : row.pro ? (
                              <span style={{ color: "#10B981", display: "inline-flex", alignItems: "center", gap: "4px" }}><FAIcon name="circle-check" /> YES</span>
                            ) : (
                              <span style={{ color: "#EF4444", display: "inline-flex", alignItems: "center", gap: "4px" }}><FAIcon name="circle-xmark" /> NO</span>
                            )}
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              </BlockStack>
            </Card>
          </Layout.Section>
        </Layout>
      </BlockStack>
    </Page>
  );
}
