"use client";

import { useEffect } from "react";

import { BackButton, CharacterAvatar } 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 { usePaymentRouteFlow } from "@/app/_hooks/use-payment-route-flow";
import type { PayChannel } from "@/data/schemas/payment";
import {
  behaviorAnalytics,
  type PaymentAnalyticsContext,
} from "@/lib/analytics";
import { getPaymentMethodConfig } from "@/lib/payment/payment_method";
import { useHasHydrated } from "@/hooks/use-has-hydrated";
import { buildTipGiftPath } from "@/lib/tip/tip_gift";
import {
  useActiveCharacter,
  useActiveCharacterRoutes,
} from "@/providers/character-provider";
import { useUserState } from "@/stores/user/user-context";

import { TipCheckoutButton } from "./tip-checkout-button";
import { TipGiftProductSelector } from "./tip-gift-product-selector";
import { TipProductImage } from "./tip-product-image";
import { getGiftImageSources } from "./tip-screen.helpers";
import { TipSuccessView } from "./tip-success-view";
import { useTipSupportPrompt } from "./use-tip-support-prompt";
import styles from "./tip-screen.module.css";

const TIP_ANALYTICS_CONTEXT: PaymentAnalyticsContext = {
  entryPoint: "tip_page",
  triggerReason: "ad_landing",
};

export interface TipScreenProps {
  initialCategory?: string | null;
  initialPlanId?: string | null;
  shouldResumePendingOrder?: boolean;
  initialPayChannel?: PayChannel | null;
  chatActionId?: string | null;
}

