"use client";

import { SquarePen, Star } from "lucide-react";
import Image from "next/image";
import moment from "moment";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";

import { BillingRegion, IUserSubscription } from "@/api/types/auth";
import { IPlanListItem, IPlanPrice } from "@/api/types/plan";
import { useGetPlanListQuery } from "@/api/plan.api";
import {
  useBuySubscriptionMutation,
  useVerifyPaymentMutation,
  useCancelSubscriptionMutation,
} from "@/api/payment.api";
import {
  useLazyGetProfileQuery,
  useUpdateBillingRegionMutation,
} from "@/api/auth.api";
import { parseApiError } from "@/api/utils/error-handler";
import { IAPIErrorResponse } from "@/api/types/common";
import { BILLING_REGION_CURRENCY, SUBSCRIPTION_STATUS } from "@/api/constant";
import BillingRegionModal from "@/components/Membership/BillingRegionModal";
import { loadRazorpay } from "@/lib/loadRazorpay";
import { useAppDispatch, useAppSelector } from "@/redux/hooks";
import { updateUser } from "@/redux/slices/authSlice";
import ConfirmModal from "@/components/common/ConfirmModal";
import ErrorCard from "@/components/common/ErrorCard";

interface SubscriptionSectionProps {
  userSubscription?: IUserSubscription | null;
  // The user's saved billing region. `null` means it hasn't been chosen yet —
  // we prompt for it (BillingRegionModal) before the plans make sense, since
  // the region decides which currency the plans are priced in.
  billingRegion?: BillingRegion | null;
  prefill?: {
    name?: string;
    email?: string;
    contact?: string;
  };
}

const parseFeatures = (plan: IPlanListItem): string[] => {
  const source = plan.descriptionText || "";
  return source
    .split(/\r?\n/)
    .map((line) => line.replace(/^\s*\*\s*/, "").trim())
    .filter((line) => line.length > 0);
};

// Build a human-readable duration from the price's `duration` + `frequency`.
// When the duration is 1 the number is dropped so it reads "month" / "year"
// (used as "every month"); otherwise it's pluralised, e.g. "6 months". The
// frequency may arrive singular or plural, so normalise the unit first.
const formatDuration = (
  price?: { duration?: number | null; frequency?: string | null } | null,
): string => {
  if (!price?.duration || !price.frequency) return "";
  const unit = String(price.frequency).trim().replace(/s$/i, "");
  return price.duration === 1 ? unit : `${price.duration} ${unit}s`;
};

// Same as formatDuration but always keeps the count, e.g. "1 month" /
// "6 months" — used by the plan cards ("for 1 month"), not the banner.
const formatDurationWithCount = (
  price?: Pick<IPlanPrice, "duration" | "frequency"> | null,
): string => {
  if (!price?.duration || !price.frequency) return "";
  const unit = String(price.frequency).trim().replace(/s$/i, "");
  return `${price.duration} ${price.duration === 1 ? unit : `${unit}s`}`;
};

const BILLING_REGION_LABELS: Record<BillingRegion, string> = {
  INDIA: "India",
  OUTSIDE_INDIA: "Outside India",
};

// Only two currencies are supported — show the symbol rather than the code.
const currencySymbol = (currency?: string | null): string => {
  switch ((currency ?? "").toUpperCase()) {
    case "INR":
      return "₹";
    case "USD":
      return "$";
    default:
      return currency ?? "";
  }
};

// When `strict` is set the preferred currency is mandatory (it's dictated by the
// user's billing region): if the plan has no price in that currency we return
// nothing rather than falling back to a different-currency price. When it's not
// strict we fall back to the plan's default/first price.
const pickPrice = (
  prices: IPlanPrice[] | undefined,
  preferredCurrency?: string,
  strict = false,
): IPlanPrice | undefined => {
  if (!prices || prices.length === 0) return undefined;
  if (preferredCurrency) {
    const match = prices.find(
      (p) => p.currency === preferredCurrency && p.isDefault,
    );
    if (match) return match;
    const byCurrency = prices.find((p) => p.currency === preferredCurrency);
    if (byCurrency) return byCurrency;
    if (strict) return undefined;
  }
  return prices.find((p) => p.isDefault) ?? prices[0];
};

