import { useEffect, useRef, useState, type CSSProperties } from 'react';
import { getMyUsage } from '../api/client';
import type { UsageRecord } from '../types';

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

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');
}

function formatTokenCompact(tokens: number) {
  if (tokens >= 1_000) {
    return `${(tokens / 1_000).toFixed(1).replace(/\.0$/, '')}k`;
  }
  return String(tokens);
}

function formatUsageTime(ts: number) {
  const date = new Date(ts);
  const now = new Date();
  const isToday =
    date.getFullYear() === now.getFullYear() &&
    date.getMonth() === now.getMonth() &&
    date.getDate() === now.getDate();
  const time = date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
  if (isToday) return `今天 ${time}`;
  return date.toLocaleString('zh-CN', {
    month: 'numeric',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
}

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 [usageRecords, setUsageRecords] = useState<UsageRecord[] | null>(null);
  const [usageLoading, setUsageLoading] = useState(false);
  const [usageError, setUsageError] = useState<string | null>(null);
  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;
  const showRecentUsage = low || empty;

  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]);

  useEffect(() => {
    if (!open) return;
    let cancelled = false;
    setUsageLoading(true);
    setUsageError(null);
    void getMyUsage()
      .then((records) => {
        if (!cancelled) setUsageRecords(records);
      })
      .catch((err) => {
        if (!cancelled) {
          setUsageError(err instanceof Error ? err.message : '加载失败');
        }
      })
      .finally(() => {
        if (!cancelled) setUsageLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [open, tokensUsed, balanceCents]);

  useEffect(() => {
    if (open) return;
    setUsageRecords(null);
    setUsageError(null);
    setUsageLoading(false);
  }, [open]);

  const recentUsage = (usageRecords ?? []).slice(0, RECENT_USAGE_LIMIT);
  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>

        <div
          className={`balance-popover-section balance-popover-usage${showRecentUsage ? ' expanded' : ''}`}
        >
          <h5>近期扣费</h5>
          {usageLoading ? (
            <p className="balance-popover-muted">加载中…</p>
          ) : usageError ? (
            <p className="balance-popover-muted">{usageError}</p>
          ) : recentUsage.length === 0 ? (
            <p className="balance-popover-muted">暂无扣费记录</p>
          ) : (
            <ul className="balance-usage-list">
              {recentUsage.map((row) => (
                <li key={row.id} className="balance-usage-item">
                  <span className="balance-usage-time">{formatUsageTime(row.createdAt)}</span>
                  <span className="balance-usage-tokens">
                    输入 {formatTokenCompact(row.inputTokens)} / 输出{' '}
                    {formatTokenCompact(row.outputTokens)}
                  </span>
                  <strong className="balance-usage-cost">{formatYuan(row.costCents)}</strong>
                </li>
              ))}
            </ul>
          )}
        </div>

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