/**
 * 元数据状态管理（plan.md「决策 1 双轨制」）。
 *
 * 统一管理 5 类本地实体：分类 / 标签 / 预算 / 信用卡 / 规则。
 * 这些实体是应用本地表（UI 增强 + linkedAccount 映射），不直接写回 .bean
 * （标签除外——标签在记账时以 #tag 语法写入 narration）。
 *
 * 持久化策略与 settingsStore 一致：内存状态 + persistTo 钩子。
 * 生产环境注入 AsyncStorage 持久化，测试环境不传（纯内存）。
 */

import { create } from 'zustand';
import { TAG_COLORS } from '../theme/palette';
import type { Category } from '../domain/taxonomy/categories';
import type { Tag } from '../domain/taxonomy/tags';
import type { Budget } from '../domain/finance/budgets';
import type { CreditCard } from '../domain/finance/creditCards';
import type { Rule } from '../domain/core/types';
import type { RecurringTransaction } from '../domain/finance/recurring';

export interface MetadataState {
  categories: Category[];
  tags: Tag[];
  budgets: Budget[];
  creditCards: CreditCard[];
  rules: Rule[];
  recurringTransactions: RecurringTransaction[];
  remarkTemplates: { id: string; name: string; template: string }[];

  // Category CRUD
  addCategory: (cat: Category) => void;
  updateCategory: (id: string, patch: Partial<Category>) => void;
  removeCategory: (id: string) => void;

  // Tag CRUD
  addTag: (tag: Tag) => void;
  updateTag: (id: string, patch: Partial<Tag>) => void;
  removeTag: (id: string) => void;

  // Budget CRUD
  addBudget: (budget: Budget) => void;
  updateBudget: (id: string, patch: Partial<Budget>) => void;
  removeBudget: (id: string) => void;

  // CreditCard CRUD
  addCreditCard: (card: CreditCard) => void;
  updateCreditCard: (id: string, patch: Partial<CreditCard>) => void;
  removeCreditCard: (id: string) => void;

  // Rule CRUD
  addRule: (rule: Rule) => void;
  updateRule: (id: string, patch: Partial<Rule>) => void;
  removeRule: (id: string) => void;
  addRecurringTransaction: (rec: RecurringTransaction) => void;
  updateRecurringTransaction: (id: string, patch: Partial<RecurringTransaction>) => void;
  removeRecurringTransaction: (id: string) => void;

  // RemarkTemplate CRUD
  addRemarkTemplate: (tpl: { id: string; name: string; template: string }) => void;
  updateRemarkTemplate: (id: string, patch: Partial<{ name: string; template: string }>) => void;
  removeRemarkTemplate: (id: string) => void;

  /** 持久化钩子（每次状态变更后调用）。 */
  persistTo?: (state: PersistableMetadata) => void;
  /** 从持久化源恢复。 */
  hydrate: (data: Partial<PersistableMetadata>) => void;
}

/** 可持久化的子集（排除函数）。 */
export interface PersistableMetadata {
  categories: Category[];
  tags: Tag[];
  budgets: Budget[];
  creditCards: CreditCard[];
  rules: Rule[];
  recurringTransactions: RecurringTransaction[];
  remarkTemplates: { id: string; name: string; template: string }[];
}

