import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import QRCode from 'qrcode';
import { createRechargeOrder, getBillingConfig, getRechargeOrder } from '../api/client';
import type { BillingConfig, RechargeOrder } from '../types';
import { invokeWechatJsapiPay, isWeChatBrowser } from '../utils/wechatPay';

function formatYuan(cents: number) {
  return `¥${(cents / 100).toFixed(cents % 100 === 0 ? 0 : 2)}`;
}

function detectPayScene(): 'native' | 'h5' | 'jsapi' {
  if (isWeChatBrowser()) return 'jsapi';
  return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent) ? 'h5' : 'native';
}

async function createRechargeOrderWithFallback(amountCents: number): Promise<RechargeOrder> {
  const payScene = detectPayScene();
  try {
    return await createRechargeOrder({ amountCents, payScene });
  } catch (err) {
    if (payScene !== 'h5') throw err;
    return createRechargeOrder({ amountCents, payScene: 'native' });
  }
}

function pickDefaultTier(tiers: number[], balanceCents: number) {
  if (!tiers.length) return 1000;
  if (balanceCents <= 0) {
    return tiers.find((tier) => tier >= 1000) ?? tiers[0];
  }
  return tiers.find((tier) => tier >= 1000) ?? tiers[0];
}

type RechargeModalProps = {
  open: boolean;
  force?: boolean;
  balanceCents: number;
  onClose: () => void;
  onSuccess: (balanceCents: number) => void;
};

