/**
 * 通用模态表单（plan.md 管理页 CRUD）。
 *
 * 底部弹出的模态对话框,包含多个文本输入字段 + 确认/取消按钮。
 * 供分类/标签/预算/信用卡/规则管理页的「添加/编辑」复用。
 *
 * 用法:
 * <FormModal
 *   visible={true}
 *   title="添加分类"
 *   fields={[
 *     { key: 'name', label: '名称', placeholder: '餐饮' },
 *     { key: 'linkedAccount', label: '关联账户', placeholder: 'Expenses:餐饮' },
 *   ]}
 *   initialValues={{ name: '', linkedAccount: '' }}
 *   onConfirm={(values) => { /* 保存 *\/ }}
 *   onCancel={() => { /* 关闭 *\/ }}
 * />
 */

import React, { useEffect, useMemo, useState } from 'react';
import { Modal, Pressable, ScrollView, StyleSheet, Text, TextInput, View } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { useTheme, createCommonStyles } from '../theme';
import { useT } from '../i18n';
import { Button } from './Button';
import { Touchable } from './Touchable';

export interface FormOption {
  label: string;      // 中文名称
  value: string;      // 英文前缀 (如 Assets)
  subLabel?: string;
}

export interface FormField {
  /** 字段 key,对应 values 对象的属性名。 */
  key: string;
  /** 显示标签。 */
  label: string;
  /** 占位提示。 */
  placeholder?: string;
  /** 默认值(新增时为空,编辑时预填)。 */
  defaultValue?: string;
  /** 键盘类型。 */
  keyboardType?: 'default' | 'numeric' | 'decimal-pad' | 'phone-pad';
  /** 多行输入。 */
  multiline?: boolean;
  /** 密码输入（遮蔽文本）。 */
  secureTextEntry?: boolean;
  /** 控件类型：'text' (默认) | 'select' 单选卡片组 | 'dropdown' 下拉选择框 */
  type?: 'text' | 'select' | 'dropdown';
  /** select / dropdown 类型的可选项。 */
  options?: FormOption[];
  /** 在同一行内布局时的占比弹性系数。 */
  flex?: number;
  /** 行号标识，相同 row 的字段组合在同一行中。 */
  row?: number;
}

interface FormModalProps {
  visible: boolean;
  title: string;
  fields: FormField[];
  onConfirm: (values: Record<string, string>) => void;
  onCancel: () => void;
  /** 确认按钮文本(默认「确定」)。 */
  confirmLabel?: string;
  /** 字段值变更时的联动回调，返回新值覆盖。 */
  onValuesChange?: (changedKey: string, newValue: string, prevValues: Record<string, string>) => Record<string, string> | void;
  /** 可选自定义内容（渲染在字段与按钮之间，如颜色选择器）。 */
  children?: React.ReactNode;
}