/** 默认数据（首次使用时给一组示例,帮助用户上手）。 */
const DEFAULTS: PersistableMetadata = {
  categories: [
    // ── 支出分类 ──────────────────────────────────────────────────────────
    { id: 'food', name: '餐饮', type: 'expense', linkedAccount: 'Expenses:餐饮', keywords: ['餐厅', '中餐', '快餐', '饭店', '外卖', '咖啡', '火锅', '奶茶', '面条', '拉面', '面包'] },
    { id: 'transport', name: '交通', type: 'expense', linkedAccount: 'Expenses:交通', keywords: ['打车', '地铁', '公交', '滴滴', '火车', '单车', '出行'] },
    { id: 'shopping', name: '购物', type: 'expense', linkedAccount: 'Expenses:购物', keywords: ['购物', '超市', '淘宝', '京东', '百货', '拼多多'] },
    { id: 'housing_utility', name: '水电物业', type: 'expense', linkedAccount: 'Expenses:居住:水电物业', keywords: ['电费', '水费', '物业', '燃气'] },
    { id: 'housing_rent', name: '房屋房租', type: 'expense', linkedAccount: 'Expenses:居住:房屋房租', keywords: ['房租', '房东'] },
    { id: 'housing_communication', name: '宽带话费', type: 'expense', linkedAccount: 'Expenses:居住:宽带话费', keywords: ['话费', '电信', '联通', '移动', '扣费', '月费', '流量'] },
    { id: 'entertainment', name: '娱乐休闲', type: 'expense', linkedAccount: 'Expenses:娱乐休闲', keywords: ['游戏', '电影', '视频', '会员'] },
    { id: 'services', name: '生活服务', type: 'expense', linkedAccount: 'Expenses:生活服务', keywords: ['快递', '订阅', '家政', '维修', '洗衣'] },
    { id: 'personal_care', name: '个护美妆', type: 'expense', linkedAccount: 'Expenses:个护美妆', keywords: ['美发', '美容', '面膜', '护肤', '发廊', '粉底液', '理发'] },
    { id: 'clothing', name: '服饰鞋包', type: 'expense', linkedAccount: 'Expenses:服饰鞋包', keywords: ['鞋子', '衣服', '服饰', '外套', '热风', '凉鞋', '裤子'] },
    { id: 'health', name: '医疗健康', type: 'expense', linkedAccount: 'Expenses:医疗健康', keywords: ['医院', '医药', '药店', '感冒', '门诊', '挂号', '诊所'] },
    { id: 'learning', name: '教育培训', type: 'expense', linkedAccount: 'Expenses:教育培训', keywords: ['培训', '学费', '网课', '书籍', '考试', '教材'] },
    { id: 'social', name: '人情往来', type: 'expense', linkedAccount: 'Expenses:人情往来', keywords: ['红包', '份子钱', '礼金', '送礼', '请客', '随礼'] },
    { id: 'travel', name: '旅行住宿', type: 'expense', linkedAccount: 'Expenses:旅行住宿', keywords: ['机票', '酒店', '旅行', '旅游', '景点', '民宿', '携程', '飞猪'] },
    { id: 'digital', name: '数码电子', type: 'expense', linkedAccount: 'Expenses:数码电子', keywords: ['手机', '电脑', '数码', '耳机', '平板', '充电器'] },
    { id: 'insurance', name: '保险', type: 'expense', linkedAccount: 'Expenses:保险', keywords: ['保险', '社保', '医保', '人寿险'] },
    { id: 'pet', name: '宠物', type: 'expense', linkedAccount: 'Expenses:宠物', keywords: ['宠物', '猫粮', '狗粮', '宠物医院', '猫砂'] },
    { id: 'other_expense', name: '其他', type: 'expense', linkedAccount: 'Expenses:其他', keywords: [] },
    // ── 收入分类 ──────────────────────────────────────────────────────────
    { id: 'salary', name: '工资', type: 'income', linkedAccount: 'Income:工资', keywords: ['工资', '薪资', '薪水'] },
    { id: 'income_activity', name: '活动收款', type: 'income', linkedAccount: 'Income:活动收款', keywords: ['群收款', '转账收款', '退款', '红包', '收款', '退还'] },
    { id: 'income_investment', name: '理财收益', type: 'income', linkedAccount: 'Income:理财收益', keywords: ['收益', '利息', '基金', '余额宝收益'] },
    { id: 'income_parttime', name: '兼职收入', type: 'income', linkedAccount: 'Income:兼职收入', keywords: ['兼职', '副业', '稿费', '劳务费'] },
    { id: 'income_reimburse', name: '报销', type: 'income', linkedAccount: 'Income:报销', keywords: ['报销', '报销款', '差旅'] },
    { id: 'income_bonus', name: '奖金', type: 'income', linkedAccount: 'Income:奖金', keywords: ['奖金', '年终奖', '绩效奖', '季度奖'] },
    { id: 'other_income', name: '其他', type: 'income', linkedAccount: 'Income:其他', keywords: [] },
  ],
  tags: [
    { id: 't1', name: 'food', color: TAG_COLORS[0] },
    { id: 't2', name: 'work', color: TAG_COLORS[3] },
    { id: 't3', name: 'travel', color: TAG_COLORS[5] },
  ],
  budgets: [
    { id: 'b1', name: '餐饮月预算', amount: '2000', period: 'monthly', categoryAccount: 'Expenses:餐饮', startDate: '2026-01-01' },
    { id: 'b2', name: '交通月预算', amount: '500', period: 'monthly', categoryAccount: 'Expenses:交通', startDate: '2026-01-01' },
  ],
  creditCards: [],
  rules: [
    // 通用匹配规则示例
    { id: 'rule_coffee', priority: 100, counterpartyContains: '咖啡', sourceAccount: 'Assets:支付宝余额', categoryAccount: 'Expenses:餐饮', narration: '咖啡', tags: ['food'], hits: 0 },
    { id: 'rule_supermarket', priority: 100, counterpartyContains: '超市', sourceAccount: 'Assets:支付宝余额', categoryAccount: 'Expenses:购物', narration: '超市购物', hits: 0 },
    { id: 'rule_train', priority: 100, counterpartyContains: '铁路', memoContains: '火车票', sourceAccount: 'Assets:支付宝余额', categoryAccount: 'Expenses:交通', narration: '火车票', hits: 0 },
    { id: 'rule_taxi', priority: 100, counterpartyContains: '滴滴', sourceAccount: 'Assets:支付宝余额', categoryAccount: 'Expenses:交通', narration: '打车', hits: 0 },
    { id: 'rule_taxi_wechat', priority: 100, counterpartyContains: '滴滴', sourceAccount: 'Assets:微信零钱', categoryAccount: 'Expenses:交通', narration: '打车', hits: 0 },
    { id: 'rule_delivery', priority: 100, counterpartyContains: '顺丰', sourceAccount: 'Assets:微信零钱', categoryAccount: 'Expenses:生活服务', narration: '快递', hits: 0 },
  ],
  recurringTransactions: [],
  remarkTemplates: [
    { id: 'tpl_meal', name: '日常餐饮', template: '${counterparty} ${time}' },
    { id: 'tpl_salary', name: '工资', template: '${month}工资' },
  ],
};

