import { useCallback, useEffect, useMemo, useState } from 'react';
import { AlertTriangle, RefreshCw, RotateCcw, Search } from 'lucide-react';
import type { BillingSettlement } from '@easyai-ai-gateway/contracts';
import { listBillingSettlements, retryBillingSettlement } from '../../api';
import {
  Badge,
  Button,
  Card,
  CardContent,
  Checkbox,
  ConfirmDialog,
  Input,
  Select,
  Table,
  TableCell,
  TableHead,
  TableRow,
} from '../../components/ui';

export function BillingSettlementsPanel(props: { token: string }) {
  const [items, setItems] = useState<BillingSettlement[]>([]);
  const [query, setQuery] = useState('');
  const [status, setStatus] = useState('');
  const [loading, setLoading] = useState(false);
  const [retrying, setRetrying] = useState('');
  const [batchRetrying, setBatchRetrying] = useState(false);
  const [confirming, setConfirming] = useState<BillingSettlement | null>(null);
  const [batchConfirming, setBatchConfirming] = useState(false);
  const [selectedIds, setSelectedIds] = useState<Set<string>>(() => new Set());
  const [message, setMessage] = useState('');

  const load = useCallback(async (signal?: AbortSignal) => {
    setLoading(true);
    setMessage('');
    try {
      const result = await listBillingSettlements(props.token, { status, pageSize: 100, signal });
      setItems(result.items);
    } catch (error) {
      if (signal?.aborted) return;
      setMessage(error instanceof Error ? error.message : '结算队列加载失败');
    } finally {
      if (!signal?.aborted) setLoading(false);
    }
  }, [props.token, status]);

  useEffect(() => {
    const controller = new AbortController();
    void load(controller.signal);
    return () => controller.abort();
  }, [load]);

  const filteredItems = useMemo(() => {
    const keyword = query.trim().toLowerCase();
    if (!keyword) return items;
    return items.filter((item) => [
      item.id,
      item.taskId,
      item.action,
      item.status,
      item.lastErrorCode,
      item.manualReviewReason,
    ].filter(Boolean).join(' ').toLowerCase().includes(keyword));
  }, [items, query]);
  const retryableItems = useMemo(() => items.filter(canRetry), [items]);
  const visibleRetryableItems = useMemo(() => filteredItems.filter(canRetry), [filteredItems]);
  const selectedItems = useMemo(
    () => retryableItems.filter((item) => selectedIds.has(item.id)),
    [retryableItems, selectedIds],
  );
  const allVisibleSelected = visibleRetryableItems.length > 0
    && visibleRetryableItems.every((item) => selectedIds.has(item.id));
  const someVisibleSelected = visibleRetryableItems.some((item) => selectedIds.has(item.id));
  const busy = batchRetrying || Boolean(retrying);

  useEffect(() => {
    const retryableIds = new Set(retryableItems.map((item) => item.id));
    setSelectedIds((current) => {
      const next = new Set(Array.from(current).filter((id) => retryableIds.has(id)));
      return next.size === current.size ? current : next;
    });
  }, [retryableItems]);

  async function retry(item: BillingSettlement) {
    setRetrying(item.id);
    setMessage('');
    try {
      await retryBillingSettlement(props.token, item.id);
      await load();
      setMessage(`结算 ${shortId(item.id)} 已重新进入队列`);
    } catch (error) {
      setMessage(error instanceof Error ? error.message : '结算重试失败');
    } finally {
      setRetrying('');
    }
  }

  function toggleItem(itemId: string, checked: boolean) {
    setSelectedIds((current) => {
      const next = new Set(current);
      if (checked) next.add(itemId);
      else next.delete(itemId);
      return next;
    });
  }

  function toggleVisible(checked: boolean) {
    setSelectedIds((current) => {
      const next = new Set(current);
      visibleRetryableItems.forEach((item) => {
        if (checked) next.add(item.id);
        else next.delete(item.id);
      });
      return next;
    });
  }

  async function retrySelected() {
    if (!selectedItems.length) return;
    setBatchRetrying(true);
    setMessage('');
    const processingItems = [...selectedItems];
    try {
      const { failedIds, succeeded } = await retrySettlementBatch(
        processingItems,
        (item) => retryBillingSettlement(props.token, item.id),
      );
      setSelectedIds(new Set(failedIds));
      await load();
      setMessage(failedIds.length
        ? `批量结算完成：成功 ${succeeded} 条，失败 ${failedIds.length} 条；失败记录已保留选择。`
        : `已批量结算 ${succeeded} 条记录。`);
    } catch (error) {
      setMessage(error instanceof Error ? error.message : '批量结算处理失败');
    } finally {
      setBatchRetrying(false);
    }
  }

  return (
    <section className="pageStack">
      <Card className="compactAdminTableCard">
        <CardContent className="compactAdminTableContent">
          <div className="compactAdminToolbar billingCompactToolbar">
            <span className="platformSearchBox compactAdminSearch">
              <Search size={15} />
              <Input
                aria-label="搜索计费结算"
                value={query}
                placeholder="任务 ID、结算 ID、动作或异常原因"
                onChange={(event) => setQuery(event.target.value)}
              />
            </span>
            <Select size="sm" aria-label="结算状态" value={status} onChange={(event) => setStatus(event.target.value)}>
              <option value="">全部状态</option>
              <option value="pending">待处理</option>
              <option value="processing">处理中</option>
              <option value="retryable_failed">等待重试</option>
              <option value="manual_review">人工复核</option>
              <option value="completed">已完成</option>
            </Select>
            <div className="compactAdminToolbarActions">
              <Button type="button" size="sm" disabled={!selectedItems.length || busy} onClick={() => setBatchConfirming(true)}>
                <RotateCcw size={14} />
                {batchRetrying ? '结算中' : `批量结算${selectedItems.length ? `（${selectedItems.length}）` : ''}`}
              </Button>
              <Button type="button" size="sm" variant="outline" disabled={loading || busy} onClick={() => void load()}>
                <RefreshCw size={14} />{loading ? '刷新中' : '刷新'}
              </Button>
            </div>
          </div>
          {message && <p className="formMessage">{message}</p>}
          {filteredItems.length ? (
            <div className="billingSettlementTableViewport">
              <Table density="compact" className="identityDataTable billingSettlementTable">
                <TableRow>
                  <TableHead>
                    <Checkbox
                      aria-label="选择当前筛选结果中的全部可处理结算"
                      checked={allVisibleSelected ? true : someVisibleSelected ? 'indeterminate' : false}
                      disabled={!visibleRetryableItems.length || busy}
                      onCheckedChange={(checked) => toggleVisible(checked === true)}
                    />
                  </TableHead>
                  <TableHead>任务 / 动作</TableHead>
                  <TableHead>状态</TableHead>
                  <TableHead>金额</TableHead>
                  <TableHead>尝试</TableHead>
                  <TableHead>异常分类</TableHead>
                  <TableHead>操作</TableHead>
                </TableRow>
                {filteredItems.map((item) => (
                  <TableRow key={item.id}>
                    <TableCell>
                      <Checkbox
                        aria-label={`选择结算 ${shortId(item.id)}`}
                        checked={selectedIds.has(item.id)}
                        disabled={!canRetry(item) || busy}
                        onCheckedChange={(checked) => toggleItem(item.id, checked === true)}
                      />
                    </TableCell>
                    <TableCell>
                      <span className="identityTableName">
                        <strong>{shortId(item.taskId)}</strong>
                        <small>{item.action === 'settle' ? '扣费' : '释放冻结'} · {shortId(item.id)}</small>
                      </span>
                    </TableCell>
                    <TableCell><Badge variant={statusVariant(item.status)}>{statusLabel(item.status)}</Badge></TableCell>
                    <TableCell>{formatAmount(item.amount)} {item.currency}</TableCell>
                    <TableCell>{item.attempts} / 20</TableCell>
                    <TableCell>{item.lastErrorCode || item.manualReviewReason || '-'}</TableCell>
                    <TableCell>
                      {canRetry(item) ? (
                        <Button type="button" size="xs" variant="outline" disabled={busy} onClick={() => setConfirming(item)}>
                          <RotateCcw size={13} />{retrying === item.id ? '提交中' : retryActionLabel(item)}
                        </Button>
                      ) : '-'}
                    </TableCell>
                  </TableRow>
                ))}
              </Table>
            </div>
          ) : (
            <div className="emptyState">
              <AlertTriangle size={18} />
              <strong>{loading ? '正在加载结算队列' : '暂无匹配的结算记录'}</strong>
              <span>可调整搜索或状态筛选查看其他记录。</span>
            </div>
          )}
        </CardContent>
      </Card>
      <ConfirmDialog
        open={Boolean(confirming)}
        loading={Boolean(confirming && retrying === confirming.id)}
        title={confirming ? `${retryActionLabel(confirming)}这条计费记录？` : '处理计费记录？'}
        description={confirming ? retryActionDescription(confirming) : ''}
        confirmLabel={confirming ? retryActionLabel(confirming) : '确认'}
        onCancel={() => setConfirming(null)}
        onConfirm={() => {
          if (!confirming) return;
          const item = confirming;
          void retry(item).finally(() => setConfirming(null));
        }}
      />
      <ConfirmDialog
        open={batchConfirming}
        loading={batchRetrying}
        title={`批量结算 ${selectedItems.length} 条记录？`}
        description="系统会按记录动作逐条执行结算或释放冻结，并复用现有审计流程；只处理等待重试或人工复核记录，不会重新调用上游。"
        confirmLabel="确认批量结算"
        onCancel={() => setBatchConfirming(false)}
        onConfirm={() => void retrySelected().finally(() => setBatchConfirming(false))}
      />
    </section>
  );
}

