/**
 * NumpadSheet 记一笔面板（P3 录入闭环核心）。
 *
 * 金额优先：方向 chip → 大金额 → 账户 chip 行（双腿之一）→ 分类快捷行（另一腿）→ 数字键盘。
 * 「更多」抽屉：日期/摘要/收款方/标签/高级模式（PostingEditor）。
 * 同时服务两种载体：
 * - presentation="page"：/transaction/new 整页宿主（含 editId/draftJson 预填、未保存守卫）
 * - presentation="modal"：全局弹层（NumpadSheetHost，＋按钮唤起）
 * 落账走 buildAndSaveTransaction()/editTransaction，与旧表单完全一致。
 */
import React, { useEffect, useMemo, useRef, useState } from 'react';
import {
  Alert, KeyboardAvoidingView, Platform, Pressable, ScrollView,
  StyleSheet, Switch, Text, TextInput, View,
} from 'react-native';
import { useNavigation, useRouter } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
import { useTheme, createCommonStyles } from '../../theme';
import { useT } from '../../i18n';
import { useLedgerStore } from '../../store/ledgerStore';
import { useMetadataStore } from '../../store/metadataStore';
import { useSettingsStore } from '../../store/settingsStore';
import { TAG_COLORS } from '../../theme/palette';
import { AccountCreateModal } from '../account/AccountCreateModal';
import { BottomSheet } from '../ui/BottomSheet';
import { Button } from '../ui/Button';
import { CategoryIcon } from '../category/CategoryIcon';
import { CategoryPicker } from '../category/CategoryPicker';
import { DatePickerField } from './DatePickerField';
import { NumpadKeyboard } from './NumpadKeyboard';
import { PostingEditor } from '../transaction/PostingEditor';
import { TagPicker } from '../category/TagPicker';
import { pressKey, evaluateExpression, type NumpadKey } from './numpadExpression';
import { useOcrScan } from '../../hooks/useOcrScan';
import { buildAndSaveTransaction, buildPostings } from '../../domain/transaction/transactionBuilder';
import { parsePostingsToLegs } from '../../domain/transaction/postingLegs';
import { serializeTransaction } from '../../domain/core/ledger';
import { addDecimals, compareDecimals, toDateString } from '../../domain/core/decimal';
import { useBottomInset } from '../../hooks/useBottomInset';
import { matchCategory } from '../../domain/taxonomy/categories';
import type { Category } from '../../domain/taxonomy/categories';
import type { Tag } from '../../domain/taxonomy/tags';
import type { Posting } from '../../domain/core/types';
import { logger } from '../../utils/logger';

type Direction = 'expense' | 'income' | 'transfer';

interface NumpadSheetProps {
  presentation?: 'modal' | 'page';
  editId?: string;
  draftJson?: string;
  autoOcr?: boolean;
  onClose?: () => void;
  /** 表单脏状态变化上报（modal 模式宿主用它做未保存守卫）。 */
  onDirtyChange?: (dirty: boolean) => void;
}

