"use client";
import { useEffect, useMemo, useState } from "react";

import { BackButton } from "@/app/_components";
import { MobileShell } from "@/app/_components/core";
import { PaymentMethodSelector } from "@/app/_components/payment/payment-method-selector";
import { usePaymentMethodSelection } from "@/app/_hooks/use-payment-method-selection";
import { usePaymentPlanAnalytics } from "@/app/_hooks/use-payment-plan-analytics";
import type { PayChannel } from "@/data/schemas/payment";
import type { SubscriptionReturnTo } from "@/lib/navigation/subscription_exit";
import { DEFAULT_CHARACTER_SLUG } from "@/data/constants/character";
import {
  behaviorAnalytics,
  getDefaultPaymentAnalyticsContext,
  type PaymentAnalyticsContext,
} from "@/lib/analytics";
import { getPaymentMethodConfig } from "@/lib/payment/payment_method";
import { useHasHydrated } from "@/hooks/use-has-hydrated";
import { useUserState } from "@/stores/user/user-context";

import {
  SubscriptionCheckoutButton,
  SubscriptionCoinsOfferSection,
  SubscriptionPaymentIssueDialog,
  SubscriptionPaymentSuccessDialog,
  SubscriptionRenewalConfirmationDialog,
  SubscriptionVipOfferSection,
} from "./components";
import styles from "./components/subscription-screen.module.css";
import {
  canCheckoutSubscriptionPlan,
  findSelectedSubscriptionPlan,
  getFirstRechargeOfferView,
  getDefaultSubscriptionPlanId,
  requiresVipPlanConfirmation,
  toCoinsOfferPlanViews,
  toVipOfferPlanViews,
  type SubscriptionType,
} from "./subscription-screen.helpers";
import { useSubscriptionPaymentFlow } from "./use-subscription-payment-flow";

export type { SubscriptionType } from "./subscription-screen.helpers";

export interface SubscriptionScreenProps {
  subscriptionType?: SubscriptionType;
  shouldResumePendingOrder?: boolean;
  returnTo?: SubscriptionReturnTo;
  initialPayChannel?: PayChannel | null;
  analyticsContext?: PaymentAnalyticsContext;
  sourceCharacterSlug?: string;
  initialPlanId?: string | null;
  commercialOfferId?: string | null;
  resumeOrderId?: string | null;
  chatActionId?: string | null;
}

