"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 { useCharacterCatalog } from "@/providers/character-catalog-provider";
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,
  SubscriptionVipOfferSection,
} from "./components";
import styles from "./components/subscription-screen.module.css";
import {
  findSelectedSubscriptionPlan,
  getFirstRechargeOfferView,
  getDefaultSubscriptionPlanId,
  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 | null;
  initialPlanId?: string | null;
  initialAutoRenew?: boolean | null;
  commercialOfferId?: string | null;
  resumeOrderId?: string | null;
  chatActionId?: string | null;
}

export function SubscriptionScreen({
  subscriptionType = "vip",
  shouldResumePendingOrder = false,
  returnTo = null,
  initialPayChannel = null,
  analyticsContext: providedAnalyticsContext,
  sourceCharacterSlug = null,
  initialPlanId = null,
  initialAutoRenew = null,
  commercialOfferId = null,
  resumeOrderId = null,
  chatActionId = null,
}: SubscriptionScreenProps) {
  const [showPaymentIssueDialog, setShowPaymentIssueDialog] = useState(false);
  const [paymentIssueNotice, setPaymentIssueNotice] = useState<string | null>(
    null,
  );
  const characterCatalog = useCharacterCatalog();
  const userState = useUserState();
  const sourceCharacter = characterCatalog.getBySlug(sourceCharacterSlug);
  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: sourceCharacter?.slug ?? null,
    initialPayChannel: paymentMethodConfig.initialPayChannel,
    initialPlanId,
    initialAutoRenew,
    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 hasFirstRechargeOffer = useMemo(
    () =>
      getFirstRechargeOfferView({
        isFirstRecharge: payment.isFirstRecharge,
        subscriptionType,
        vipPlans: vipOfferPlans,
        coinPlans: directCoinsPlans,
      }) !== null,
    [
      directCoinsPlans,
      payment.isFirstRecharge,
      subscriptionType,
      vipOfferPlans,
    ],
  );

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

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

  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}>
        <div className={styles.scrollArea}>
          <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}

        {chatActionId && sourceCharacter ? (
          <section
            className={styles.characterSupportBanner}
            aria-label={`Support ${sourceCharacter.displayName}`}
            data-payment-guidance-character={sourceCharacter.id}
          >
            <h2>Keep talking with {sourceCharacter.shortName}</h2>
            <p>
              Without the required VIP access or credits, paid chat and locked
              content cannot continue. Choosing an option here is a voluntary
              way to support{" "}
              {sourceCharacter.shortName}; it is never a test of your feelings.
            </p>
          </section>
        ) : null}

        {payment.commercialOffer && !hasFirstRechargeOffer && sourceCharacter ? (
          <section
            className={styles.firstRechargeBanner}
            aria-label={`${sourceCharacter.shortName} private offer`}
          >
            <span className={styles.firstRechargeBadge}>Private offer</span>
            <div className={styles.firstRechargeCopy}>
              <h2 className={styles.firstRechargeTitle}>
                {sourceCharacter.shortName} 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>

        <div className={styles.ctaSlot}>
          <SubscriptionCheckoutButton
            disabled={!canActivate}
            subscriptionType={subscriptionType}
            returnTo={returnTo}
            sourceCharacterSlug={sourceCharacter?.slug ?? DEFAULT_CHARACTER_SLUG}
            renewalPlan={selectedVipPlan}
            renewalConsentSubjectId={userState.currentUser?.id || null}
          />
        </div>

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

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