export function NumpadSheet({ presentation = 'modal', editId, draftJson, autoOcr, onClose, onDirtyChange }: NumpadSheetProps) {
  const { theme } = useTheme();
  const commonStyles = useMemo(() => createCommonStyles(theme), [theme]);
  const bottomInset = useBottomInset(0);
  const t = useT();
  const router = useRouter();
  const navigation = useNavigation();

  const ledger = useLedgerStore(s => s.ledger);
  const editTransaction = useLedgerStore(s => s.editTransaction);
  const autoOpenAccounts = useLedgerStore(s => s.autoOpenAccounts);
  const categories = useMetadataStore(s => s.categories);
  const tags = useMetadataStore(s => s.tags);
  const lastUsedAccount = useSettingsStore(s => s.lastUsedAccount);
  const lastUsedCategoryId = useSettingsStore(s => s.lastUsedCategoryId);
  const setLastUsedEntry = useSettingsStore(s => s.setLastUsedEntry);

  const [direction, setDirection] = useState<Direction>('expense');
  const [expr, setExpr] = useState('');
  const [currency, setCurrency] = useState('CNY');
  const [date, setDate] = useState(() => toDateString(new Date()));
  const [narration, setNarration] = useState('');
  const [payee, setPayee] = useState('');
  const [sourceAccount, setSourceAccount] = useState('');
  const [targetAccount, setTargetAccount] = useState('');
  const [selectedCategory, setSelectedCategory] = useState<Category | null>(null);
  const [selectedTags, setSelectedTags] = useState<Tag[]>([]);
  const [showMore, setShowMore] = useState(false);
  const [isAdvanced, setIsAdvanced] = useState(false);
  const [postings, setPostings] = useState<Posting[]>([]);
  const [status, setStatus] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [isSubmitted, setIsSubmitted] = useState(false);
  const [accountPicker, setAccountPicker] = useState<'source' | 'target' | null>(null);
  const [categoryPickerOpen, setCategoryPickerOpen] = useState(false);
  const [isQuickAddingAccount, setIsQuickAddingAccount] = useState(false);

  const handleQuickAddAccount = async (values: Record<string, string>) => {
    const typeVal = values.type?.trim();
    const nameVal = values.name?.trim();
    if (!typeVal || !nameVal) {
      Alert.alert(t('account.addFail'), t('account.addFailEmpty'));
      return;
    }
    const rawAccount = `${typeVal}:${nameVal}`;
    let sanitized = rawAccount.replace(/：/g, ':');
    sanitized = sanitized
      .split(':')
      .map((seg, idx) => {
        if (idx === 0) return seg;
        let cleaned = seg.replace(/[()（）[\]]/g, '-');
        cleaned = cleaned.replace(/-+/g, '-');
        cleaned = cleaned.replace(/^-|-$/g, '');
        cleaned = cleaned.replace(/[^\w\u4e00-\u9fa5-]/g, '');
        return cleaned;
      })
      .join(':');

    try {
      await autoOpenAccounts([sanitized]);
      setIsQuickAddingAccount(false);
      if (accountPicker === 'source') {
        setSourceAccount(sanitized);
      } else if (accountPicker === 'target') {
        setTargetAccount(sanitized);
      }
      setAccountPicker(null);
    } catch (e) {
      Alert.alert(t('account.openFail'), e instanceof Error ? e.message : String(e));
    }
  };

  // 编辑模式保留字段
  const [oldRaw, setOldRaw] = useState('');
  const [editFlag, setEditFlag] = useState<string | undefined>(undefined);
  const [editLinks, setEditLinks] = useState<string[] | undefined>(undefined);
  const [editMetadata, setEditMetadata] = useState<Record<string, string> | undefined>(undefined);

  const amount = useMemo(() => evaluateExpression(expr), [expr]);
  const { scan, status: ocrStatus } = useOcrScan();

  // ===== 账户列表（双腿之一的资金账户：Assets + Liabilities） =====
  const assetAccounts = useMemo(() => {
    if (!ledger) return [] as string[];
    return Array.from(ledger.accounts.keys()).filter(
      a => a.startsWith('Assets') || a.startsWith('Liabilities'),
    );
  }, [ledger]);

  // chip 行：上次使用优先，最多 4 个 + 「⋯」
  const chipAccounts = useMemo(() => {
    const rest = assetAccounts.filter(a => a !== lastUsedAccount);
    const pinned = lastUsedAccount && assetAccounts.includes(lastUsedAccount) ? [lastUsedAccount] : [];
    return [...pinned, ...rest].slice(0, 4);
  }, [assetAccounts, lastUsedAccount]);

  // 默认资金账户：上次使用 > 列表第一个
  useEffect(() => {
    if (sourceAccount) return;
    const def = lastUsedAccount && assetAccounts.includes(lastUsedAccount)
      ? lastUsedAccount
      : assetAccounts[0];
    if (def) setSourceAccount(def);
  }, [assetAccounts, lastUsedAccount, sourceAccount]);

  // ===== 分类快捷行 =====
  const availableCategories = useMemo(
    () => categories.filter(c => c.type === (direction === 'income' ? 'income' : 'expense')),
    [categories, direction],
  );
  const quickCategories = useMemo(() => {
    const pinned = availableCategories.find(c => c.id === lastUsedCategoryId);
    const rest = availableCategories.filter(c => c.id !== lastUsedCategoryId);
    return [...(pinned ? [pinned] : []), ...rest].slice(0, 3);
  }, [availableCategories, lastUsedCategoryId]);

  const parsedOriginalDraftRef = useRef<{ payee?: string; categoryAccount?: string; sourceAccount?: string; amount?: string; direction?: string } | null>(null);

  // ===== 预填：draftJson（草稿） =====
  useEffect(() => {
    if (!draftJson) return;
    try {
      const draft = JSON.parse(draftJson);
      if (draft.date) setDate(String(draft.date).slice(0, 10));
      setNarration(draft.narration || '');
      setPayee(draft.payee || '');
      const legs = parsePostingsToLegs(draft.postings ?? []);
      if (legs) {
        setDirection(legs.direction);
        setExpr(legs.amount);
        setCurrency(legs.currency);
        setSourceAccount(legs.sourceAccount);
        setTargetAccount(legs.targetAccount);
        if (legs.direction !== 'transfer') {
          const matched = categories.find(c => c.linkedAccount === legs.targetAccount);
          if (matched) setSelectedCategory(matched);
        }
      }
      parsedOriginalDraftRef.current = {
        payee: (draft.payee || '').trim(),
        categoryAccount: legs?.targetAccount || '',
        sourceAccount: legs?.sourceAccount || '',
        amount: legs?.amount || '',
        direction: legs?.direction || 'expense',
      };
      if (Array.isArray(draft.postings) && draft.postings.length > 0) {
        setPostings((draft.postings as Posting[]).map((p) => ({
          account: p.account, amount: p.amount, currency: p.currency,
          cost: p.cost, price: p.price, metadata: p.metadata,
        })));
        // 带 cost/price/metadata 的分录在简单模式会丢失 → 进高级模式
        const hasExtras = (draft.postings as Posting[]).some(
          (p: Posting) => p.cost || p.price || (p.metadata && Object.keys(p.metadata).length > 0),
        );
        // 无法双腿解析（拆分交易等）→ 直接进高级模式，避免丢腿
        if (!legs || hasExtras) setIsAdvanced(true);
      }
      // 标签预填（与 editId 预填同逻辑：store 按 name 查找，找不到用兜底色）
      if (Array.isArray(draft.tags) && draft.tags.length > 0) {
        setSelectedTags(draft.tags.map((name: string) => {
          const found = tags.find(tg => tg.name === name);
          return found ?? { id: name, name, color: TAG_COLORS[3] };
        }));
      }
    } catch (e) {
      console.error('Failed to parse draftJson', e);
    }
  }, [draftJson, categories, tags]);

  // ===== 预填：editId（编辑模式） =====
  const editingTx = useMemo(
    () => (editId ? ledger?.transactions.find(txn => txn.id === editId) : undefined),
    [editId, ledger],
  );
  useEffect(() => {
    if (!editingTx) return;
    setOldRaw(editingTx.raw);
    setDate(editingTx.date.slice(0, 10));
    setNarration(editingTx.narration || '');
    setPayee(editingTx.payee || '');
    setEditFlag(editingTx.flag || '*');
    setEditLinks(editingTx.links || []);
    setEditMetadata(editingTx.metadata);
    const legs = parsePostingsToLegs(editingTx.postings);
    if (legs) {
      setDirection(legs.direction);
      setExpr(legs.amount);
      setCurrency(legs.currency);
      setSourceAccount(legs.sourceAccount);
      setTargetAccount(legs.targetAccount);
      if (legs.direction !== 'transfer') {
        const matched = categories.find(c => c.linkedAccount === legs.targetAccount);
        if (matched) setSelectedCategory(matched);
      }
    }
    setPostings(editingTx.postings.map(p => ({
      account: p.account, amount: p.amount, currency: p.currency,
      cost: p.cost, price: p.price, metadata: p.metadata,
    })));
    // 带 cost/price/metadata 的分录在简单模式会丢失 → 进高级模式
    const hasExtras = editingTx.postings.some(
      p => p.cost || p.price || (p.metadata && Object.keys(p.metadata).length > 0),
    );
    // 无法双腿解析（拆分交易等）→ 直接进高级模式，避免丢腿
    if ((!legs || hasExtras) && editingTx.postings.length > 0) setIsAdvanced(true);
    if (editingTx.tags.length > 0) {
      setSelectedTags(editingTx.tags.map(name => {
        const found = tags.find(tg => tg.name === name);
        return found ?? { id: name, name, color: TAG_COLORS[3] };
      }));
    }
  }, [editingTx, categories, tags]);

  // ===== OCR =====
  const applyOcrEvent = (event: import('../../hooks/useOcrScan').OcrEvent) => {
    // 金额/摘要仅在当前为空时填充，避免覆盖用户已输入内容
    if (event.amount) setExpr(prev => prev || event.amount!.replace(/^-/, ''));
    if (event.direction === 'income' || event.direction === 'transfer') setDirection(event.direction);
    else setDirection('expense');
    const text = [event.counterparty, event.memo].filter(Boolean).join(' - ');
    if (text) setNarration(prev => prev || text);
    const matchText = [event.counterparty, event.memo].filter(Boolean).join(' ');
    if (matchText) {
      const type = event.direction === 'income' ? 'income' : 'expense';
      const match = matchCategory(matchText, categories.filter(c => c.type === type));
      if (match.category) setSelectedCategory(match.category);
    }
  };
  const handleOcr = async () => {
    const event = await scan();
    if (event) applyOcrEvent(event);
  };
  useEffect(() => {
    if (autoOcr) handleOcr();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [autoOcr]);

  // ===== 未保存守卫 =====
  const initialSnapshotRef = useRef<{ expr: string; narration: string; payee: string; tags: string[] } | null>(null);
  useEffect(() => {
    if (editingTx) {
      const legs = parsePostingsToLegs(editingTx.postings);
      initialSnapshotRef.current = {
        expr: legs?.amount || '',
        narration: editingTx.narration || '',
        payee: editingTx.payee || '',
        tags: editingTx.tags || [],
      };
    } else if (draftJson) {
      try {
        const draft = JSON.parse(draftJson);
        const legs = parsePostingsToLegs(draft.postings ?? []);
        initialSnapshotRef.current = {
          expr: legs?.amount || '',
          narration: draft.narration || '',
          payee: draft.payee || '',
          tags: Array.isArray(draft.tags) ? draft.tags : [],
        };
      } catch { /* intentionally empty */ }
    }
  }, [editingTx, draftJson]);

  const formRef = useRef({ expr, narration, payee, selectedTags, isAdvanced, postings, isSubmitted });
  formRef.current = { expr, narration, payee, selectedTags, isAdvanced, postings, isSubmitted };
  // 脏状态计算（读 formRef，整页守卫与 modal 宿主共用）
  const computeDirty = () => {
    const s = formRef.current;
    if (s.isSubmitted) return false;
    const init = initialSnapshotRef.current;
    if (init) {
      const tagsChanged = JSON.stringify(s.selectedTags.map(t => t.name).sort()) !== JSON.stringify([...init.tags].sort());
      return (
        evaluateExpression(s.expr) !== evaluateExpression(init.expr) ||
        s.narration.trim() !== init.narration.trim() ||
        s.payee.trim() !== init.payee.trim() ||
        tagsChanged
      );
    }
    return (
      evaluateExpression(s.expr) !== '' ||
      s.narration.trim() !== '' ||
      s.payee.trim() !== '' ||
      s.selectedTags.length > 0 ||
      (s.isAdvanced && s.postings.some(p => p.account.trim() !== '' || (p.amount || '').trim() !== ''))
    );
  };
  // modal 模式：每次渲染后把脏状态上报给宿主（Host 的遮罩/返回键守卫用）
  useEffect(() => {
    onDirtyChange?.(computeDirty());
  });
  // 整页模式：beforeRemove 守卫
  useEffect(() => {
    if (presentation !== 'page') return;
    const unsubscribe = navigation.addListener('beforeRemove', (e) => {
      if (!computeDirty()) return;
      e.preventDefault();
      Alert.alert(t('transaction.unsavedTitle'), t('transaction.unsavedMessage'), [
        { text: t('common.cancel'), style: 'cancel', onPress: () => {} },
        { text: t('common.discard'), style: 'destructive', onPress: () => navigation.dispatch(e.data.action) },
      ]);
    });
    return unsubscribe;
     
  }, [navigation, presentation, t]);

  // ===== 键盘 =====
  const handleKey = (key: string) => {
    if (key === 'done') { submit(); return; }
    if (key === 'today') { setDate(toDateString(new Date())); return; }
    setExpr(prev => pressKey(prev, key as NumpadKey));
  };

  const swapAccounts = () => {
    const s = sourceAccount;
    setSourceAccount(targetAccount);
    setTargetAccount(s);
  };

  const closeSoon = () => {
    onClose?.();
  };

  // modal 工具行关闭按钮：脏数据时先确认（提交成功走 closeSoon 直关，isSubmitted 已置位不会误拦）
  const requestModalClose = () => {
    if (!computeDirty()) { onClose?.(); return; }
    Alert.alert(t('transaction.unsavedTitle'), t('transaction.unsavedMessage'), [
      { text: t('common.cancel'), style: 'cancel', onPress: () => {} },
      { text: t('common.discard'), style: 'destructive', onPress: () => onClose?.() },
    ]);
  };

  // ===== 提交 =====
  const submit = async () => {
    if (submitting || isSubmitted) return;
    setSubmitting(true);
    const tagNames = selectedTags.map(tg => tg.name);
    try {
      if (isAdvanced) {
        // ===== 高级模式：多行分录 =====
        const validPostings = postings.filter(p => p.account.trim());
        if (validPostings.length < 2) { setStatus(t('transaction.atLeast2Postings')); return; }
        const currencySum: Record<string, string[]> = {};
        for (const p of validPostings) {
          if (p.amount && p.currency) {
            (currencySum[p.currency] = currencySum[p.currency] || []).push(p.amount);
          }
        }
        const balanced = Object.values(currencySum).every(amounts => compareDecimals(addDecimals(amounts), '0') === 0);
        if (!balanced) { setStatus(t('transaction.unbalanced')); return; }
        const draft = {
          date,
          flag: editId ? editFlag : undefined,
          narration: narration.trim() || t('transaction.defaultAdvancedNarration'),
          postings: validPostings,
          tags: tagNames,
          links: editId && editLinks && editLinks.length > 0 ? editLinks : undefined,
          metadata: editId ? editMetadata : undefined,
        };
        if (editId && oldRaw) {
          await editTransaction(oldRaw, serializeTransaction(draft));
          setStatus(t('transaction.editSuccess'));
        } else {
          await useLedgerStore.getState().addTransaction(draft);
          setStatus(t('transaction.appended'));
        }
        setIsSubmitted(true);
        closeSoon();
        return;
      }

      // ===== 简单模式：双腿 =====
      const amt = amount;
      if (!amt || compareDecimals(amt, '0') <= 0) { setStatus(t('transaction.amountRequired')); return; }
      if (!sourceAccount) { setStatus(t('numpad.noAccount')); return; }
      if (direction === 'transfer' && sourceAccount === targetAccount) {
        setStatus(t('transaction.sameAccountError'));
        return;
      }
      // 转账双方必须是资金/负债账户，防止分类账户污染目标腿
      if (direction === 'transfer') {
        const notAssetLike = (a: string) => !a.startsWith('Assets') && !a.startsWith('Liabilities');
        if (notAssetLike(sourceAccount) || notAssetLike(targetAccount)) {
          setStatus(t('numpad.transferTargetError'));
          return;
        }
      }
      const categoryAccount = direction === 'transfer'
        ? targetAccount
        : selectedCategory?.linkedAccount ?? (direction === 'income' ? 'Income:未分类' : 'Expenses:未分类');
      const defaultNarration =
        direction === 'expense' ? t('transaction.narrationDefaultExpense') :
        direction === 'income' ? t('transaction.narrationDefaultIncome') :
        t('transaction.narrationDefaultTransfer');

      if (editId && oldRaw) {
        const draft = {
          date,
          payee: payee.trim() || undefined,
          flag: editFlag,
          narration: narration.trim() || defaultNarration,
          postings: buildPostings(direction, sourceAccount, categoryAccount, amt, currency),
          tags: tagNames,
          links: editLinks && editLinks.length > 0 ? editLinks : undefined,
          metadata: editMetadata,
        };
        await editTransaction(oldRaw, serializeTransaction(draft));
        setStatus(t('transaction.editSuccess'));
        setIsSubmitted(true);
        closeSoon();
      } else {
        if (parsedOriginalDraftRef.current) {
          const orig = parsedOriginalDraftRef.current;
          const userPayee = payee.trim();
          const userCategory = categoryAccount;
          const userSource = sourceAccount;
          const userAmount = amt;
          const userDirection = direction;

          const isCategoryChanged = userCategory !== orig.categoryAccount;
          const isPayeeChanged = userPayee !== orig.payee;
          const isAmountChanged = userAmount !== orig.amount;
          const isSourceChanged = userSource !== orig.sourceAccount;
          const isDirectionChanged = userDirection !== orig.direction;

          if (isCategoryChanged || isPayeeChanged || isAmountChanged || isSourceChanged || isDirectionChanged) {
            logger.info('userCorrection', `[用户修正草稿记账] 预填推荐 vs 用户手动修正:`, {
              original: { payee: orig.payee, category: orig.categoryAccount, sourceAccount: orig.sourceAccount, amount: orig.amount, direction: orig.direction },
              corrected: { payee: userPayee, category: userCategory, sourceAccount: userSource, amount: userAmount, direction: userDirection },
              changes: { categoryChanged: isCategoryChanged, payeeChanged: isPayeeChanged, amountChanged: isAmountChanged, sourceChanged: isSourceChanged, directionChanged: isDirectionChanged },
            });
          }
        }

        await buildAndSaveTransaction({
          date,
          amount: amt,
          payee: payee.trim() || undefined,
          narration: narration.trim() || defaultNarration,
          categoryAccount,
          sourceAccount,
          direction,
          currency,
          tags: tagNames,
        }, useLedgerStore.getState());
        setLastUsedEntry(sourceAccount || null, direction === 'transfer' ? lastUsedCategoryId : (selectedCategory?.id ?? null));
        setStatus(t('transaction.appended'));
        setIsSubmitted(true);
        setExpr('');
        setNarration('');
        setSelectedCategory(null);
        setSelectedTags([]);
        closeSoon();
      }
    } catch (e) {
      setStatus(String(e instanceof Error ? e.message : e));
    } finally {
      setSubmitting(false);
    }
  };

  // ===== 高级模式切换时初始化分录 =====
  const toggleAdvanced = (val: boolean) => {
    setIsAdvanced(val);
    if (val) {
      const amt = amount;
      const categoryAccount = direction === 'transfer'
        ? targetAccount
        : selectedCategory?.linkedAccount ?? (direction === 'income' ? 'Income:未分类' : 'Expenses:未分类');
      setPostings(buildPostings(direction, sourceAccount, categoryAccount, amt || '0', currency)
        .map(p => ({ ...p, amount: p.amount === '-0' || p.amount === '0' ? '' : p.amount })));
    }
  };

  const directions: { key: Direction; label: string }[] = [
    { key: 'expense', label: t('transaction.directionExpense') },
    { key: 'income', label: t('transaction.directionIncome') },
    { key: 'transfer', label: t('transaction.directionTransfer') },
  ];

  const shortName = (acct: string) => acct.split(':').pop() || acct;
  const previewTarget = direction === 'transfer'
    ? targetAccount
    : selectedCategory?.linkedAccount ?? '';

  const renderAccountRow = (label: string, value: string, onSelect: (a: string) => void, pickerKey: 'source' | 'target') => (
    <View style={styles.accountRow}>
      <Text style={[theme.typography.caption, styles.accountLabel, { color: theme.colors.fgSecondary }]}>{label}</Text>
      <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.accountChips}>
        {assetAccounts.length === 0 ? (
          <Pressable
            onPress={() => {
              // 复用「⋯更多→新建账户」的快捷创建流程（AccountCreateModal），
              // 避免整页路由跳转导致表单状态丢失。setAccountPicker 让
              // handleQuickAddAccount 知道新建后回填到 source/target 哪条腿。
              setAccountPicker(pickerKey);
              setIsQuickAddingAccount(true);
            }}
            style={commonStyles.chip}
          >
            <Text style={[commonStyles.chipText, { color: theme.colors.accent }]}>{t('numpad.noAccount')}</Text>
          </Pressable>
        ) : (
          <>
            {chipAccounts.map(acct => {
              const active = value === acct;
              return (
                <Pressable
                  key={`${pickerKey}-${acct}`}
                  onPress={() => onSelect(acct)}
                  style={[commonStyles.chip, active && commonStyles.chipActive]}
                >
                  <Text style={[commonStyles.chipText, active && commonStyles.chipTextActive]}>{shortName(acct)}</Text>
                </Pressable>
              );
            })}
            <Pressable onPress={() => setAccountPicker(pickerKey)} style={commonStyles.chip}>
              <Text style={[commonStyles.chipText, { color: theme.colors.fgSecondary }]}>⋯</Text>
            </Pressable>
          </>
        )}
      </ScrollView>
    </View>
  );

  return (
    <KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'} style={presentation === 'page' ? styles.flex1 : undefined}>
      <View style={[
        styles.sheet,
        presentation === 'modal' && {
          backgroundColor: theme.colors.bgSecondary,
          borderTopLeftRadius: theme.radii.xl,
          borderTopRightRadius: theme.radii.xl,
        },
        presentation === 'page' && { backgroundColor: theme.colors.bgPrimary },
      ]}>
        <ScrollView keyboardShouldPersistTaps="handled" contentContainerStyle={[styles.content, { paddingBottom: Math.max(bottomInset, 24) }]}>
          {/* 工具行 */}
          <View style={styles.toolRow}>
            {presentation === 'modal' ? (
              <Pressable onPress={requestModalClose} hitSlop={8} accessibilityRole="button" accessibilityLabel={t('numpad.close')}>
                <Ionicons name="chevron-down" size={24} color={theme.colors.fgSecondary} />
              </Pressable>
            ) : null}
            <View style={styles.flex1} />
            <Pressable onPress={handleOcr} hitSlop={8} accessibilityRole="button" accessibilityLabel={t('home.ocrScan')}>
              <Ionicons name="camera-outline" size={22} color={theme.colors.fgSecondary} />
            </Pressable>
            {presentation === 'page' ? (
              <Pressable onPress={() => router.push('/import')} hitSlop={8} accessibilityRole="button" accessibilityLabel={t('tab.import')} style={{ marginLeft: 16 }}>
                <Ionicons name="download-outline" size={22} color={theme.colors.fgSecondary} />
              </Pressable>
            ) : null}
          </View>

          {/* 方向 */}
          <View style={styles.directionRow}>
            {directions.map(d => (
              <Pressable
                key={d.key}
                onPress={() => {
                  setDirection(d.key);
                  setSelectedCategory(null);
                  // 切到转账时清掉非资金/负债的目标账户，避免分类账户污染转账腿
                  if (d.key === 'transfer' && targetAccount
                    && !targetAccount.startsWith('Assets') && !targetAccount.startsWith('Liabilities')) {
                    setTargetAccount('');
                  }
                }}
                style={[commonStyles.chip, direction === d.key && commonStyles.chipActive, styles.directionChip]}
              >
                <Text style={[commonStyles.chipText, direction === d.key && commonStyles.chipTextActive]}>{d.label}</Text>
              </Pressable>
            ))}
          </View>

          {/* 金额 */}
          <Text style={[theme.typography.display, styles.amount, { color: theme.colors.fgPrimary }]} numberOfLines={1}>
            ¥ {amount || '0'}
          </Text>

          {/* 账户行（双腿之一） */}
          {direction === 'transfer' ? (
            <>
              {renderAccountRow(t('numpad.outFrom'), sourceAccount, setSourceAccount, 'source')}
              <Pressable onPress={swapAccounts} style={styles.swapBtn} accessibilityRole="button" accessibilityLabel={t('numpad.swap')}>
                <Ionicons name="swap-vertical" size={18} color={theme.colors.fgSecondary} />
              </Pressable>
              {renderAccountRow(t('numpad.transferTo'), targetAccount, setTargetAccount, 'target')}
            </>
          ) : (
            renderAccountRow(direction === 'income' ? t('numpad.to') : t('numpad.from'), sourceAccount, setSourceAccount, 'source')
          )}

          {/* 分类快捷行（另一腿，非转账） */}
          {direction !== 'transfer' && (
            <View style={styles.categoryRow}>
              {quickCategories.map(cat => {
                const active = selectedCategory?.id === cat.id;
                return (
                  <Pressable
                    key={cat.id}
                    onPress={() => setSelectedCategory(active ? null : cat)}
                    style={[styles.categoryCell, {
                      backgroundColor: active ? theme.colors.accentLight : theme.colors.bgTertiary,
                      borderColor: active ? theme.colors.accent : 'transparent',
                      borderRadius: theme.radii.md,
                    }]}
                  >
                    <CategoryIcon categoryId={cat.id} size={28} />
                    <Text style={[theme.typography.caption, { color: theme.colors.fgPrimary }]} numberOfLines={1}>{cat.name}</Text>
                  </Pressable>
                );
              })}
              <Pressable
                onPress={() => setCategoryPickerOpen(true)}
                style={[styles.categoryCell, { backgroundColor: theme.colors.bgTertiary, borderColor: 'transparent', borderRadius: theme.radii.md }]}
              >
                <Ionicons name="grid-outline" size={22} color={theme.colors.fgSecondary} />
                <Text style={[theme.typography.caption, { color: theme.colors.fgSecondary }]}>{t('numpad.allCategories')}</Text>
              </Pressable>
            </View>
          )}

          {/* 数字键盘（简单模式） */}
          {!isAdvanced && (
            <NumpadKeyboard onKey={handleKey} todayLabel={t('numpad.today')} doneLabel={t('numpad.done')} backspaceLabel={t('numpad.backspace')} />
          )}

          {/* 分录预览（常驻小字） */}
          {!isAdvanced && amount && sourceAccount && previewTarget ? (
            <Text style={[theme.typography.caption, styles.preview, { color: theme.colors.fgSecondary }]} numberOfLines={1}>
              {shortName(sourceAccount)} → {shortName(previewTarget)} · ¥{amount} · {date}
            </Text>
          ) : null}

          {/* 更多抽屉 */}
          <Pressable onPress={() => setShowMore(v => !v)} style={styles.moreToggle} accessibilityRole="button">
            <Text style={[theme.typography.bodySmall, { color: theme.colors.accent, fontWeight: '700' }]}>
              {showMore ? t('numpad.less') : t('numpad.more')}
            </Text>
            <Ionicons name={showMore ? 'chevron-up-outline' : 'chevron-down-outline'} size={16} color={theme.colors.accent} />
          </Pressable>

          {showMore && (
            <View style={styles.moreSection}>
              <Text style={[theme.typography.caption, { color: theme.colors.fgSecondary }]}>{t('transaction.formDate')}</Text>
              <DatePickerField value={date} onChange={setDate} />

              <Text style={[theme.typography.caption, styles.fieldGap, { color: theme.colors.fgSecondary }]}>{t('transaction.formCurrency')}</Text>
              <TextInput
                value={currency}
                onChangeText={setCurrency}
                autoCapitalize="characters"
                maxLength={8}
                placeholderTextColor={theme.colors.fgSecondary}
                style={commonStyles.input}
              />

              <Text style={[theme.typography.caption, styles.fieldGap, { color: theme.colors.fgSecondary }]}>{t('transaction.formNarration')}</Text>
              <TextInput
                value={narration}
                onChangeText={setNarration}
                placeholder={t('transaction.formNarration')}
                placeholderTextColor={theme.colors.fgSecondary}
                style={commonStyles.input}
              />

              <Text style={[theme.typography.caption, styles.fieldGap, { color: theme.colors.fgSecondary }]}>{t('transaction.formPayee')}</Text>
              <TextInput
                value={payee}
                onChangeText={setPayee}
                placeholder={t('transaction.formPayeePlaceholder')}
                placeholderTextColor={theme.colors.fgSecondary}
                style={commonStyles.input}
              />

              <Text style={[theme.typography.caption, styles.fieldGap, { color: theme.colors.fgSecondary }]}>{t('transaction.formTags')}</Text>
              <TagPicker
                tags={tags}
                selectedNames={selectedTags.map(tg => tg.name)}
                onToggle={(tag) => setSelectedTags(prev =>
                  prev.some(x => x.name === tag.name) ? prev.filter(x => x.name !== tag.name) : [...prev, tag],
                )}
              />

              {/* 高级模式 */}
              <View style={[commonStyles.switchRow, styles.advancedRow]}>
                <Text style={[theme.typography.body, { color: theme.colors.fgPrimary, fontWeight: '700' }]}>
                  {t('numpad.advanced')}
                </Text>
                <Switch
                  value={isAdvanced}
                  onValueChange={toggleAdvanced}
                  trackColor={{ false: theme.colors.bgTertiary, true: theme.colors.accent }}
                  thumbColor={theme.colors.fgInverse}
                />
              </View>
            </View>
          )}

          {/* 高级模式分录编辑器 */}
          {isAdvanced && (
            <View style={styles.advancedSection}>
              <PostingEditor postings={postings} onChange={setPostings} />
              <View style={styles.postingBtnRow}>
                <View style={styles.flex1}>
                  <Button label={t('transaction.addPosting')} onPress={() => setPostings([...postings, { account: '', amount: '', currency }])} variant="secondary" />
                </View>
                <View style={styles.flex1}>
                  <Button label={t('transaction.deleteLastPosting')} onPress={() => postings.length > 2 && setPostings(postings.slice(0, -1))} variant="secondary" />
                </View>
              </View>
              <Button label={t('transaction.submit')} onPress={submit} disabled={submitting || isSubmitted} />
            </View>
          )}

          {status || ocrStatus ? (
            <Text style={[theme.typography.bodySmall, styles.status, { color: theme.colors.fgSecondary }]}>{status || ocrStatus}</Text>
          ) : null}
        </ScrollView>

        {/* 全部账户 BottomSheet */}
        <BottomSheet visible={accountPicker !== null} onClose={() => setAccountPicker(null)} title={t('numpad.allAccounts')}>
          <ScrollView style={styles.accountList}>
            <Pressable
              onPress={() => setIsQuickAddingAccount(true)}
              style={[styles.accountListItem, { borderBottomColor: theme.colors.divider, flexDirection: 'row', alignItems: 'center' }]}
            >
              <Ionicons name="add-circle-outline" size={20} color={theme.colors.accent} />
              <Text style={[theme.typography.body, { color: theme.colors.accent, fontWeight: '700', marginLeft: 6 }]}>
                {t('account.addNew')}
              </Text>
            </Pressable>
            {assetAccounts.map(acct => (
              <Pressable
                key={acct}
                onPress={() => {
                  if (accountPicker === 'source') setSourceAccount(acct);
                  else if (accountPicker === 'target') setTargetAccount(acct);
                  setAccountPicker(null);
                }}
                style={[styles.accountListItem, { borderBottomColor: theme.colors.divider }]}
              >
                <Text style={[theme.typography.body, { color: theme.colors.fgPrimary }]}>{acct}</Text>
              </Pressable>
            ))}
          </ScrollView>
        </BottomSheet>

        {/* 快捷新建账户 AccountCreateModal (全应用 100% 统一复用) */}
        <AccountCreateModal
          visible={isQuickAddingAccount}
          defaultType="Assets"
          onConfirm={handleQuickAddAccount}
          onCancel={() => setIsQuickAddingAccount(false)}
        />

        {/* 全部分类 BottomSheet */}
        <BottomSheet visible={categoryPickerOpen} onClose={() => setCategoryPickerOpen(false)} title={direction === 'income' ? t('transaction.formCategoryIncome') : t('transaction.formCategoryExpense')}>
          <ScrollView style={styles.accountList}>
            <CategoryPicker
              categories={availableCategories}
              selectedId={selectedCategory?.id}
              onSelect={(cat) => { setSelectedCategory(cat); setCategoryPickerOpen(false); }}
            />
          </ScrollView>
        </BottomSheet>
      </View>
    </KeyboardAvoidingView>
  );
}

