"use client";

import { Wallet } from "lucide-react";
import Image from "next/image";
import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";

import { getWalletBalance, getWalletLogs } from "@/api/wallet";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { PlayerPanel } from "@/components/layout/player-panel";
import {
  TransferInDialog,
  TransferOutDialog,
} from "@/features/wallet/wallet-transfer-dialogs";
import { WalletLogsBlock } from "@/features/wallet/wallet-logs-block";
import { dispatchWalletLogsRefresh } from "@/hooks/use-pending-wallet-reconcile";
import { useActivePlayerCurrency } from "@/hooks/use-active-player-currency";
import { formatMinorAsCurrency } from "@/lib/money";
import { PLAYER_CURRENCY_CHANGE_EVENT } from "@/lib/player-currency-preference";
import { formatWalletClientError } from "@/lib/wallet-api-error";
import type { WalletBalanceData } from "@/types/api/wallet-balance";
import { getWalletLogsLastPage, type WalletLogsData } from "@/types/api/wallet-logs";

const WALLET_LOGS_PAGE_SIZE = 10;

export function WalletScreen() {
  const { activeCurrency: currency } = useActivePlayerCurrency();
  const { t } = useTranslation("player");
  const [balance, setBalance] = useState<WalletBalanceData | null>(null);
  const [logs, setLogs] = useState<WalletLogsData | null>(null);
  const [filter, setFilter] = useState("");
  const [loading, setLoading] = useState(true);
  const [logsLoading, setLogsLoading] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const loadMoreRef = useRef<HTMLDivElement | null>(null);

  const fetchPassRef = useRef(true);

  const loadLogs = useCallback(async (targetPage = 1, append = false) => {
    const nextLogs = await getWalletLogs({
      page: targetPage,
      size: WALLET_LOGS_PAGE_SIZE,
      type: filter || undefined,
      currency,
    });
    setLogs((current) =>
      append && current
        ? { ...nextLogs, items: [...current.items, ...nextLogs.items] }
        : nextLogs,
    );
    dispatchWalletLogsRefresh(nextLogs.pending_reconcile ?? []);
    return nextLogs;
  }, [currency, filter]);

  useEffect(() => {
    let cancelled = false;

    void (async () => {
      setError(null);
      if (fetchPassRef.current) {
        setLoading(true);
        fetchPassRef.current = false;
      } else {
        setLogsLoading(true);
      }
      try {
        const b = await getWalletBalance({ currency });
        if (cancelled) return;
        setBalance(b);
        const nextLogs = await loadLogs(1, false);
        if (cancelled) return;
        setLogs(nextLogs);
      } catch (e) {
        if (!cancelled) {
          setError(formatWalletClientError(e, t));
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
          setLogsLoading(false);
        }
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [currency, loadLogs, t]);

  const refreshAll = useCallback(async () => {
    setError(null);
    setLogsLoading(true);
    try {
      const b = await getWalletBalance({ currency });
      setBalance(b);
      await loadLogs(1, false);
    } catch (e) {
      setError(formatWalletClientError(e, t));
    } finally {
      setLogsLoading(false);
      setLoading(false);
    }
  }, [currency, loadLogs, t]);

  useEffect(() => {
    const onCurrencyChange = () => void refreshAll();
    window.addEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange);
    return () => window.removeEventListener(PLAYER_CURRENCY_CHANGE_EVENT, onCurrencyChange);
  }, [refreshAll]);

  const hasMore = logs ? logs.page < getWalletLogsLastPage(logs) : false;

  const loadMore = useCallback(() => {
    if (!logs || !hasMore || loadingMore) return;

    setError(null);
    setLoadingMore(true);
    void loadLogs(logs.page + 1, true)
      .catch((e) => {
        setError(formatWalletClientError(e, t));
      })
      .finally(() => {
        setLoadingMore(false);
      });
  }, [hasMore, loadLogs, loadingMore, logs, t]);

  useEffect(() => {
    const target = loadMoreRef.current;
    if (!target || loading || logsLoading || loadingMore || !hasMore) return;

    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry?.isIntersecting) {
          loadMore();
        }
      },
      { rootMargin: "160px" },
    );

    observer.observe(target);
    return () => observer.disconnect();
  }, [hasMore, loadMore, loading, loadingMore, logsLoading]);

  return (
    <PlayerPanel title={t("wallet.title")}>
      <div className="space-y-3">
        {error ? (
          <div className="rounded-xl border border-red-200 bg-red-50 px-3 py-3 text-sm text-red-700">
            <p>{error}</p>
            <Button
              type="button"
              className="mt-3 bg-[#e5002c] text-white hover:bg-[#d10028]"
              onClick={() => void refreshAll()}
            >
              {t("actions.retry")}
            </Button>
          </div>
        ) : null}

        <section className="relative overflow-hidden rounded-xl bg-[#e5002c] px-3 py-4 text-white shadow-[0_10px_28px_rgba(229,0,44,0.25)]">
          <Image
            src="/entry/image5.png"
            alt=""
            fill
            className="pointer-events-none object-cover object-center"
            aria-hidden
          />
          <div className="relative flex items-center gap-3">
            <div className="flex size-13 shrink-0 items-center justify-center rounded-full bg-white text-[#d81435] shadow-sm">
              <Wallet className="size-7" aria-hidden />
            </div>
            <div className="min-w-0 flex-1">
              <p className="text-sm font-semibold text-white/90">{t("wallet.balance")}</p>
              {loading ? (
                <Skeleton className="mt-2 h-8 w-44 rounded-md bg-white/25" />
              ) : (
                <p className="mt-1 text-2xl font-black leading-none tabular-nums tracking-normal">
                  {formatMinorAsCurrency(balance?.balance ?? 0, currency)}
                </p>
              )}
              <p className="mt-2 text-xs text-white/75">
                {t("wallet.available", {
                  amount: formatMinorAsCurrency(balance?.available_balance ?? 0, currency),
                })}
              </p>
            </div>
          </div>
        </section>

        <div className="grid grid-cols-2 gap-3">
          <TransferInDialog
            idPrefix="wallet-"
            currency={currency}
            lotteryMinor={Number(balance?.balance ?? 0)}
            mainMinor={
              balance?.main_balance === null || balance?.main_balance === undefined
                ? null
                : Number(balance.main_balance)
            }
            onSuccess={refreshAll}
            triggerVariant="hall"
            triggerLabel={t("wallet.transferIn", { defaultValue: "Transfer In" })}
            triggerClassName="h-14 rounded-2xl text-base font-black"
          />
          <TransferOutDialog
            idPrefix="wallet-"
            currency={currency}
            availableMinor={Number(balance?.available_balance ?? 0)}
            onSuccess={refreshAll}
            triggerVariant="hall"
            triggerLabel={t("wallet.transferOut", { defaultValue: "Transfer Out" })}
            triggerClassName="h-14 rounded-2xl text-base font-black"
          />
        </div>

        <WalletLogsBlock
          logs={logs}
          logsLoading={loading || logsLoading}
          loadingMore={loadingMore}
          hasMore={hasMore}
          onLoadMore={loadMore}
          loadMoreRef={loadMoreRef}
          filter={filter}
          onFilterChange={setFilter}
          currency={currency}
        />
      </div>
    </PlayerPanel>
  );
}
