import { useEffect, useRef, useState, type CSSProperties } from 'react';

const RING_R = 16;
const CIRC = 2 * Math.PI * RING_R;
const POPOVER_WIDTH = 260;

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

function formatTokenCount(tokens: number) {
  if (tokens >= 100_000) {
    return `${(tokens / 10_000).toFixed(1).replace(/\.0$/, '')} 万`;
  }
  if (tokens >= 10_000) {
    return `${(tokens / 10_000).toFixed(2).replace(/\.?0+$/, '')} 万`;
  }
  if (tokens >= 1_000) {
    return `${(tokens / 1_000).toFixed(1).replace(/\.0$/, '')}k`;
  }
  return tokens.toLocaleString('zh-CN');
}

type BalanceRingProps = {
  balanceCents: number;
  totalCreditCents?: number;
  tokensUsed?: number;
  onRecharge: (force?: boolean) => void;
};

export function BalanceRing({
  balanceCents,
  totalCreditCents,
  tokensUsed = 0,
  onRecharge,
}: BalanceRingProps) {
  const [open, setOpen] = useState(false);
  const [popoverStyle, setPopoverStyle] = useState<CSSProperties>({});
  const wrapRef = useRef<HTMLDivElement>(null);

  const total = Math.max(totalCreditCents ?? balanceCents, balanceCents, 0);
  const spent = Math.max(0, total - balanceCents);
  const pct = total > 0 ? Math.round((balanceCents / total) * 100) : 0;
  const spentLen = total > 0 ? (spent / total) * CIRC : 0;
  const remainLen = total > 0 ? (balanceCents / total) * CIRC : 0;
  const spentPct = total > 0 ? (spent / total) * 100 : 0;
  const remainPct = total > 0 ? (balanceCents / total) * 100 : 0;

  const low = balanceCents > 0 && balanceCents <= 100;
  const empty = balanceCents <= 0;

  useEffect(() => {
    if (!open) return;
    const handleClick = (event: MouseEvent) => {
      if (wrapRef.current && !wrapRef.current.contains(event.target as Node)) {
        setOpen(false);
      }
    };
    document.addEventListener('click', handleClick);
    return () => document.removeEventListener('click', handleClick);
  }, [open]);

  useEffect(() => {
    if (!open) return;

    const updatePosition = () => {
      const anchor = wrapRef.current;
      if (!anchor) return;
      const rect = anchor.getBoundingClientRect();
      const width = Math.min(POPOVER_WIDTH, window.innerWidth - 24);
      let left = rect.left + rect.width / 2 - width / 2;
      left = Math.max(12, Math.min(left, window.innerWidth - width - 12));
      setPopoverStyle({
        position: 'fixed',
        top: rect.bottom + 10,
        left,
        width,
      });
    };

    updatePosition();
    window.addEventListener('resize', updatePosition);
    window.addEventListener('scroll', updatePosition, true);
    return () => {
      window.removeEventListener('resize', updatePosition);
      window.removeEventListener('scroll', updatePosition, true);
    };
  }, [open]);

  const centerLabel = total <= 0 ? '—' : empty ? '0%' : `${pct}%`;
  const ariaLabel = total > 0 ? `账户额度，剩余 ${pct}%` : '账户额度';

  return (
    <div className={`balance-popover-wrap${open ? ' open' : ''}`} ref={wrapRef}>
      <button
        type="button"
        className={`balance-ring-btn${low ? ' low' : ''}${empty ? ' empty' : ''}`}
        aria-label={ariaLabel}
        aria-expanded={open}
        onClick={(event) => {
          event.stopPropagation();
          setOpen((value) => !value);
        }}
      >
        <svg className="balance-ring-svg" viewBox="0 0 40 40" aria-hidden="true">
          <circle className="balance-ring-track" cx="20" cy="20" r={RING_R} />
          <circle
            className="balance-ring-spent"
            cx="20"
            cy="20"
            r={RING_R}
            strokeDasharray={`${spentLen} ${CIRC}`}
            strokeDashoffset={0}
          />
          <circle
            className="balance-ring-remain"
            cx="20"
            cy="20"
            r={RING_R}
            strokeDasharray={`${remainLen} ${CIRC}`}
            strokeDashoffset={-spentLen}
          />
        </svg>
        <span className="balance-ring-center">{centerLabel}</span>
      </button>

      <div className="balance-popover" role="dialog" aria-label="账户额度" style={popoverStyle}>
        <h4>账户额度</h4>
        <div className="balance-popover-row">
          <span className="balance-popover-label">
            <span className="balance-dot balance-dot-remain" aria-hidden="true" />
            剩余
          </span>
          <strong>{formatYuan(balanceCents)}</strong>
        </div>
        <div className="balance-popover-row">
          <span className="balance-popover-label">
            <span className="balance-dot balance-dot-spent" aria-hidden="true" />
            已消耗
          </span>
          <strong>{formatYuan(spent)}</strong>
        </div>
        <div className="balance-popover-row">
          <span className="balance-popover-label balance-popover-label-muted">累计充值</span>
          <span>{formatYuan(total)}</span>
        </div>
        <div className="balance-popover-bar" aria-hidden="true">
          <div className="balance-popover-bar-spent" style={{ width: `${spentPct}%` }} />
          <div className="balance-popover-bar-remain" style={{ width: `${remainPct}%` }} />
        </div>

        <div className="balance-popover-section">
          <h5>AI 消耗</h5>
          <div className="balance-popover-row">
            <span className="balance-popover-label balance-popover-label-muted">累计 Token</span>
            <span>{formatTokenCount(tokensUsed)}</span>
          </div>
          <p className="balance-popover-hint">按人民币结算，每次对话按实际用量扣费</p>
        </div>

        <button
          type="button"
          className="balance-popover-cta"
          onClick={() => {
            setOpen(false);
            onRecharge(empty);
          }}
        >
          去充值
        </button>
      </div>
    </div>
  );
}
