"use client";

import { useEffect, useMemo, useState, type CSSProperties } from "react";
import Image from "next/image";
import { Heart, Sparkles } from "lucide-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 {
  buildTipCoffeePath,
  DEFAULT_TIP_COFFEE_TYPE,
  getTipCoffeeOption,
  TIP_COFFEE_OPTIONS,
  type TipCoffeeType,
} from "@/lib/tip/tip_coffee";
import { useAppNavigator } from "@/router/use-app-navigator";
import {
  useActiveCharacter,
  useActiveCharacterRoutes,
} from "@/providers/character-provider";
import { useAuthState } from "@/stores/auth/auth-context";
import { useUserState } from "@/stores/user/user-context";

import { TipCheckoutButton } from "./tip-checkout-button";
import {
  TipCoffeeTierSelector,
  type TipCoffeeTierItem,
} from "./tip-coffee-tier-selector";
import {
  findTipCoffeePlan,
  formatTipPrice,
  isRealLoginStatus,
} from "./tip-screen.helpers";
import styles from "./tip-screen.module.css";

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

export interface TipScreenProps {
  coffeeType?: TipCoffeeType;
  shouldResumePendingOrder?: boolean;
  initialPayChannel?: PayChannel | null;
}

export function TipScreen({
  coffeeType = DEFAULT_TIP_COFFEE_TYPE,
  shouldResumePendingOrder = false,
  initialPayChannel = null,
}: TipScreenProps) {
  const navigator = useAppNavigator();
  const character = useActiveCharacter();
  const characterRoutes = useActiveCharacterRoutes();
  const authState = useAuthState();
  const userState = useUserState();
  const paymentMethodConfig = getPaymentMethodConfig({
    countryCode: userState.currentUser?.countryCode,
    requestedPayChannel: initialPayChannel,
  });
  const [selectedCoffeeType, setSelectedCoffeeType] =
    useState<TipCoffeeType>(coffeeType);
  const coffeeOption = getTipCoffeeOption(selectedCoffeeType);
  const returnPath = buildTipCoffeePath(
    selectedCoffeeType,
    characterRoutes.tip,
  );
  const { payment, paymentDispatch } = usePaymentRouteFlow({
    catalog: "tip",
    initialPayChannel: paymentMethodConfig.initialPayChannel,
    paymentType: "tip",
    shouldResumePendingOrder,
  });

  const coffeeTiers = useMemo(
    () =>
      TIP_COFFEE_OPTIONS.map((option) => ({
        option,
        plan: findTipCoffeePlan(payment.plans, option.type),
      })),
    [payment.plans],
  );
  const coffeePlan =
    coffeeTiers.find(({ option }) => option.type === selectedCoffeeType)?.plan ??
    null;
  const priceLabel = formatTipPrice(coffeePlan, selectedCoffeeType);
  const availableCoffeePlans = useMemo(
    () => coffeeTiers.flatMap(({ plan }) => (plan ? [plan] : [])),
    [coffeeTiers],
  );
  const tierItems = useMemo<readonly TipCoffeeTierItem[]>(
    () =>
      coffeeTiers.map(({ option, plan }) => ({
        type: option.type,
        displayName: option.displayName,
        priceLabel: formatTipPrice(plan, option.type),
        unavailable:
          payment.status === "ready" &&
          !payment.isLoadingPlans &&
          plan === null,
      })),
    [coffeeTiers, payment.isLoadingPlans, payment.status],
  );
  usePaymentPlanAnalytics(availableCoffeePlans, TIP_ANALYTICS_CONTEXT);
  const isPaymentBusy =
    payment.isCreatingOrder || payment.isPollingOrder || payment.isPaid;
  const canCreateOrder =
    coffeePlan !== null &&
    payment.selectedPlanId === coffeePlan.planId &&
    payment.agreed &&
    !payment.autoRenew &&
    !payment.isLoadingPlans &&
    !isPaymentBusy;
  const showMissingPlan =
    payment.status === "ready" && !payment.isLoadingPlans && coffeePlan === null;
  const isTierSelectionDisabled =
    payment.status !== "ready" || payment.isLoadingPlans || isPaymentBusy;
  const isAuthLoading = !authState.hasInitialized || authState.isLoading;

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

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

  useEffect(() => {
    if (payment.isLoadingPlans || payment.isCreatingOrder || payment.isPollingOrder) {
      return;
    }
    if (!coffeePlan) return;

    if (payment.selectedPlanId !== coffeePlan.planId) {
      paymentDispatch({
        type: "PaymentPlanSelected",
        planId: coffeePlan.planId,
      });
      return;
    }

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

    if (!payment.agreed) {
      paymentDispatch({ type: "PaymentAgreementChanged", agreed: true });
    }
  }, [
    coffeePlan,
    payment.agreed,
    payment.autoRenew,
    payment.isCreatingOrder,
    payment.isLoadingPlans,
    payment.isPollingOrder,
    payment.selectedPlanId,
    paymentDispatch,
  ]);

  const handleOrder = () => {
    if (isAuthLoading) return;
    if (coffeePlan) {
      behaviorAnalytics.planClick(coffeePlan, TIP_ANALYTICS_CONTEXT);
    }
    if (!isRealLoginStatus(authState.loginStatus)) {
      navigator.openAuth(returnPath);
      return;
    }
    if (!canCreateOrder) return;

    paymentDispatch({
      type: "PaymentCreateOrderSubmitted",
      recipientCharacterId: character.id,
    });
  };

  const handleCoffeeTypeChange = (type: TipCoffeeType) => {
    if (isTierSelectionDisabled) return;
    const nextPlan = findTipCoffeePlan(payment.plans, type);
    if (!nextPlan) return;

    setSelectedCoffeeType(type);
    if (payment.selectedPlanId !== nextPlan.planId) {
      paymentDispatch({
        type: "PaymentPlanSelected",
        planId: nextPlan.planId,
      });
    }
  };

  const handleResetPaidState = () => {
    paymentDispatch({ type: "PaymentReset" });
  };

  return (
    <MobileShell background="#fff5ed">
      <main
        className={styles.shell}
        style={
          {
            "--tip-cover-image": `url("${character.assets.cover}")`,
          } as CSSProperties
        }
      >
        <div className={styles.bgImage} aria-hidden="true" />
        <div className={styles.bgGlowOne} aria-hidden="true" />
        <div className={styles.bgGlowTwo} aria-hidden="true" />

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

        <section className={styles.hero} aria-labelledby="tip-title">
          <div className={styles.avatarRing}>
            <CharacterAvatar
              src={character.assets.avatar}
              alt={character.displayName}
              size="100%"
              imageSize={88}
              priority
            />
          </div>
          <p className={styles.eyebrow}>A little sweetness for today</p>
          <h1 id="tip-title" className={styles.title}>
            {character.copy.tipTitle}
          </h1>
          <p className={styles.subtitle}>
            Send a warm coffee tip and keep the private moments glowing.
          </p>
        </section>

        <section className={styles.productCard} aria-label="Coffee tip product">
          <div className={styles.coffeeStage}>
            <Image
              src={coffeeOption.image.src}
              alt={`${coffeeOption.displayName} coffee`}
              width={coffeeOption.image.width}
              height={coffeeOption.image.height}
              sizes="(max-width: 380px) 220px, 211px"
              className={styles.coffeeImage}
            />
          </div>

          <div className={styles.productCopy}>
            <span className={styles.productBadge}>
              <Sparkles size={14} aria-hidden="true" />
              Coffee Gift
            </span>
            <h2 className={styles.productName}>
              {coffeeOption.displayName}
            </h2>
            <p className={styles.productPrice}>{priceLabel}</p>
          </div>

          <TipCoffeeTierSelector
            disabled={isTierSelectionDisabled}
            items={tierItems}
            onChange={handleCoffeeTypeChange}
            selectedType={selectedCoffeeType}
          />
        </section>

        <PaymentMethodSelector
          config={paymentMethodConfig}
          value={payment.payChannel}
          disabled={isPaymentBusy}
          caption="GCash by default in the Philippines"
          className={styles.paymentMethodSlot}
          analyticsKey="tip.payment_method"
          onChange={handlePaymentMethodChange}
        />

        {showMissingPlan ? (
          <p className={styles.statusMessage} role="alert">
            Coffee tip is not available yet. Please try again later.
          </p>
        ) : null}

        {payment.isPaid ? (
          <section className={styles.successCard} aria-live="polite">
            <Heart size={18} aria-hidden="true" />
            <div>
              <p className={styles.successTitle}>Coffee sent</p>
              <p className={styles.successText}>
                Thank you. Your payment has been confirmed.
              </p>
            </div>
            <button
              type="button"
              className={styles.successButton}
              onClick={handleResetPaidState}
            >
              Send again
            </button>
          </section>
        ) : null}

        <div className={styles.checkoutSlot}>
          <TipCheckoutButton
            coffeeType={selectedCoffeeType}
            disabled={
              showMissingPlan ||
              (!canCreateOrder && isRealLoginStatus(authState.loginStatus))
            }
            isAuthLoading={isAuthLoading}
            onOrder={handleOrder}
            returnPath={returnPath}
          />
        </div>
      </main>
    </MobileShell>
  );
}
