import * as FileSystem from 'expo-file-system/legacy';
import * as SecureStore from 'expo-secure-store';
import { useSettingsStore, SECURE_KEYS, toPersistable, type PersistableSettings } from './settingsStore';
import { useMetadataStore, type PersistableMetadata } from './metadataStore';
import { logger } from '../utils/logger';

const SETTINGS_FILE = FileSystem.documentDirectory + 'settings.json';
const SETTINGS_FILE_TMP = FileSystem.documentDirectory + 'settings.json.tmp';
const METADATA_FILE = FileSystem.documentDirectory + 'metadata.json';
const METADATA_FILE_TMP = FileSystem.documentDirectory + 'metadata.json.tmp';

/** 持久化 Schema 版本号。每次变更持久化结构时递增，并添加对应迁移函数。 */
export const SETTINGS_SCHEMA_VERSION = 1;
export const METADATA_SCHEMA_VERSION = 1;

/** Settings 迁移链：键为目标版本，值为从上一版迁移的函数。 */
const _SETTINGS_MIGRATIONS: Record<number, (data: Record<string, unknown>) => Record<string, unknown>> = {
  // 示例：2: (d) => ({ ...d, newField: d.oldField, _version: 2 }),
};

/** Metadata 迁移链。 */
const _METADATA_MIGRATIONS: Record<number, (data: Record<string, unknown>) => Record<string, unknown>> = {
  // 示例：2: (d) => ({ ...d, _version: 2 }),
};

/** 执行迁移：从当前版本升级到最新版本。 */
function _migrateData(
  data: Record<string, unknown>,
  currentVersion: number,
  migrations: Record<number, (d: Record<string, unknown>) => Record<string, unknown>>,
): Record<string, unknown> {
  const dataVersion = (data._version as number) ?? 0;
  if (dataVersion >= currentVersion) return data;
  let result = { ...data };
  for (let v = dataVersion + 1; v <= currentVersion; v++) {
    const migrate = migrations[v];
    if (migrate) result = migrate(result);
    result._version = v;
  }
  logger.info('persistence', 'Schema \u8fc1\u79fb: v' + dataVersion + ' -> v' + currentVersion);
  return result;
}


/**
 * 持久化初始化：从存储恢复状态 + 挂载写入钩子。
 *
 * 安全策略：
 * - 敏感字段（密码、API Key）通过 expo-secure-store 加密存储（Android Keystore / iOS Keychain）
 * - 其余配置仍以 JSON 文件存储（便于调试、导出）
 * - settings.json 中不包含任何敏感字段（写入前剔除）
 */
let settingsDebounce: ReturnType<typeof setTimeout> | null = null;
let metadataDebounce: ReturnType<typeof setTimeout> | null = null;
let lastSettingsState: PersistableSettings | null = null;
let lastMetadataState: unknown = null;

export async function flushPersistence() {
  if (settingsDebounce && lastSettingsState) {
    clearTimeout(settingsDebounce);
    settingsDebounce = null;
    const content = JSON.stringify(lastSettingsState, null, 2);
    try {
      await FileSystem.writeAsStringAsync(SETTINGS_FILE_TMP, content);
      await FileSystem.deleteAsync(SETTINGS_FILE, { idempotent: true });
      await FileSystem.moveAsync({ from: SETTINGS_FILE_TMP, to: SETTINGS_FILE });
      logger.info('persistence', 'Settings write flushed successfully');
    } catch (e) {
      logger.error('persistence', `Failed to flush settings: ${e}`);
    }
  }
  if (metadataDebounce && lastMetadataState) {
    clearTimeout(metadataDebounce);
    metadataDebounce = null;
    const content = JSON.stringify(lastMetadataState, null, 2);
    try {
      await FileSystem.writeAsStringAsync(METADATA_FILE_TMP, content);
      await FileSystem.deleteAsync(METADATA_FILE, { idempotent: true });
      await FileSystem.moveAsync({ from: METADATA_FILE_TMP, to: METADATA_FILE });
      logger.info('persistence', 'Metadata write flushed successfully');
    } catch (e) {
      logger.error('persistence', `Failed to flush metadata: ${e}`);
    }
  }
}