export function FormModal({ visible, title, fields, onConfirm, onCancel, confirmLabel, onValuesChange, children }: FormModalProps) {
  const { theme } = useTheme();
  const t = useT();
  const commonStyles = useMemo(() => createCommonStyles(theme), [theme]);
  const [values, setValues] = useState<Record<string, string>>({});
  const [activeDropdownKey, setActiveDropdownKey] = useState<string | null>(null);
  const [focusedKey, setFocusedKey] = useState<string | null>(null);

  const updateFieldValue = (key: string, val: string) => {
    setValues(prev => {
      const next = { ...prev, [key]: val };
      if (onValuesChange) {
        const overridden = onValuesChange(key, val, next);
        return overridden ? { ...next, ...overridden } : next;
      }
      return next;
    });
  };

  // 每次 visible 变为 true 时,用 fields 的 defaultValue 初始化
  useEffect(() => {
    if (visible) {
      const init: Record<string, string> = {};
      for (const f of fields) {
        init[f.key] = f.defaultValue ?? '';
      }
      setValues(init);
      setActiveDropdownKey(null);
      setFocusedKey(null);
    }
  }, [visible]); // eslint-disable-line react-hooks/exhaustive-deps

  // 将包含 flex 的连续字段组合成同行渲染组
  const renderField = (f: FormField) => {
    const isFocused = focusedKey === f.key || activeDropdownKey === f.key;

    if (f.type === 'dropdown' && f.options) {
      const selectedOpt = f.options.find(o => o.value === (values[f.key] ?? ''));
      const rawValue = selectedOpt ? selectedOpt.value : (values[f.key] ?? '');
      const rawLabel = selectedOpt ? selectedOpt.label : '';

      const hasColon = rawValue.includes(':');
      const triggerPrefix = hasColon ? rawValue.slice(0, rawValue.lastIndexOf(':')) : '';
      const triggerTitle = hasColon ? rawValue.slice(rawValue.lastIndexOf(':') + 1) : (rawLabel || f.placeholder || '');
      const isPlaceholder = !rawValue;

      return (
        <View key={f.key} style={[styles.field, f.flex ? { flex: f.flex } : undefined]}>
          <Text style={[theme.typography.caption, styles.fieldLabel, { color: theme.colors.fgSecondary }]}>
            {f.label}
          </Text>
          <Touchable
            style={[
              commonStyles.input,
              styles.dropdownTrigger,
              {
                borderColor: isFocused ? theme.colors.accent : theme.colors.border,
                backgroundColor: isFocused ? theme.colors.bgPrimary : theme.colors.bgTertiary,
                borderWidth: isFocused ? 1.5 : StyleSheet.hairlineWidth,
              },
            ]}
            onPress={() => setActiveDropdownKey(f.key)}
          >
            <View style={styles.dropdownTriggerContent}>
              {triggerPrefix ? (
                <Text style={[styles.dropdownValueText, { color: theme.colors.fgSecondary, fontSize: 10, lineHeight: 12 }]} numberOfLines={1}>
                  {triggerPrefix}
                </Text>
              ) : null}
              <Text
                style={[
                  styles.dropdownLabelText,
                  {
                    color: isPlaceholder ? theme.colors.fgSecondary : theme.colors.fgPrimary,
                    fontSize: 13,
                    fontWeight: isPlaceholder ? '400' : '600',
                    lineHeight: 16,
                  },
                ]}
                numberOfLines={1}
              >
                {triggerTitle}
              </Text>
            </View>
            <Ionicons name="chevron-down" size={16} color={isFocused ? theme.colors.accent : theme.colors.fgSecondary} />
          </Touchable>
        </View>
      );
    }

    if (f.type === 'select' && f.options) {
      return (
        <View key={f.key} style={[styles.field, f.flex ? { flex: f.flex } : undefined]}>
          <Text style={[theme.typography.caption, styles.fieldLabel, { color: theme.colors.fgSecondary }]}>
            {f.label}
          </Text>
          <View style={styles.optionContainer}>
            {f.options.map(opt => {
              const isSelected = (values[f.key] ?? '') === opt.value;
              return (
                <Touchable
                  key={opt.value}
                  style={[
                    styles.optionChip,
                    {
                      backgroundColor: isSelected ? `${theme.colors.accent}15` : theme.colors.bgPrimary,
                      borderColor: isSelected ? theme.colors.accent : theme.colors.border,
                    },
                  ]}
                  onPress={() => updateFieldValue(f.key, opt.value)}
                >
                  <View style={styles.optionTextWrap}>
                    <Text style={[styles.dropdownValueText, { color: theme.colors.fgSecondary }]}>
                      {opt.value}
                    </Text>
                    <Text
                      style={[
                        styles.dropdownLabelText,
                        {
                          color: isSelected ? theme.colors.accent : theme.colors.fgPrimary,
                          fontWeight: isSelected ? '700' : '600',
                        },
                      ]}
                    >
                      {opt.label}
                    </Text>
                  </View>
                  {isSelected && (
                    <Ionicons name="checkmark-circle" size={16} color={theme.colors.accent} style={{ marginLeft: 'auto' }} />
                  )}
                </Touchable>
              );
            })}
          </View>
        </View>
      );
    }

    return (
      <View key={f.key} style={[styles.field, f.flex ? { flex: f.flex } : undefined]}>
        <Text style={[theme.typography.caption, styles.fieldLabel, { color: theme.colors.fgSecondary }]}>
          {f.label}
        </Text>
        <TextInput
          value={values[f.key] ?? ''}
          onChangeText={(text) => updateFieldValue(f.key, text)}
          onFocus={() => setFocusedKey(f.key)}
          onBlur={() => setFocusedKey(null)}
          placeholder={f.placeholder}
          placeholderTextColor={theme.colors.fgSecondary}
          keyboardType={f.keyboardType ?? 'default'}
          multiline={f.multiline}
          secureTextEntry={f.secureTextEntry}
          style={[
            commonStyles.input,
            f.flex ? { height: 44 } : undefined,
            {
              backgroundColor: isFocused ? theme.colors.bgPrimary : theme.colors.bgTertiary,
              borderColor: isFocused ? theme.colors.accent : theme.colors.border,
              borderWidth: isFocused ? 1.5 : StyleSheet.hairlineWidth,
            },
          ]}
        />
      </View>
    );
  };

  // 分组具有 flex 且相同 row 的连续字段
  const fieldElements: React.ReactNode[] = [];
  let flexGroup: FormField[] = [];
  let currentGroupRow: number | undefined = undefined;

  const flushFlexGroup = () => {
    if (flexGroup.length > 0) {
      fieldElements.push(
        <View key={`row-${flexGroup[0].key}`} style={styles.rowFieldGroup}>
          {flexGroup.map(renderField)}
        </View>
      );
      flexGroup = [];
    }
  };

  for (const f of fields) {
    if (f.flex) {
      const fieldRow = f.row ?? 1;
      if (flexGroup.length > 0 && currentGroupRow !== fieldRow) {
        flushFlexGroup();
      }
      currentGroupRow = fieldRow;
      flexGroup.push(f);
    } else {
      flushFlexGroup();
      currentGroupRow = undefined;
      fieldElements.push(renderField(f));
    }
  }
  flushFlexGroup();

  const activeField = fields.find(f => f.key === activeDropdownKey);

  return (
    <Modal visible={visible} transparent animationType="slide" onRequestClose={onCancel}>
      <Pressable style={[styles.overlay, { backgroundColor: theme.colors.overlay }]} onPress={onCancel}>
        <Pressable
          style={[
            styles.sheet,
            theme.shadows.lg,
            {
              backgroundColor: theme.colors.bgSecondary,
              borderColor: theme.colors.border,
            },
          ]}
          onPress={(e) => e.stopPropagation()}
        >
          {/* 顶部 Drag Handle */}
          <View style={[styles.dragHandle, { backgroundColor: theme.colors.divider }]} />

          <View style={styles.header}>
            <Text style={[theme.typography.h3, { color: theme.colors.fgPrimary, fontWeight: '700' }]}>{title}</Text>
            <Touchable onPress={onCancel} hitSlop={8} style={[styles.closeCircleBtn, { backgroundColor: theme.colors.bgTertiary }]}>
              <Ionicons name="close" size={16} color={theme.colors.fgSecondary} />
            </Touchable>
          </View>

          <ScrollView style={styles.body} showsVerticalScrollIndicator={false}>
            {fieldElements}
          </ScrollView>

          {children}
          <View style={styles.actions}>
            <Button label={t('common.cancel')} onPress={onCancel} variant="secondary" />
            <View style={{ flex: 1 }} />
            <Button label={confirmLabel ?? t('common.confirm')} onPress={() => onConfirm(values)} />
          </View>
        </Pressable>
      </Pressable>

      {/* 下拉菜单弹出 Modal */}
      <Modal visible={activeDropdownKey !== null} transparent animationType="fade" onRequestClose={() => setActiveDropdownKey(null)}>
        <Pressable style={[styles.menuOverlay, { backgroundColor: theme.colors.overlay }]} onPress={() => setActiveDropdownKey(null)}>
          <Pressable style={[styles.dropdownMenu, theme.shadows.lg, { backgroundColor: theme.colors.bgSecondary, borderColor: theme.colors.border }]} onPress={e => e.stopPropagation()}>
            <Text style={[theme.typography.caption, { color: theme.colors.fgSecondary, marginBottom: 8, letterSpacing: 0.5, fontWeight: '600' }]}>
              {activeField?.label}
            </Text>
            {activeField?.options?.map(opt => {
              const isSelected = (values[activeField.key] ?? '') === opt.value;
              const hasColon = opt.value.includes(':');
              const pathPrefix = hasColon ? opt.value.slice(0, opt.value.lastIndexOf(':')) : '';
              const shortName = hasColon ? opt.value.slice(opt.value.lastIndexOf(':') + 1) : opt.label;

              return (
                <Touchable
                  key={opt.value}
                  style={[
                    styles.dropdownMenuItem,
                    {
                      backgroundColor: isSelected ? `${theme.colors.accent}15` : theme.colors.bgPrimary,
                      borderColor: isSelected ? theme.colors.accent : theme.colors.border,
                    },
                  ]}
                  onPress={() => {
                    updateFieldValue(activeField.key, opt.value);
                    setActiveDropdownKey(null);
                  }}
                >
                  <View style={{ flex: 1 }}>
                    {pathPrefix ? (
                      <Text style={[styles.dropdownValueText, { color: theme.colors.fgSecondary, fontSize: 10, lineHeight: 12 }]}>
                        {pathPrefix}
                      </Text>
                    ) : null}
                    <Text
                      style={[
                        styles.dropdownLabelText,
                        {
                          color: isSelected ? theme.colors.accent : theme.colors.fgPrimary,
                          fontWeight: isSelected ? '700' : '600',
                          fontSize: 14,
                          lineHeight: 18,
                        },
                      ]}
                    >
                      {shortName}
                    </Text>
                  </View>
                  {isSelected && (
                    <Ionicons name="checkmark-circle" size={18} color={theme.colors.accent} />
                  )}
                </Touchable>
              );
            })}
          </Pressable>
        </Pressable>
      </Modal>
    </Modal>
  );
}