function toPersistable(state: MetadataState): PersistableMetadata {
  return {
    categories: state.categories,
    tags: state.tags,
    budgets: state.budgets,
    creditCards: state.creditCards,
    rules: state.rules,
    recurringTransactions: state.recurringTransactions,
    remarkTemplates: state.remarkTemplates,
  };
}

/** 生成唯一 ID（时间戳 + 随机）。 */
export function generateId(prefix = 'id'): string {
  return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
}

import { logger } from '../utils/logger';

function createCrudActions<T extends { id: string }>(
  key: keyof PersistableMetadata,
  set: (fn: (s: MetadataState) => Partial<MetadataState>) => void,
  get: () => MetadataState,
) {
  return {
    add: (item: T) => {
      set((s) => ({ [key]: [...((s[key] as unknown as T[])), item] }) as Partial<MetadataState>);
      const name = (item as Record<string, unknown>).name || (item as Record<string, unknown>).narration || item.id;
      logger.info('metadataStore', `添加元数据实体 [${key}]: ${name} (ID: ${item.id})`, item);
      get().persistTo?.(toPersistable(get()));
    },
    update: (id: string, patch: Partial<T>) => {
      set((s) => ({
        [key]: (s[key] as unknown as T[]).map(item => item.id === id ? { ...item, ...patch } : item),
      }) as Partial<MetadataState>);
      logger.info('metadataStore', `更新元数据实体 [${key}] (ID: ${id})`, patch);
      get().persistTo?.(toPersistable(get()));
    },
    remove: (id: string) => {
      set((s) => ({
        [key]: (s[key] as unknown as T[]).filter(item => item.id !== id),
      }) as Partial<MetadataState>);
      logger.info('metadataStore', `删除元数据实体 [${key}] (ID: ${id})`);
      get().persistTo?.(toPersistable(get()));
    },
  };
}

export const useMetadataStore = create<MetadataState>((set, get) => {
  const cat = createCrudActions<Category>('categories', set, get);
  const tag = createCrudActions<Tag>('tags', set, get);
  const budget = createCrudActions<Budget>('budgets', set, get);
  const card = createCrudActions<CreditCard>('creditCards', set, get);
  const rule = createCrudActions<Rule>('rules', set, get);
  const rec = createCrudActions<RecurringTransaction>('recurringTransactions', set, get);
  const tpl = createCrudActions<{ id: string; name: string; template: string }>('remarkTemplates', set, get);

  return {
    ...DEFAULTS,

    addCategory: cat.add,
    updateCategory: cat.update,
    removeCategory: cat.remove,

    addTag: tag.add,
    updateTag: tag.update,
    removeTag: tag.remove,

    addBudget: budget.add,
    updateBudget: budget.update,
    removeBudget: budget.remove,

    addCreditCard: card.add,
    updateCreditCard: card.update,
    removeCreditCard: card.remove,

    addRule: rule.add,
    updateRule: rule.update,
    removeRule: rule.remove,

    addRecurringTransaction: rec.add,
    updateRecurringTransaction: rec.update,
    removeRecurringTransaction: rec.remove,

    addRemarkTemplate: tpl.add,
    updateRemarkTemplate: tpl.update,
    removeRemarkTemplate: tpl.remove,

    hydrate: (data) => {
    // 通用按 id 合并：用户数据覆盖同 id 的默认值，新 id 追加到末尾
    // deleted 标记的项不从 defaults 恢复
    const isDeleted = (item: unknown): boolean =>
      typeof item === 'object' && item !== null && 'deleted' in item && !!(item as { deleted?: boolean }).deleted;
    const mergeById = <T extends { id: string }>(defaults: T[], user?: T[]): T[] => {
      if (!user) return defaults;
      const deletedIds = new Set(
        user.filter(item => isDeleted(item)).map(item => item.id)
      );
      const merged = defaults.filter(d => !deletedIds.has(d.id));
      for (const item of user) {
        if (isDeleted(item)) continue;
        const index = merged.findIndex(d => d.id === item.id);
        if (index !== -1) {
          merged[index] = { ...merged[index], ...item };
        } else {
          merged.push(item);
        }
      }
      return merged;
    };

    set({
      ...DEFAULTS,
      ...data,
      categories: mergeById(DEFAULTS.categories, data.categories),
      rules: mergeById(DEFAULTS.rules, data.rules),
      tags: mergeById(DEFAULTS.tags, data.tags),
      budgets: mergeById(DEFAULTS.budgets, data.budgets),
      creditCards: mergeById(DEFAULTS.creditCards, data.creditCards),
      recurringTransactions: mergeById(DEFAULTS.recurringTransactions, data.recurringTransactions),
      remarkTemplates: mergeById(DEFAULTS.remarkTemplates, data.remarkTemplates),
    });
  },
}});