export async function initPersistence() {
  try {
    // 0. 崩溃恢复：如果存在临时文件且正式文件不存在，用临时文件恢复
    const settingsTmpInfo = await FileSystem.getInfoAsync(SETTINGS_FILE_TMP);
    if (settingsTmpInfo.exists) {
      const settingsInfo = await FileSystem.getInfoAsync(SETTINGS_FILE);
      if (!settingsInfo.exists) {
        await FileSystem.moveAsync({ from: SETTINGS_FILE_TMP, to: SETTINGS_FILE });
      } else {
        await FileSystem.deleteAsync(SETTINGS_FILE_TMP, { idempotent: true });
      }
    }

    const metadataTmpInfo = await FileSystem.getInfoAsync(METADATA_FILE_TMP);
    if (metadataTmpInfo.exists) {
      const metadataInfo = await FileSystem.getInfoAsync(METADATA_FILE);
      if (!metadataInfo.exists) {
        await FileSystem.moveAsync({ from: METADATA_FILE_TMP, to: METADATA_FILE });
      } else {
        await FileSystem.deleteAsync(METADATA_FILE_TMP, { idempotent: true });
      }
    }

    // 1. 从明文 JSON 读取非敏感设置
    const settingsData: Partial<PersistableSettings> = {};
    const settingsInfo = await FileSystem.getInfoAsync(SETTINGS_FILE);
    if (settingsInfo.exists) {
      const settingsContent = await FileSystem.readAsStringAsync(SETTINGS_FILE);
      try {
        Object.assign(settingsData, JSON.parse(settingsContent));
      } catch (parseErr) {
        logger.error('persistence', `Failed to parse settings.json: ${parseErr}`);
      }
    }

    // 2. 从 SecureStore 读取敏感字段，合并到 settingsData
    for (const key of SECURE_KEYS) {
      const value = await SecureStore.getItemAsync(key);
      if (value !== null && value !== undefined) {
        (settingsData as Record<string, unknown>)[key] = value;
      }
    }

    if (Object.keys(settingsData).length > 0) {
      useSettingsStore.getState().hydrate(settingsData);
      logger.info('persistence', 'Settings hydrated from storage');
    }

    // 3. Hydrate Metadata（无敏感字段，全部走 JSON）
    let metadataData: Partial<PersistableMetadata> | null = null;
    const metadataInfo = await FileSystem.getInfoAsync(METADATA_FILE);
    if (metadataInfo.exists) {
      const metadataContent = await FileSystem.readAsStringAsync(METADATA_FILE);
      try {
        metadataData = JSON.parse(metadataContent);
        useMetadataStore.getState().hydrate(metadataData!);
        logger.info('persistence', 'Metadata hydrated from storage');
      } catch (parseErr) {
        logger.error('persistence', `Failed to parse metadata.json: ${parseErr}`);
      }
    }

    // 初始化时获取已 hydration 的设置状态进行序列化，防止 skipPersist 切换触发不必要的空写入
    const initialSettings = toPersistable(useSettingsStore.getState());
    const initialSafeSettings = { ...initialSettings };
    for (const key of SECURE_KEYS) {
      delete initialSafeSettings[key];
    }
    let lastSettingsSerialized = JSON.stringify(stripFunctions(initialSafeSettings));
    
    let lastMetadataSerialized = metadataData ? JSON.stringify(metadataData) : '';

    // 4. 挂载 settingsStore persistTo + subscribe 自动持久化
    const persistSettings = (state: PersistableSettings) => {
      // 4a. 敏感字段立即写入 SecureStore（加密）— 不防抖（敏感数据应及时持久化）
      for (const key of SECURE_KEYS) {
        const value = state[key];
        if (value !== undefined && value !== null && value !== '') {
          SecureStore.setItemAsync(key, value)
            .catch(e => {
              logger.error('persistence', `Failed to persist secure key ${key}: ${e}`);
              // 1 次延迟重试
              setTimeout(() => {
                SecureStore.setItemAsync(key, value).catch(e2 =>
                  logger.error('persistence', `Retry failed for secure key ${key}: ${e2}`),
                );
              }, 500);
            });
        } else {
          SecureStore.deleteItemAsync(key).catch(() => { /* 忽略：可能本就不存在 */ });
        }
      }

      // 4b. 非敏感字段防抖写入 JSON 文件（原子性操作）
      const safeState = { ...state };
      for (const key of SECURE_KEYS) {
        delete safeState[key];
      }
      const withVersion = { ...stripFunctions(safeState as unknown as Record<string, unknown>), _version: SETTINGS_SCHEMA_VERSION };
      const serialized = JSON.stringify(withVersion);
      // 深比较：内容未变则跳过写入
      if (serialized === lastSettingsSerialized) return;
      lastSettingsSerialized = serialized;
      lastSettingsState = safeState as unknown as PersistableSettings;
      if (settingsDebounce) clearTimeout(settingsDebounce);
      settingsDebounce = setTimeout(() => {
        if (lastSettingsState) {
          const content = JSON.stringify(lastSettingsState, null, 2);
          FileSystem.writeAsStringAsync(SETTINGS_FILE_TMP, content)
            .then(() => FileSystem.deleteAsync(SETTINGS_FILE, { idempotent: true }))
            .then(() => FileSystem.moveAsync({ from: SETTINGS_FILE_TMP, to: SETTINGS_FILE }))
            .catch(e => {
              logger.error('persistence', `Failed to persist settings: ${e}`);
              setTimeout(() => {
                FileSystem.writeAsStringAsync(SETTINGS_FILE_TMP, content)
                  .then(() => FileSystem.deleteAsync(SETTINGS_FILE, { idempotent: true }))
                  .then(() => FileSystem.moveAsync({ from: SETTINGS_FILE_TMP, to: SETTINGS_FILE }))
                  .catch(e2 => logger.error('persistence', `Retry failed for settings: ${e2}`));
              }, 500);
            });
        }
      }, 300);
    };

    // subscribe 自动触发持久化（跳过 hydrate 和初始状态）
    useSettingsStore.subscribe((state, prevState) => {
      if (state.skipPersist) {
        // 同步更新 lastSettingsSerialized 避免后续误写入，但跳过实际的写入操作
        const safeState = toPersistable(state);
        for (const key of SECURE_KEYS) {
          delete safeState[key];
        }
        lastSettingsSerialized = JSON.stringify(stripFunctions(safeState as unknown as Record<string, unknown>));
        return;
      }
      if (state === prevState) return;
      persistSettings(toPersistable(state));
    });

    // 5. 挂载 metadataStore persistTo（防抖写入 JSON 原子性操作）
    useMetadataStore.setState({
      persistTo: (state) => {
        const serialized = JSON.stringify(state);
        // 深比较：内容未变则跳过写入
        if (serialized === lastMetadataSerialized) return;
        lastMetadataSerialized = serialized;
        lastMetadataState = state;
        if (metadataDebounce) clearTimeout(metadataDebounce);
        metadataDebounce = setTimeout(() => {
          if (lastMetadataState) {
            const content = JSON.stringify(lastMetadataState, null, 2);
            FileSystem.writeAsStringAsync(METADATA_FILE_TMP, content)
              .then(() => FileSystem.deleteAsync(METADATA_FILE, { idempotent: true }))
              .then(() => FileSystem.moveAsync({ from: METADATA_FILE_TMP, to: METADATA_FILE }))
              .catch(e => {
                logger.error('persistence', `Failed to persist metadata: ${e}`);
                setTimeout(() => {
                  FileSystem.writeAsStringAsync(METADATA_FILE_TMP, content)
                    .then(() => FileSystem.deleteAsync(METADATA_FILE, { idempotent: true }))
                    .then(() => FileSystem.moveAsync({ from: METADATA_FILE_TMP, to: METADATA_FILE }))
                    .catch(e2 => logger.error('persistence', `Retry failed for metadata: ${e2}`));
                }, 500);
              });
          }
        }, 300);
      },
    });

  } catch (e) {
    logger.error('persistence', `Failed to init persistence: ${e}`);
  }
}

/** 从 state 对象中剔除函数，只保留可序列化的数据字段。 */
function stripFunctions(state: Record<string, unknown>): Record<string, unknown> {
  const result: Record<string, unknown> = {};
  for (const [key, value] of Object.entries(state)) {
    if (typeof value !== 'function') {
      result[key] = value;
    }
  }
  return result;
}