function canRetry(item: BillingSettlement) {
  return item.status === 'retryable_failed' || item.status === 'manual_review';
}

export async function retrySettlementBatch<T extends { id: string }>(
  items: T[],
  retryOne: (item: T) => Promise<unknown>,
  concurrency = 5,
) {
  const failedIds: string[] = [];
  let succeeded = 0;
  const batchSize = Math.max(1, Math.floor(concurrency));
  for (let index = 0; index < items.length; index += batchSize) {
    const batch = items.slice(index, index + batchSize);
    const results = await Promise.allSettled(batch.map(retryOne));
    results.forEach((result, resultIndex) => {
      if (result.status === 'fulfilled') succeeded += 1;
      else failedIds.push(batch[resultIndex].id);
    });
  }
  return { failedIds, succeeded };
}

function statusLabel(status: string) {
  return ({ pending: '待处理', processing: '处理中', retryable_failed: '等待重试', manual_review: '人工复核', completed: '已完成' } as Record<string, string>)[status] ?? status;
}

function statusVariant(status: string): 'secondary' | 'warning' | 'destructive' | 'success' | 'outline' {
  if (status === 'completed') return 'success';
  if (status === 'manual_review') return 'destructive';
  if (status === 'retryable_failed') return 'warning';
  if (status === 'processing') return 'outline';
  return 'secondary';
}

function formatAmount(value: number) {
  return new Intl.NumberFormat('zh-CN', { minimumFractionDigits: 0, maximumFractionDigits: 9 }).format(value);
}

function retryActionLabel(item: BillingSettlement) {
  if (item.status !== 'manual_review') return '重试';
  if (item.manualReviewReason === 'upstream_submission_unknown' && item.action === 'release') return '确认释放';
  if (item.manualReviewReason === 'historical_success_without_charge' && item.action === 'settle') return '确认结算';
  return '重新入队';
}

function retryActionDescription(item: BillingSettlement) {
  if (item.manualReviewReason === 'upstream_submission_unknown' && item.action === 'release') {
    return '上游提交结果不明。确认后只会释放当前冻结，不会再次调用上游；请先完成外部核查。';
  }
  if (item.manualReviewReason === 'historical_success_without_charge' && item.action === 'settle') {
    return `确认后将按历史快照结算 ${formatAmount(item.amount)} ${item.currency}，不会重新调用上游。`;
  }
  return '确认后会将该记录重新放入结算队列，不会重新调用上游。';
}

function shortId(value: string) {
  return value.length > 12 ? `${value.slice(0, 8)}…${value.slice(-4)}` : value;
}