const styles = StyleSheet.create({
  overlay: {
    flex: 1,
    justifyContent: 'flex-end',
  },
  sheet: {
    maxHeight: '80%',
    padding: 20,
    paddingTop: 12,
    paddingBottom: 36,
    borderTopLeftRadius: 24,
    borderTopRightRadius: 24,
  },
  dragHandle: {
    width: 36,
    height: 4,
    borderRadius: 2,
    alignSelf: 'center',
    marginBottom: 16,
    opacity: 0.8,
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 16,
  },
  closeCircleBtn: {
    width: 32,
    height: 32,
    borderRadius: 16,
    alignItems: 'center',
    justifyContent: 'center',
  },
  body: {
    maxHeight: 400,
  },
  field: {
    marginBottom: 14,
  },
  fieldLabel: {
    fontSize: 12,
    fontWeight: '600',
    letterSpacing: 0.3,
    marginBottom: 6,
  },
  rowFieldGroup: {
    flexDirection: 'row',
    gap: 12,
  },
  dropdownTrigger: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingVertical: 2,
    paddingHorizontal: 12,
    height: 44,
    borderRadius: 12,
  },
  dropdownTriggerContent: {
    justifyContent: 'center',
  },
  dropdownValueText: {
    fontSize: 10,
    lineHeight: 12,
  },
  dropdownLabelText: {
    fontSize: 13,
    lineHeight: 16,
    fontWeight: '600',
  },
  optionContainer: {
    gap: 8,
    marginTop: 4,
  },
  optionChip: {
    paddingHorizontal: 12,
    paddingVertical: 10,
    borderRadius: 10,
    borderWidth: 1,
    flexDirection: 'row',
    alignItems: 'center',
  },
  optionTextWrap: {
    flexDirection: 'column',
  },
  optionSubLabel: {
    fontSize: 11,
  },
  actions: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 10,
    marginTop: 12,
  },
  menuOverlay: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 24,
  },
  dropdownMenu: {
    width: '100%',
    maxWidth: 320,
    borderRadius: 20,
    padding: 18,
    borderWidth: StyleSheet.hairlineWidth,
    gap: 10,
  },
  dropdownMenuItem: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: 14,
    paddingVertical: 10,
    borderRadius: 12,
    borderWidth: 1,
  },
});