const styles = StyleSheet.create({
  flex1: { flex: 1 },
  sheet: { maxHeight: '100%' },
  content: { paddingHorizontal: 16, paddingBottom: 24 },
  toolRow: { flexDirection: 'row', alignItems: 'center', paddingVertical: 8 },
  directionRow: { flexDirection: 'row', gap: 8, marginBottom: 4 },
  directionChip: { flex: 1, alignItems: 'center' },
  amount: { textAlign: 'right', paddingVertical: 8, fontVariant: ['tabular-nums'] },
  accountRow: { flexDirection: 'row', alignItems: 'center', marginTop: 4 },
  accountLabel: { width: 34 },
  accountChips: { gap: 6, paddingRight: 8 },
  swapBtn: { alignSelf: 'center', padding: 4 },
  categoryRow: { flexDirection: 'row', gap: 6, marginTop: 10, marginBottom: 6 },
  categoryCell: { flex: 1, alignItems: 'center', justifyContent: 'center', paddingVertical: 8, gap: 4, borderWidth: 1.5 },
  preview: { textAlign: 'center', marginTop: 6 },
  moreToggle: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 4, paddingVertical: 10 },
  moreSection: { gap: 4 },
  fieldGap: { marginTop: 10, marginBottom: 4 },
  advancedRow: { marginTop: 14 },
  advancedSection: { marginTop: 8, gap: 8 },
  postingBtnRow: { flexDirection: 'row', gap: 8 },
  status: { textAlign: 'center', marginTop: 8 },
  accountList: { maxHeight: 360 },
  accountListItem: { paddingVertical: 12, borderBottomWidth: StyleSheet.hairlineWidth },
});