export function TipScreen({
  initialCategory = null,
  initialPlanId = null,
  shouldResumePendingOrder = false,
  initialPayChannel = null,
  chatActionId = null,
}: TipScreenProps) {
  const character = useActiveCharacter();
  const characterRoutes = useActiveCharacterRoutes();
  const userState = useUserState();
  const hasHydrated = useHasHydrated();
  const supportPrompt = useTipSupportPrompt(character.displayName);
  const paymentMethodConfig = getPaymentMethodConfig({
    countryCode: userState.currentUser?.countryCode,
    requestedPayChannel: initialPayChannel,
  });
  const renderedPaymentMethodConfig = hasHydrated
    ? paymentMethodConfig
    : { ...paymentMethodConfig, showPaymentMethodSelector: false };
  const { payment, paymentDispatch } = usePaymentRouteFlow({
    catalog: "tip",
    characterId: character.id,
    initialCategory,
    initialPlanId,
    initialPayChannel: paymentMethodConfig.initialPayChannel,
    paymentType: "tip",
    shouldResumePendingOrder,
    chatActionId,
  });

  const selectedCategory =
    payment.giftCategories.find(
      (category) => category.category === payment.selectedGiftCategory,
    ) ?? null;
  const visibleProducts = payment.selectedGiftCategory
    ? payment.giftProducts.filter(
        (product) => product.category === payment.selectedGiftCategory,
      )
    : [];
  const selectedProduct =
    visibleProducts.find(
      (product) => product.planId === payment.selectedPlanId,
    ) ?? null;
  const selectedPlan =
    payment.plans.find((plan) => plan.planId === payment.selectedPlanId) ??
    null;
  const returnPath = buildTipGiftPath(
    {
      category: payment.selectedGiftCategory,
      planId: payment.selectedPlanId || null,
    },
    characterRoutes.tip,
  );

  usePaymentPlanAnalytics(payment.plans, TIP_ANALYTICS_CONTEXT);

  const isPaymentBusy =
    payment.isCreatingOrder || payment.isPollingOrder || payment.isPaid;
  const canCreateOrder =
    selectedProduct !== null &&
    selectedPlan !== null &&
    payment.agreed &&
    !payment.autoRenew &&
    !payment.isLoadingPlans &&
    !isPaymentBusy;
  const isSelectionDisabled =
    !["ready", "failed", "expired"].includes(payment.status) ||
    payment.isLoadingPlans ||
    isPaymentBusy;
  const catalogLoaded =
    payment.status === "ready" && !payment.isLoadingPlans;
  const showCatalogError =
    catalogLoaded && payment.errorMessage !== null && visibleProducts.length === 0;
  const showEmptyCatalog =
    catalogLoaded && payment.errorMessage === null && visibleProducts.length === 0;

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

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

  useEffect(() => {
    if (!selectedProduct || isPaymentBusy || payment.isLoadingPlans) return;

    if (payment.autoRenew) {
      paymentDispatch({ type: "PaymentAutoRenewChanged", autoRenew: false });
      return;
    }

    if (!payment.agreed) {
      paymentDispatch({ type: "PaymentAgreementChanged", agreed: true });
    }
  }, [
    isPaymentBusy,
    payment.agreed,
    payment.autoRenew,
    payment.isLoadingPlans,
    paymentDispatch,
    selectedProduct,
  ]);

  const handleOrder = () => {
    if (!canCreateOrder || !selectedPlan) return;

    behaviorAnalytics.planClick(selectedPlan, TIP_ANALYTICS_CONTEXT);
    paymentDispatch({
      type: "PaymentCreateOrderSubmitted",
      recipientCharacterId: character.id,
    });
  };

  const handleProductChange = (planId: string) => {
    if (isSelectionDisabled || planId === payment.selectedPlanId) return;
    if (!visibleProducts.some((product) => product.planId === planId)) return;
    paymentDispatch({ type: "PaymentPlanSelected", planId });
  };

  if (payment.isPaid) {
    const successProduct =
      payment.giftProducts.find(
        (product) => product.planId === payment.tipMessage?.planId,
      ) ?? selectedProduct;
    const successCategory =
      payment.giftCategories.find(
        (category) => category.category === successProduct?.category,
      ) ?? selectedCategory;

    return (
      <TipSuccessView
        characterName={character.displayName}
        characterAvatar={character.assets.avatar}
        characterCover={character.assets.cover}
        giftImageSources={getGiftImageSources(
          successProduct,
          successCategory,
        )}
        giftName={
          payment.tipMessage?.productName ??
          successProduct?.planName ??
          "Your gift"
        }
        isMessageLoading={payment.isLoadingTipMessage}
        tipCount={payment.tipMessage?.tipCount ?? null}
        message={payment.tipMessage?.message ?? null}
        messageError={payment.tipMessageError}
        splashHref={characterRoutes.splash}
        onRetryMessage={() =>
          paymentDispatch({ type: "PaymentTipMessageRetryRequested" })
        }
        onSendAgain={() => paymentDispatch({ type: "PaymentReset" })}
      />
    );
  }

  return (
    <MobileShell background="#fff5ed">
      <main className={styles.shell}>
        <div className={styles.bgGlowOne} aria-hidden="true" />
        <div className={styles.bgGlowTwo} aria-hidden="true" />

        <header className={styles.header}>
          <BackButton
            href={characterRoutes.splash}
            variant="soft"
            iconSize={28}
            ariaLabel="Back to character home"
            analyticsKey="tip.back_to_splash"
          />
        </header>

        <div className={styles.contentFlow}>
          <div className={styles.headerIdentity}>
            <div className={styles.headerAvatar}>
              <CharacterAvatar
                src={character.assets.avatar}
                alt={character.displayName}
                size="100%"
                imageSize={88}
                priority
              />
            </div>
            <h1 id="tip-title" className={styles.headerTitle}>
              {character.copy.tipTitle}
            </h1>
          </div>

          <p
            className={`${styles.supportPrompt} ${
              supportPrompt.isReady ? styles.supportPromptReady : ""
            }`}
          >
            {supportPrompt.prompt}
          </p>

          <div className={styles.purchaseFlow}>
            {payment.isLoadingPlans ? (
              <section
                className={`${styles.productCard} ${styles.productSkeleton}`}
                aria-label="Loading gifts"
                aria-busy="true"
              >
                <div className={styles.skeletonImage} />
                <div className={styles.skeletonList}>
                  <span />
                  <span />
                  <span />
                </div>
              </section>
            ) : selectedProduct ? (
              <>
                <section
                  className={styles.productCard}
                  aria-label="Gift products"
                >
                  <div className={styles.coffeeStage}>
                    <TipProductImage
                      key={selectedProduct.planId}
                      sources={getGiftImageSources(
                        selectedProduct,
                        selectedCategory,
                      )}
                      alt={selectedProduct.planName}
                      className={styles.coffeeImage}
                      priority
                    />
                  </div>

                  <TipGiftProductSelector
                    disabled={isSelectionDisabled}
                    products={visibleProducts}
                    onChange={handleProductChange}
                    selectedPlanId={payment.selectedPlanId}
                  />
                </section>

                <PaymentMethodSelector
                  config={renderedPaymentMethodConfig}
                  value={payment.payChannel}
                  density="compact"
                  disabled={isPaymentBusy}
                  className={styles.paymentMethodSlot}
                  analyticsKey="tip.payment_method"
                  onChange={handlePaymentMethodChange}
                />

                <div className={styles.checkoutSlot}>
                  <TipCheckoutButton
                    giftCategory={payment.selectedGiftCategory}
                    giftPlanId={payment.selectedPlanId || null}
                    disabled={!canCreateOrder}
                    onOrder={handleOrder}
                    returnPath={returnPath}
                  />
                </div>
              </>
            ) : showCatalogError || showEmptyCatalog ? (
              <section className={styles.catalogStatus} role="status">
                <p>
                  {showCatalogError
                    ? "We could not load gifts for this character."
                    : "This character does not have any gifts available yet."}
                </p>
                {showCatalogError ? (
                  <button
                    type="button"
                    onClick={() =>
                      paymentDispatch({
                        type: "PaymentCatalogRetryRequested",
                      })
                    }
                  >
                    Try again
                  </button>
                ) : null}
              </section>
            ) : null}
          </div>
        </div>
      </main>
    </MobileShell>
  );
}