export function SubscriptionScreen({
  subscriptionType = "vip",
  shouldResumePendingOrder = false,
  returnTo = null,
  initialPayChannel = null,
  analyticsContext: providedAnalyticsContext,
  sourceCharacterSlug = DEFAULT_CHARACTER_SLUG,
  initialPlanId = null,
  commercialOfferId = null,
  resumeOrderId = null,
  chatActionId = null,
}: SubscriptionScreenProps) {
  const [confirmedVipPlanIds, setConfirmedVipPlanIds] = useState<
    ReadonlySet<string>
  >(() => new Set());
  const [pendingVipPlanId, setPendingVipPlanId] = useState<string | null>(null);
  const [showPaymentIssueDialog, setShowPaymentIssueDialog] = useState(false);
  const [paymentIssueNotice, setPaymentIssueNotice] = useState<string | null>(
    null,
  );
  const userState = useUserState();
  const hasHydrated = useHasHydrated();
  const countryCode = userState.currentUser?.countryCode;
  const paymentMethodConfig = getPaymentMethodConfig({
    countryCode,
    requestedPayChannel: initialPayChannel,
  });
  const renderedPaymentMethodConfig = hasHydrated
    ? paymentMethodConfig
    : { ...paymentMethodConfig, showPaymentMethodSelector: false };
  const {
    payment,
    paymentDispatch,
    showPaymentSuccessDialog,
    handleBackClick,
    handlePaymentSuccessClose,
  } = useSubscriptionPaymentFlow({
    subscriptionType,
    shouldResumePendingOrder,
    returnTo,
    sourceCharacterSlug,
    initialPayChannel: paymentMethodConfig.initialPayChannel,
    initialPlanId,
    commercialOfferId,
    resumeOrderId,
    chatActionId,
  });
  const canSubscribeVip = subscriptionType === "vip";
  const analyticsContext =
    providedAnalyticsContext ??
    getDefaultPaymentAnalyticsContext(subscriptionType);

  const vipOfferPlans = useMemo(
    () => toVipOfferPlanViews(payment.plans),
    [payment.plans],
  );
  const directCoinsPlans = useMemo(
    () => toCoinsOfferPlanViews(payment.plans),
    [payment.plans],
  );
  const displayedPlans = useMemo(() => {
    const displayedPlanIds = [
      ...(canSubscribeVip ? vipOfferPlans : []),
      ...directCoinsPlans,
    ].map((plan) => plan.id);
    return displayedPlanIds.flatMap((planId) => {
      const plan = payment.plans.find((item) => item.planId === planId);
      return plan ? [plan] : [];
    });
  }, [canSubscribeVip, directCoinsPlans, payment.plans, vipOfferPlans]);
  usePaymentPlanAnalytics(displayedPlans, analyticsContext);
  const firstRechargeOffer = useMemo(
    () =>
      getFirstRechargeOfferView({
        isFirstRecharge: payment.isFirstRecharge,
        subscriptionType,
        vipPlans: vipOfferPlans,
        coinPlans: directCoinsPlans,
      }),
    [
      directCoinsPlans,
      payment.isFirstRecharge,
      subscriptionType,
      vipOfferPlans,
    ],
  );

  const selectedPlan = findSelectedSubscriptionPlan({
    canSubscribeVip,
    selectedPlanId: payment.selectedPlanId,
    vipPlans: vipOfferPlans,
    coinPlans: directCoinsPlans,
  });
  const isPaymentBusy =
    payment.isCreatingOrder ||
    payment.isPollingOrder;
  const selectedPlanIsVip = vipOfferPlans.some(
    (plan) => plan.id === payment.selectedPlanId,
  );
  const canActivate =
    selectedPlan !== null &&
    canCheckoutSubscriptionPlan({
      selectedPlanId: payment.selectedPlanId,
      vipPlans: vipOfferPlans,
      confirmedVipPlanIds,
    }) &&
    !isPaymentBusy;
  const pendingVipPlan =
    vipOfferPlans.find((plan) => plan.id === pendingVipPlanId) ?? null;

  const handleSelectPlan = (planId: string) => {
    const plan = payment.plans.find((item) => item.planId === planId);
    if (plan) behaviorAnalytics.planClick(plan, analyticsContext);
    if (
      requiresVipPlanConfirmation({
        planId,
        vipPlans: vipOfferPlans,
        confirmedVipPlanIds,
      })
    ) {
      setPendingVipPlanId(planId);
      return;
    }
    paymentDispatch({ type: "PaymentPlanSelected", planId });
  };

  const handleConfirmVipPlan = () => {
    if (!pendingVipPlanId) return;
    const planId = pendingVipPlanId;
    setConfirmedVipPlanIds((current) => {
      const next = new Set(current);
      next.add(planId);
      return next;
    });
    paymentDispatch({ type: "PaymentPlanSelected", planId });
    setPendingVipPlanId(null);
  };

  const handlePaymentMethodChange = (payChannel: PayChannel) => {
    paymentDispatch({
      type: "PaymentPayChannelChanged",
      payChannel,
    });
  };

  usePaymentMethodSelection({
    config: paymentMethodConfig,
    currentPayChannel: payment.payChannel,
    isPaymentBusy,
    requestedPayChannel: initialPayChannel,
    onChange: handlePaymentMethodChange,
  });

  useEffect(() => {
    const defaultPlanId = getDefaultSubscriptionPlanId({
      canSubscribeVip,
      selectedPlanId: payment.selectedPlanId,
      status: payment.status,
      isLoadingPlans: payment.isLoadingPlans,
      selectedPlan,
      vipPlans: vipOfferPlans,
      coinPlans: directCoinsPlans,
    });
    if (!defaultPlanId) return;

    paymentDispatch({
      type: "PaymentPlanSelected",
      planId: defaultPlanId,
    });
  }, [
    canSubscribeVip,
    directCoinsPlans,
    payment.isLoadingPlans,
    paymentDispatch,
    payment.selectedPlanId,
    payment.status,
    selectedPlan,
    vipOfferPlans,
  ]);

  return (
    <MobileShell>
      <div className={styles.shell}>
        <header className={styles.header}>
          <BackButton
            className={styles.backSlot}
            onClick={handleBackClick}
            variant="soft"
            analyticsKey="subscription.back"
          />
          <button
            type="button"
            className={styles.paymentIssueButton}
            onClick={() => {
              setPaymentIssueNotice(null);
              setShowPaymentIssueDialog(true);
            }}
          >
            Payment issue?
          </button>
        </header>

        {paymentIssueNotice ? (
          <p className={styles.paymentIssueNotice} role="status">
            {paymentIssueNotice}
          </p>
        ) : null}

        {firstRechargeOffer ? (
          <section
            className={styles.firstRechargeBanner}
            aria-label="First recharge offer"
          >
            <span className={styles.firstRechargeBadge}>
              {firstRechargeOffer.badgeText}
            </span>
            <div className={styles.firstRechargeCopy}>
              <h2 className={styles.firstRechargeTitle}>
                {firstRechargeOffer.title}
              </h2>
              <p className={styles.firstRechargeSubtitle}>
                {firstRechargeOffer.subtitle}
              </p>
              {firstRechargeOffer.renewalNotice ? (
                <p className={styles.firstRechargeRenewalNotice}>
                  {firstRechargeOffer.renewalNotice}
                </p>
              ) : null}
            </div>
          </section>
        ) : null}

        {payment.commercialOffer && !firstRechargeOffer ? (
          <section
            className={styles.firstRechargeBanner}
            aria-label="Elio private offer"
          >
            <span className={styles.firstRechargeBadge}>Private offer</span>
            <div className={styles.firstRechargeCopy}>
              <h2 className={styles.firstRechargeTitle}>Elio got this price for you</h2>
              <p className={styles.firstRechargeSubtitle}>
                {payment.commercialOffer.message ||
                  `Your ${payment.commercialOffer.discountPercent}% discount is already applied below.`}
              </p>
            </div>
          </section>
        ) : null}

        <div className={styles.offerStack}>
          {canSubscribeVip ? (
            <SubscriptionVipOfferSection
              plans={vipOfferPlans}
              selectedPlanId={payment.selectedPlanId || selectedPlan?.id || null}
              onSelectPlan={handleSelectPlan}
            />
          ) : null}
          <SubscriptionCoinsOfferSection
            plans={directCoinsPlans}
            selectedPlanId={payment.selectedPlanId || selectedPlan?.id || null}
            onSelectPlan={handleSelectPlan}
          />
        </div>

        <PaymentMethodSelector
          config={renderedPaymentMethodConfig}
          value={payment.payChannel}
          disabled={isPaymentBusy}
          caption={
            paymentMethodConfig.ezpayDisplayName === "QRIS"
              ? "QRIS by default in Indonesia"
              : "GCash by default in the Philippines"
          }
          className={styles.paymentMethodSlot}
          analyticsKey="subscription.payment_method"
          onChange={handlePaymentMethodChange}
        />

        <div className={styles.ctaSlot}>
          <SubscriptionCheckoutButton
            disabled={!canActivate}
            subscriptionType={subscriptionType}
            returnTo={returnTo}
            sourceCharacterSlug={sourceCharacterSlug}
          />
        </div>

        <SubscriptionRenewalConfirmationDialog
          open={pendingVipPlan !== null}
          plan={pendingVipPlan}
          onCancel={() => setPendingVipPlanId(null)}
          onConfirm={handleConfirmVipPlan}
        />

        {showPaymentIssueDialog ? (
          <SubscriptionPaymentIssueDialog
            open
            subscriptionType={
              selectedPlan
                ? selectedPlanIsVip
                  ? "vip"
                  : "topup"
                : subscriptionType
            }
            planId={selectedPlan?.id ?? null}
            orderId={payment.currentOrderId}
            payChannel={payment.payChannel}
            countryCode={countryCode}
            characterId={sourceCharacterSlug}
            onClose={() => setShowPaymentIssueDialog(false)}
            onSubmitted={setPaymentIssueNotice}
          />
        ) : null}

        <SubscriptionPaymentSuccessDialog
          open={showPaymentSuccessDialog}
          subscriptionType={subscriptionType}
          onClose={handlePaymentSuccessClose}
        />
      </div>
    </MobileShell>
  );
}