const SubscriptionSection = ({
  userSubscription,
  billingRegion,
  prefill,
}: SubscriptionSectionProps) => {
  const { user } = useAppSelector((state) => state.auth);
  const dispatch = useAppDispatch();

  // console.log(user, userSubscription, "user");

  const planData = userSubscription?.planData;

  // Show the plans based on the profile's billing region whenever it's known:
  // prefer the freshly-loaded profile (prop), then the value cached in the auth
  // store. Currency follows the region (INDIA → INR, OUTSIDE_INDIA → USD),
  // falling back to the active subscription's currency, then USD, only while the
  // region is still unknown (in which case the modal prompts for it).
  const effectiveBillingRegion: BillingRegion | null =
    billingRegion ?? user?.billingRegion ?? null;
  const regionCurrency = effectiveBillingRegion
    ? BILLING_REGION_CURRENCY[effectiveBillingRegion]
    : undefined;
  const preferredCurrency =
    regionCurrency ??
    planData?.currency ??
    BILLING_REGION_CURRENCY.OUTSIDE_INDIA;
  const billingRegionLabel = effectiveBillingRegion
    ? BILLING_REGION_LABELS[effectiveBillingRegion]
    : "Set billing region";
  const currentPeriodStart = userSubscription?.currentPeriodStart;
  const currentPeriodEnd = userSubscription?.currentPeriodEnd;
  const status = userSubscription?.status;

  const DATE_FORMAT = "DD MMM YYYY, h:mm A";
  const startDate = currentPeriodStart
    ? moment(currentPeriodStart).format(DATE_FORMAT)
    : "";
  const endDate = currentPeriodEnd
    ? moment(currentPeriodEnd).format(DATE_FORMAT)
    : "";

  const isActiveSubscription =
    status === SUBSCRIPTION_STATUS.ACTIVE &&
    !!currentPeriodEnd &&
    moment(currentPeriodEnd).isAfter(moment());

  const statusLabel =
    status === SUBSCRIPTION_STATUS.CANCELLED
      ? "CANCELLED"
      : status === SUBSCRIPTION_STATUS.FAILED
        ? "FAILED"
        : status === SUBSCRIPTION_STATUS.DUE
          ? "DUE"
          : status === SUBSCRIPTION_STATUS.PENDING
            ? "PENDING"
            : isActiveSubscription
              ? "ACTIVE"
              : status === SUBSCRIPTION_STATUS.EXPIRED
                ? "EXPIRED"
                : "UNKNOWN";
  const statusBgClass = isActiveSubscription
    ? "bg-green-vibrant"
    : "bg-red-500";

  const currentPriceIdNum = planData?.priceId ? Number(planData.priceId) : NaN;

  const { data, isLoading, error, refetch } = useGetPlanListQuery({
    sortDirection: "asc",
  });
  const packages = data?.data ?? [];

  // Billing cycle for the active-plan banner ("every month" / "every 6 months").
  // planData carries the subscription's own duration/frequency snapshot.
  const activeDuration = formatDuration(planData);

  const [cancelModalOpen, setCancelModalOpen] = useState(false);
  const [buyingPriceId, setBuyingPriceId] = useState<number | null>(null);
  const [buySubscription] = useBuySubscriptionMutation();
  const [verifyPayment] = useVerifyPaymentMutation();
  const [getProfile] = useLazyGetProfileQuery();
  const [cancelSubscription, { isLoading: cancelling }] =
    useCancelSubscriptionMutation();
  const [updateBillingRegion, { isLoading: savingRegion }] =
    useUpdateBillingRegionMutation();

  // Prompt for the billing region only when it's unknown from every source.
  // Once saved, the profile refetch / store update flips it non-null and the
  // modal closes on its own.
  const [regionModalOpen, setRegionModalOpen] = useState(
    effectiveBillingRegion == null,
  );
  useEffect(() => {
    setRegionModalOpen(effectiveBillingRegion == null);
  }, [effectiveBillingRegion]);

  // Save the chosen region, then refresh the profile and mirror the
  // authoritative value (userSetting.billingRegion) into the auth store.
  const handleRegionContinue = async (region: BillingRegion) => {
    try {
      await updateBillingRegion({ billingRegion: region }).unwrap();
      let saved: BillingRegion | null = region;
      if (user?.id) {
        try {
          const profile = await getProfile(user.id).unwrap();
          saved = profile.userSetting?.billingRegion ?? region;
        } catch {
          // Refetch failed — fall back to the value we just sent.
        }
      }
      dispatch(updateUser({ billingRegion: saved }));
      setRegionModalOpen(false);
    } catch (err) {
      toast.error(parseApiError(err));
    }
  };

  // Cancel the active subscription. The mutation invalidates the `User` tag, so
  // the profile (and this banner) refresh automatically on success.
  const handleCancel = async () => {
    if (!userSubscription?.id) return;
    try {
      await cancelSubscription(userSubscription.id).unwrap();
      toast.success("Your subscription has been cancelled.");
      setCancelModalOpen(false);
    } catch (err) {
      toast.error(parseApiError(err));
    }
  };

  const handleBuy = async (planId: number, priceId: number) => {
    const selectedPlan = packages.find((p) => p.id === planId);
    const selectedPrice = selectedPlan?.prices?.find((pr) => pr.id === priceId);

    // Block buying any other plan while a subscription is still active — the
    // user must let the current plan run out (or cancel it) before switching.
    if (
      isActiveSubscription &&
      !Number.isNaN(currentPriceIdNum) &&
      priceId !== currentPriceIdNum
    ) {
      toast.error(
        `You already have ${planData?.name} active until ${endDate}. You can't buy another plan while your subscription is active.`,
      );
      return;
    }

    setBuyingPriceId(priceId);
    try {
      const sdkLoaded = await loadRazorpay();
      if (!sdkLoaded) {
        throw new Error("Could not load payment SDK. Check your connection.");
      }

      const { paymentIntent } = await buySubscription({
        planId,
        priceId,
      }).unwrap();

      const keyId = process.env.NEXT_PUBLIC_RAZORPAY_KEY_ID;
      if (!keyId) {
        throw new Error("Payment is not configured.");
      }

      const siteUrl =
        process.env.NEXT_PUBLIC_SITE_URL ?? window.location.origin;

      const description = selectedPlan
        ? `${selectedPlan.name}${
            selectedPrice
              ? ` — ${selectedPrice.currency} ${selectedPrice.amount}`
              : ""
          }`
        : "Premium subscription";

      // The buy API returns a subscription id (`sub_...`) for recurring plans
      // and an order id (`order_...`) for one-off payments. Razorpay checkout
      // takes these under different keys, so pick the right one.
      const isSubscription = paymentIntent.startsWith("sub_");

      const rzp = new window.Razorpay({
        key: keyId,
        ...(isSubscription
          ? { subscription_id: paymentIntent }
          : { order_id: paymentIntent }),
        name: "MySeaTime",
        description,
        image: siteUrl.startsWith("https://")
          ? `${siteUrl}/assets/images/razorpay-logo.svg`
          : undefined,
        prefill: {
          name: prefill?.name,
          email: prefill?.email,
          contact: prefill?.contact,
        },
        notes: {
          planId: String(planId),
          priceId: String(priceId),
          ...(user?.id ? { userId: String(user.id) } : {}),
        },
        theme: { color: "#0EA5E9" },
        handler: async (resp) => {
          // console.log("Payment response:", resp);
          try {
            const result = await verifyPayment({
              razorpayPaymentId: resp.razorpay_payment_id,
              ...(resp.razorpay_subscription_id
                ? { razorpaySubscriptionId: resp.razorpay_subscription_id }
                : { razorpayOrderId: resp.razorpay_order_id }),
              razorpaySignature: resp.razorpay_signature,
            }).unwrap();
            if (result.isValid) {
              toast.success("Subscription activated");
              if (user?.id) {
                try {
                  const profile = await getProfile(user.id).unwrap();
                  dispatch(
                    updateUser({
                      email: profile.email,
                      name: profile.userProfile.name,
                      profileImage:
                        profile.userProfile.profileImage?.filePath || null,
                      rankName: profile.userProfile.rank?.name || "",
                      isPremium: profile.userSetting.isPremium,
                    }),
                  );
                } catch {
                  toast.error(
                    "Profile refresh failed. Please reload the page.",
                  );
                }
              }
              // If the user arrived here from another page (e.g. a /discussion
              // they were trying to read), return them there with a full load so
              // it refetches with the now-premium access.
              const redirect = new URLSearchParams(window.location.search).get(
                "redirect",
              );
              if (
                redirect &&
                redirect.startsWith("/") &&
                !redirect.startsWith("//")
              ) {
                window.location.href = redirect;
              }
            } else {
              toast.error(
                "Payment verification failed. Please contact support.",
              );
            }
          } catch (verifyErr) {
            toast.error(parseApiError(verifyErr));
          } finally {
            setBuyingPriceId(null);
          }
        },
        modal: {
          ondismiss: () => setBuyingPriceId(null),
          confirm_close: true,
        },
      });
      rzp.open();
    } catch (err) {
      const apiErr = err as IAPIErrorResponse;
      toast.error(
        apiErr?.data?.message || apiErr?.data?.error || parseApiError(err),
      );
      setBuyingPriceId(null);
    }
  };

  return (
    <div className="flex flex-col gap-[17px] w-full">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <h2 className="text-black font-semibold text-[24px] leading-[1.2] tracking-[-0.24px]">
          Plans
        </h2>

        {/* Billing Region */}
        <button
          type="button"
          onClick={() => setRegionModalOpen(true)}
          className="flex items-center gap-2 px-3 h-[34px] rounded-lg border border-coolgray-200 bg-white text-sm font-medium text-coolgray-700 hover:bg-coolgray-50 transition-colors"
        >
          <SquarePen className="h-3.5 w-3.5 text-coolgray-500 shrink-0" />
          <span>{billingRegionLabel}</span>
        </button>
      </div>

      {/* Outside-India availability notice */}
      {/* <div className="w-full bg-blue-pale border border-blue-soft rounded-[10px] p-3 sm:p-4 flex items-start gap-3">
        <div className="flex p-[6px] justify-center items-center rounded-[6px] bg-blue-soft shrink-0">
          <Globe size={18} className="text-blue-banner " />
        </div>
        <p className="text-[13px] sm:text-[15px] font-medium leading-[140%] tracking-[-0.15px] text-blue-banner">
          We&apos;re working on opening subscriptions for users outside India.
          Thanks for your patience while we expand availability.
        </p>
      </div> */}

      {/* Active Plan Banner */}
      {userSubscription && planData && (
        <div className="w-full bg-grad-sky rounded-[10px] p-3 sm:p-4 flex flex-col md:flex-row md:items-center justify-between gap-3 md:gap-4 text-white">
          <div className="flex flex-wrap items-center gap-2 sm:gap-3">
            <div className="flex p-1 justify-center items-center gap-[5px] rounded-[3px] bg-blue-banner shrink-0">
              <Star size={16} fill="white" className="text-white" />
              <span className="font-semibold text-[15px] sm:text-[18px] leading-[120%] tracking-[-0.18px] text-white">
                {planData.name}
              </span>
            </div>
            {/* Price + billing cycle combined into one span, e.g. "$100 every
                month" / "$100 every 6 months". */}
            <span className="text-[14px] sm:text-[18px] font-semibold leading-[120%] tracking-[-0.18px] text-white break-words">
              {planData.amount > 0
                ? `${currencySymbol(planData.currency)}${planData.amount}${
                    activeDuration
                      ? ` ${userSubscription?.autoRenew ? "every" : `for ${planData?.duration===1?planData?.duration:""}`} ${activeDuration}`
                      : ""
                  }`
                : planData.descriptionText || planData.name}
            </span>
          </div>

          <div className="flex flex-wrap items-center gap-2 sm:gap-4 justify-between md:justify-end">
            <span className="text-[12px] sm:text-[14px] font-medium leading-[18px] text-white">
              {startDate} - {endDate}
            </span>
            <div
              className={`flex px-2 py-[3px] justify-center items-center gap-[10px] rounded-[25px] border border-white ${statusBgClass} text-[11px] sm:text-[12px] font-bold uppercase tracking-wider shrink-0`}
            >
              {statusLabel}
            </div>
            {isActiveSubscription && userSubscription?.autoRenew && (
              <button
                type="button"
                onClick={() => setCancelModalOpen(true)}
                disabled={cancelling}
                className="flex px-3 py-[3px] justify-center items-center rounded-[25px] border border-white bg-white/10 hover:bg-white/20 text-white text-[11px] sm:text-[12px] font-bold uppercase tracking-wider shrink-0 transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
              >
                {cancelling ? "Cancelling…" : "Cancel"}
              </button>
            )}
          </div>
        </div>
      )}

      {/* Package Grid */}
      {isLoading ? (
        <div className="flex items-center justify-center min-h-[378px] w-full bg-white border border-gray-125 rounded-[14px]">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-light"></div>
        </div>
      ) : error ? (
        <ErrorCard
          message="Failed to load plans. Please try again."
          onRetry={() => refetch()}
        />
      ) : packages.length === 0 ? (
        <div className="text-gray-500 p-4 bg-white border border-gray-125 rounded-[14px]">
          No plans available.
        </div>
      ) : (
        <div className="grid grid-cols-1 lg:grid-cols-3 bg-white border border-gray-125 rounded-[14px] overflow-hidden w-full min-h-[378px]">
          {packages.map((pkg, idx) => {
            const features = parseFeatures(pkg);
            // When the billing region is known, the region currency is
            // mandatory — don't fall back to another currency's price.
            const price = pickPrice(
              pkg.prices,
              preferredCurrency,
              regionCurrency !== undefined,
            );
            const isCurrent =
              isActiveSubscription &&
              price !== undefined &&
              !Number.isNaN(currentPriceIdNum) &&
              price.id === currentPriceIdNum;
            const isBuying = price !== undefined && buyingPriceId === price.id;
            const disabled =
              isCurrent ||
              isBuying ||
              price === undefined ||
              buyingPriceId !== null ||
              // No switching while a subscription is active.
              isActiveSubscription;
            const visuallyDimmed =
              isCurrent ||
              isBuying ||
              price === undefined ||
              isActiveSubscription;

            return (
              <div
                key={pkg.id}
                className={`flex flex-col pt-5 ${
                  idx < packages.length - 1
                    ? "border-b border-gray-125 lg:border-b-0 lg:border-r"
                    : ""
                }`}
              >
                <h3 className="text-center text-black font-semibold text-[20px] leading-[120%] tracking-[-0.2px] w-full mb-5">
                  {pkg.name}
                </h3>

                <div className="bg-gray-125 h-px w-full"></div>
                <div className="p-5.75">
                  <div className="flex items-baseline justify-center gap-1 mb-5">
                    {price ? (
                      <>
                        <span className="text-black font-semibold text-[20px] leading-[120%] tracking-[-0.2px]">
                          {currencySymbol(price.currency)}
                          {price.amount}
                        </span>
                        {price.currency?.toUpperCase() === "INR" && (
                          <span className="text-black text-[14px] font-medium leading-[15px] tracking-[-0.14px] opacity-50">
                            (Inc. GST)
                          </span>
                        )}
                        {formatDurationWithCount(price) && (
                          <span className="text-black text-[14px] font-medium leading-[15px] tracking-[-0.14px] opacity-50">
                            for {formatDurationWithCount(price)}
                          </span>
                        )}
                      </>
                    ) : (
                      <span className="text-black text-[14px] font-medium opacity-50">
                        Price unavailable
                      </span>
                    )}
                  </div>

                  <button
                    onClick={() => price && handleBuy(pkg.id, price.id)}
                    disabled={disabled}
                    className={`flex h-[38.128px] w-full px-[19.064px] justify-center items-center gap-[6.355px] self-stretch border border-blue-light bg-blue-light/6 rounded-[74px] text-black text-[14px] font-bold leading-[120%] text-center mb-5 transition-all ${
                      disabled ? "cursor-not-allowed" : "hover:bg-blue-light/10"
                    } ${visuallyDimmed ? "opacity-50" : ""}`}
                  >
                    {isCurrent
                      ? "Current plan"
                      : isBuying
                        ? "Processing…"
                        : "Buy"}
                  </button>

                  <div className="flex flex-col gap-4">
                    {features.map((feature, fIdx) => (
                      <div key={fIdx} className="flex items-start gap-3">
                        <Image
                          src="/assets/icons/tick-black.svg"
                          alt="tick"
                          width={20}
                          height={20}
                          className="text-gray-300 shrink-0 mt-0.5"
                        />
                        <span className="text-surface-80 text-[14px] font-medium leading-[18px]">
                          {feature}
                        </span>
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}

      <ConfirmModal
        isOpen={cancelModalOpen}
        onClose={() => setCancelModalOpen(false)}
        onConfirm={handleCancel}
        title="Cancel subscription?"
        description="You'll keep access until the current period ends. This can't be undone."
        confirmLabel="Cancel subscription"
        cancelLabel="Keep plan"
        destructive
        loading={cancelling}
        loadingLabel="Cancelling…"
      />

      <BillingRegionModal
        isOpen={regionModalOpen}
        onClose={() => setRegionModalOpen(false)}
        onContinue={handleRegionContinue}
        defaultValue={effectiveBillingRegion ?? undefined}
        loading={savingRegion}
      />
    </div>
  );
};

export default SubscriptionSection;
