"use client";

/**
 * useUpgradeAwareFetch
 * ─────────────────────
 * Thin wrapper over fetch() that recognises the server's
 * upgrade_required 403 envelope and auto-opens the upgrade modal.
 *
 * Shape detected:
 *   HTTP 403 + JSON body { error: "upgrade_required", feature?, reason? }
 *
 * Usage:
 *
 *   const fetchGated = useUpgradeAwareFetch();
 *   const r = await fetchGated(`/api/rank-tracker?brandId=${id}`);
 *   if (r.upgradeRequired) return; // modal already opened — bail
 *   const data = await r.response.json();
 *
 * This keeps every feature-protected page consistent: the server
 * route is the true gate, and a 403 never requires bespoke handling
 * to surface the upgrade CTA.
 */

import { useCallback } from "react";
import { usePlanContext } from "@/context/plan-context";
import type { FeatureKey } from "@/lib/plan-config";

interface UpgradeFetchResult {
  /** Underlying Response (always a real Response, even when
   *  upgradeRequired is true — consumers can still read body.error). */
  response: Response;
  /** True when the response matched the upgrade_required envelope.
   *  When true, the upgrade modal has already been opened — the
   *  caller can exit early without showing its own error UI. */
  upgradeRequired: boolean;
}

export function useUpgradeAwareFetch() {
  const { openUpgrade } = usePlanContext();

  return useCallback(
    async (input: RequestInfo | URL, init?: RequestInit): Promise<UpgradeFetchResult> => {
      const response = await fetch(input, init);
      if (response.status !== 403) {
        return { response, upgradeRequired: false };
      }
      // Clone so the caller can still .json() / .text() the body
      // after we peek at it here.
      let body: { error?: string; feature?: string; reason?: string } | null = null;
      try {
        body = await response.clone().json();
      } catch { /* not JSON — not our shape */ }

      if (body?.error !== "upgrade_required") {
        return { response, upgradeRequired: false };
      }

      // Branch on which trigger to open. "brand_limit" from
      // requireBrandSlotAvailable becomes the credit_limit /
      // brands modal; anything else with a feature becomes a
      // feature-trigger modal.
      if (body.reason === "brand_limit") {
        openUpgrade({ kind: "credit_limit", creditKind: "brands" });
      } else if (body.feature) {
        openUpgrade({ kind: "feature", feature: body.feature as FeatureKey });
      } else {
        openUpgrade({ kind: "manual" });
      }
      return { response, upgradeRequired: true };
    },
    [openUpgrade],
  );
}