export function RechargeModal({
  open,
  force = false,
  balanceCents,
  onClose,
  onSuccess,
}: RechargeModalProps) {
  const [config, setConfig] = useState<BillingConfig | null>(null);
  const [loadingConfig, setLoadingConfig] = useState(false);
  const [selectedCents, setSelectedCents] = useState(1000);
  const [order, setOrder] = useState<RechargeOrder | null>(null);
  const [qrDataUrl, setQrDataUrl] = useState<string | null>(null);
  const [paying, setPaying] = useState(false);
  const [polling, setPolling] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);
  const pollRef = useRef<number | null>(null);
  const redirectedRef = useRef(false);

  const tiers = config?.tiersCents ?? [];
  const projectedBalance = balanceCents + (order?.amountCents ?? selectedCents);

  const resetPayState = useCallback(() => {
    setOrder(null);
    setQrDataUrl(null);
    setPaying(false);
    setPolling(false);
    setError(null);
    setSuccessMessage(null);
    redirectedRef.current = false;
    if (pollRef.current != null) {
      window.clearInterval(pollRef.current);
      pollRef.current = null;
    }
  }, []);

  useEffect(() => {
    if (!open) {
      resetPayState();
      return;
    }
    setLoadingConfig(true);
    setError(null);
    void getBillingConfig()
      .then((loaded) => {
        setConfig(loaded);
        setSelectedCents(pickDefaultTier(loaded.tiersCents, loaded.balanceCents));
      })
      .catch((err) => {
        setError(err instanceof Error ? err.message : '无法加载充值配置');
      })
      .finally(() => setLoadingConfig(false));
  }, [open, resetPayState]);

  const stopPolling = useCallback(() => {
    if (pollRef.current != null) {
      window.clearInterval(pollRef.current);
      pollRef.current = null;
    }
    setPolling(false);
  }, []);

  const startPolling = useCallback(
    (orderId: string) => {
      stopPolling();
      setPolling(true);
      pollRef.current = window.setInterval(() => {
        void getRechargeOrder(orderId)
          .then((result) => {
            if (result.order.status === 'paid') {
              stopPolling();
              const nextBalance = result.balanceCents ?? projectedBalance;
              setSuccessMessage(`充值成功，当前余额 ${formatYuan(nextBalance)}`);
              window.setTimeout(() => onSuccess(nextBalance), 900);
            } else if (result.order.status === 'expired') {
              stopPolling();
              setError('订单已过期，请重新发起支付');
              setOrder(null);
              setQrDataUrl(null);
            }
          })
          .catch(() => {});
      }, 2000);
    },
    [onSuccess, projectedBalance, stopPolling],
  );

  useEffect(() => () => stopPolling(), [stopPolling]);

  useEffect(() => {
    if (!order?.codeUrl) {
      setQrDataUrl(null);
      return;
    }
    void QRCode.toDataURL(order.codeUrl, {
      width: 220,
      margin: 1,
      color: { dark: '#18211d', light: '#ffffff' },
    }).then(setQrDataUrl);
  }, [order?.codeUrl]);

  const handlePay = async () => {
    if (!config?.wechatEnabled) {
      setError('微信支付尚未配置，请联系管理员');
      return;
    }
    setPaying(true);
    setError(null);
    setSuccessMessage(null);
    try {
      const created = await createRechargeOrderWithFallback(selectedCents);
      setOrder(created);
      if (created.payMode === 'jsapi' && created.jsapiParams) {
        startPolling(created.id);
        const result = await invokeWechatJsapiPay(created.jsapiParams);
        if (result === 'cancel') {
          setError('已取消支付，可重新发起');
        }
        return;
      }
      if (created.payMode === 'h5' && created.h5Url && !redirectedRef.current) {
        redirectedRef.current = true;
        window.location.href = created.h5Url;
      }
      startPolling(created.id);
    } catch (err) {
      setError(err instanceof Error ? err.message : '创建支付订单失败');
    } finally {
      setPaying(false);
    }
  };

  const expireLabel = useMemo(() => {
    if (!order?.expireAt) return null;
    return new Date(order.expireAt).toLocaleTimeString('zh-CN', {
      hour: '2-digit',
      minute: '2-digit',
    });
  }, [order?.expireAt]);

  if (!open) return null;

  return createPortal(
    <div className="recharge-backdrop" role="presentation">
      <div
        className="recharge-dialog"
        role="dialog"
        aria-modal="true"
        aria-labelledby="recharge-title"
        onClick={(event) => event.stopPropagation()}
      >
        <div className="recharge-dialog-bar">
          <div>
            <p className="recharge-eyebrow">账户充值</p>
            <h3 id="recharge-title">{balanceCents <= 0 ? '余额不足，请充值后继续' : '为账户充值'}</h3>
          </div>
          {!force && (
            <button type="button" className="recharge-close" onClick={onClose} aria-label="关闭">
              关闭
            </button>
          )}
        </div>

        <div className="recharge-balance-row">
          <span>当前余额</span>
          <strong>{formatYuan(balanceCents)}</strong>
        </div>

        {loadingConfig ? (
          <p className="recharge-muted">加载充值档位…</p>
        ) : (
          <>
            <p className="recharge-muted">
              最低充值 {formatYuan(config?.minRechargeCents ?? 500)}，用于 AI 对话按量扣费
            </p>
            <div className="recharge-tier-grid">
              {tiers.map((tier) => (
                <button
                  key={tier}
                  type="button"
                  className={`recharge-tier${selectedCents === tier ? ' recharge-tier-active' : ''}`}
                  disabled={Boolean(order)}
                  onClick={() => setSelectedCents(tier)}
                >
                  {formatYuan(tier)}
                </button>
              ))}
            </div>
            <p className="recharge-projected">
              充值后预计余额：<strong>{formatYuan(projectedBalance)}</strong>
            </p>
          </>
        )}

        {error && <p className="recharge-error">{error}</p>}
        {successMessage && <p className="recharge-success">{successMessage}</p>}

        {order?.payMode === 'native' && qrDataUrl && (
          <div className="recharge-qr-panel">
            <img src={qrDataUrl} alt="微信支付二维码" className="recharge-qr" />
            <p className="recharge-muted">请使用微信扫一扫完成支付</p>
            {expireLabel && <p className="recharge-muted">订单将于 {expireLabel} 过期</p>}
          </div>
        )}

        {order?.payMode === 'jsapi' && (
          <div className="recharge-h5-panel">
            <p className="recharge-muted">
              {polling ? '请在微信支付弹窗中完成付款…' : '点击「微信支付」后将直接调起微信收银台'}
            </p>
            {expireLabel && <p className="recharge-muted">订单将于 {expireLabel} 过期</p>}
          </div>
        )}

        {order?.payMode === 'h5' && (
          <div className="recharge-h5-panel">
            <p className="recharge-muted">已跳转微信收银台；若未自动打开，请点击下方按钮。</p>
            {order.h5Url && (
              <a className="recharge-h5-link" href={order.h5Url}>
                打开微信支付
              </a>
            )}
          </div>
        )}

        <div className="recharge-actions">
          {!order ? (
            <button
              type="button"
              className="recharge-pay-btn"
              disabled={paying || loadingConfig || !config?.wechatEnabled}
              onClick={() => void handlePay()}
            >
              {paying ? '创建订单中…' : '微信支付'}
            </button>
          ) : (
            <button
              type="button"
              className="recharge-secondary-btn"
              disabled={polling}
              onClick={() => {
                resetPayState();
              }}
            >
              重新选择金额
            </button>
          )}
        </div>

        {!config?.wechatEnabled && !loadingConfig && (
          <p className="recharge-warning">支付渠道尚未配置，请联系管理员开通。</p>
        )}

        <p className="recharge-legal">支付完成后余额自动到账，如有疑问请联系客服。</p>
      </div>
    </div>,
    document.body,
  );
}
