import React, { useState } from 'react';
import { ScrollView, StyleSheet, Text, View, Alert, Platform } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import * as DocumentPicker from 'expo-document-picker';
import * as FileSystem from 'expo-file-system/legacy';
import * as Sharing from 'expo-sharing';
import { useTheme } from '../../theme';
import { useT } from '../../i18n';
import { useSettingsStore, type PersistableSettings } from '../../store/settingsStore';
import { useLedgerStore } from '../../store/ledgerStore';
import { useImportStore } from '../../store/importStore';
import { useMetadataStore, type PersistableMetadata } from '../../store/metadataStore';
import { Card } from '../../components/ui/Card';
import { Button } from '../../components/ui/Button';
import { FormModal, type FormField } from '../../components/form/FormModal';
import { ScreenHeader } from '../../components/layout/ScreenHeader';
import { syncWithWebDAV, WebDAVClient, type FetchImpl } from '../../services/sync/webdavSync';
import { syncWithGit, ExpoGitBackend } from '../../services/sync/gitSync';
import { syncWithICloud, MockICloudFileSystem } from '../../services/sync/icloudSync';
import { createBackupBundle, serializeBundle, deserializeBundle, restoreFiles } from '../../services/data/backup';
import type { ExcelWorkbook } from '../../services/data/exportToExcel';
import { runMaintenance, ExpoMaintenanceFs, ExpoMaintenanceDb } from '../../services/data/maintenance';

export default function SyncSettingsScreen() {
  const { theme } = useTheme();
  const t = useT();

  // Sync Configuration
  const webdavUrl = useSettingsStore(s => s.webdavUrl) || '';
  const webdavUsername = useSettingsStore(s => s.webdavUsername) || '';
  const webdavPassword = useSettingsStore(s => s.webdavPassword) || '';
  const webdavRemotePath = useSettingsStore(s => s.webdavRemotePath) || 'main.bean';
  const gitRemoteUrl = useSettingsStore(s => s.gitRemoteUrl) || '';
  const gitBranch = useSettingsStore(s => s.gitBranch) || 'main';
  const gitUsername = useSettingsStore(s => s.gitUsername) || '';
  const gitPassword = useSettingsStore(s => s.gitPassword) || '';
  const updateSyncConfig = useSettingsStore(s => s.updateSyncConfig);

  // Ledger state
  const ledger = useLedgerStore(s => s.ledger);
  const mobileBean = useLedgerStore(s => s.mobileBean);
  const replaceMobileBean = useLedgerStore(s => s.replaceMobileBean);

  // Modal Visibility
  const [webdavModalVisible, setWebdavModalVisible] = useState(false);
  const [gitModalVisible, setGitModalVisible] = useState(false);

  // WebDAV credentials form fields
  const webdavFields: FormField[] = [
    { key: 'url', label: t('sync.webdavUrl'), placeholder: 'https://dav.example.com/beancount/', defaultValue: webdavUrl },
    { key: 'username', label: t('sync.username'), placeholder: 'username', defaultValue: webdavUsername },
    { key: 'password', label: t('sync.password'), placeholder: 'password', defaultValue: webdavPassword },
    { key: 'remotePath', label: t('sync.remotePath'), placeholder: 'main.bean', defaultValue: webdavRemotePath },
  ];

  // Git credentials form fields
  const gitFields: FormField[] = [
    { key: 'remoteUrl', label: 'Git Remote URL', placeholder: 'https://github.com/user/ledger.git', defaultValue: gitRemoteUrl },
    { key: 'branch', label: t('sync.branch'), placeholder: 'main', defaultValue: gitBranch },
    { key: 'username', label: t('sync.username'), placeholder: 'gituser', defaultValue: gitUsername },
    { key: 'password', label: t('sync.passwordToken'), placeholder: 'token', defaultValue: gitPassword },
  ];

  const saveWebDAV = (values: Record<string, string>) => {
    updateSyncConfig({
      webdavUrl: values.url,
      webdavUsername: values.username,
      webdavPassword: values.password,
      webdavRemotePath: values.remotePath,
    });
    setWebdavModalVisible(false);
  };

  const saveGit = (values: Record<string, string>) => {
    updateSyncConfig({
      gitRemoteUrl: values.remoteUrl,
      gitBranch: values.branch,
      gitUsername: values.username,
      gitPassword: values.password,
    });
    setGitModalVisible(false);
  };

  // === WebDAV 同步（真实） ===
  const handleWebDAVSync = async () => {
    if (!webdavUrl) {
      Alert.alert(t('sync.hint'), t('sync.webdavNotConfigured'));
      return;
    }
    try {
      const client = new WebDAVClient({
        url: webdavUrl,
        username: webdavUsername,
        password: webdavPassword,
        remotePath: webdavRemotePath,
        backupKeepCount: 3,
      }, fetch as unknown as FetchImpl);
      const result = await syncWithWebDAV(client, mobileBean, new Date().toISOString());
      if (result.action === 'pulled' || result.action === 'conflict') {
        await replaceMobileBean(result.content);
      }
      Alert.alert(t('sync.syncSuccess'), t('sync.webdvResult', { action: result.action }));
    } catch (e) {
      Alert.alert(t('sync.syncFail', { error: e instanceof Error ? e.message : String(e) }));
    }
  };

  // === Git 同步（真实 — ExpoGitBackend 基于 HTTP 单文件同步） ===
  const handleGitSync = async () => {
    if (!gitRemoteUrl) {
      Alert.alert(t('sync.hint'), t('sync.gitNotConfigured'));
      return;
    }
    try {
      const backend = new ExpoGitBackend(gitRemoteUrl, gitUsername, gitPassword, fetch);
      const result = await syncWithGit(backend, {
        remoteUrl: gitRemoteUrl,
        branch: gitBranch,
        autoSync: false,
        syncIntervalMin: 30,
      }, mobileBean);
      if (result.action === 'pulled' || result.action === 'merged' || result.action === 'conflict') {
        await replaceMobileBean(result.content);
      }
      const msgKey = result.conflicts && result.conflicts.length > 0
        ? t('sync.gitConflict', { count: result.conflicts.length })
        : t('sync.gitResult', { action: result.action });
      Alert.alert(t('sync.syncSuccess'), msgKey);
    } catch (e) {
      Alert.alert(t('sync.syncFail', { error: e instanceof Error ? e.message : String(e) }));
    }
  };

  // === iCloud 同步（演示模式 — Mock 后端，Android 上隐藏） ===
  const handleICloudSync = async () => {
    Alert.alert(
      t('sync.demoMode'),
      t('sync.iCloudDemoDesc'),
      [
        { text: t('common.cancel'), style: 'cancel' },
        {
          text: t('sync.runDemo'),
          onPress: async () => {
            try {
              const fs = new MockICloudFileSystem();
              fs.available = true;
              fs.setRemoteFile('main.bean', `${t('sync.iCloudDemoContent')}\n`, new Date().toISOString());
              const result = await syncWithICloud(fs, mobileBean, new Date().toISOString());
              if (result.action === 'pulled' || result.action === 'conflict') {
                await replaceMobileBean(result.content);
              }
              Alert.alert(t('sync.demoSyncSuccess'), t('sync.iCloudResult', { action: result.action }));
            } catch (e) {
              Alert.alert(t('sync.syncFail', { error: e instanceof Error ? e.message : String(e) }));
            }
          },
        },
      ],
    );
  };

  // === 本地备份（真实写文件 + 分享） ===
  const handleBackup = async () => {
    try {
      const files = ledger?.files ?? [];
      // 收集设置（剔除敏感字段和函数）
      const settingsState = useSettingsStore.getState();
      const settings: Record<string, unknown> = {};
      for (const [k, v] of Object.entries(settingsState)) {
        if (typeof v !== 'function' && !['webdavPassword', 'gitPassword', 'appLockPin'].includes(k)) {
          settings[k] = v;
        }
      }
      // 收集元数据（分类/规则/预算/标签/信用卡/周期记账）
      const metaState = useMetadataStore.getState();
      const metadata: Record<string, unknown> = {
        categories: metaState.categories,
        tags: metaState.tags,
        budgets: metaState.budgets,
        creditCards: metaState.creditCards,
        rules: metaState.rules,
        recurringTransactions: metaState.recurringTransactions,
      };

      const bundle = createBackupBundle(files, mobileBean, settings, metadata);
      const json = serializeBundle(bundle);
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');

      // Android 特殊处理：使用 SAF (存储访问框架) 直接让用户选择文件夹并保存
      if (Platform.OS === 'android') {
        try {
          const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
          if (permissions.granted) {
            const fileUri = await FileSystem.StorageAccessFramework.createFileAsync(
              permissions.directoryUri,
              `backup-${timestamp}`,
              'application/json',
            );
            await FileSystem.writeAsStringAsync(fileUri, json);
            Alert.alert(t('sync.backupSuccess'), t('sync.backupSuccessFolder'));
            return;
          }
        } catch (safError) {
          // 如果 SAF 失败，降级到系统分享
          console.warn('SAF backup failed, falling back to sharing:', safError);
        }
      }

      const backupPath = FileSystem.documentDirectory + `backup-${timestamp}.json`;
      await FileSystem.writeAsStringAsync(backupPath, json);

      // 尝试分享（用户可保存到云盘/发送）
      if (await Sharing.isAvailableAsync()) {
        await Sharing.shareAsync(backupPath, {
          mimeType: 'application/json',
          dialogTitle: t('sync.backupShareTitle'),
        });
      }
      Alert.alert(t('sync.backupSuccess'), t('sync.backupSuccessDesc', { path: backupPath }));
    } catch (e) {
      Alert.alert(t('sync.backupFail'), String(e));
    }
  };

  // === 从备份文件恢复（真实） ===
  const handleRestore = async () => {
    try {
      const res = await DocumentPicker.getDocumentAsync({
        type: 'application/json',
        copyToCacheDirectory: true,
      });
      if (res.canceled) return;
      const file = res.assets[0];
      const content = await FileSystem.readAsStringAsync(file.uri);
      const bundle = deserializeBundle(content);
      const restoredFiles = restoreFiles(bundle);
      // 用恢复的 content 替换当前内容
      const restoredMainBean = restoredFiles.find(f => f.path === 'main.bean')?.content || '';
      await replaceMobileBean(restoredMainBean);

      // 恢复设置（v2）
      if (bundle.settings) {
        useSettingsStore.getState().hydrate(bundle.settings as Partial<PersistableSettings>);
        // 同步持久化到文件
        const settingsPath = FileSystem.documentDirectory + 'settings.json';
        await FileSystem.writeAsStringAsync(settingsPath, JSON.stringify(bundle.settings, null, 2));
      }

      // 恢复元数据（v2）
      if (bundle.metadata) {
        useMetadataStore.getState().hydrate(bundle.metadata as Partial<PersistableMetadata>);
        // 同步持久化到文件
        const metadataPath = FileSystem.documentDirectory + 'metadata.json';
        await FileSystem.writeAsStringAsync(metadataPath, JSON.stringify(bundle.metadata, null, 2));
      }

      const restoredParts = [t('sync.restorePartsTx')];
      if (bundle.settings) restoredParts.push(t('sync.restorePartsSettings'));
      if (bundle.metadata) restoredParts.push(t('sync.restorePartsMeta'));
      Alert.alert(
        t('sync.restoreSuccess'),
        `${t('sync.restoreDesc', { name: file.name })}：${restoredParts.join('、')}`,
      );
    } catch (e) {
      Alert.alert(t('sync.restoreFail'), e instanceof Error ? e.message : String(e));
    }
  };

  // === 加载本地 .bean 账本（真实） ===
  const handleLoadLocalLedger = async () => {
    try {
      const res = await DocumentPicker.getDocumentAsync({
        type: '*/*',
        copyToCacheDirectory: true,
      });
      if (res.canceled) return;
      const file = res.assets[0];
      const content = await FileSystem.readAsStringAsync(file.uri);

      // 持久化到 documentDirectory，下次启动自动加载
      const mainPath = FileSystem.documentDirectory + 'main.bean';
      await FileSystem.writeAsStringAsync(mainPath, content);

      const rules = useMetadataStore.getState().rules;
      const categories = useMetadataStore.getState().categories;
      const loadLedger = useLedgerStore.getState().loadLedger;
      const setContext = useImportStore.getState().setContext;
      const { FileSystemBackend } = await import('../../services/data/fileSystemBackend');

      await loadLedger([{ path: 'main.bean', content }], new FileSystemBackend());
      setContext({ rules, categories });

      Alert.alert(t('sync.loadSuccess'), t('sync.loadDesc', { name: file.name }));
    } catch (e) {
      Alert.alert(t('sync.loadFail'), e instanceof Error ? e.message : String(e));
    }
  };

  // === 维护清理（真实 — 扫描并清理 documentDirectory 下的孤儿文件） ===
  const handleMaintenance = async () => {
    Alert.alert(
      t('sync.maintenanceTitle'),
      t('sync.maintenanceConfirm'),
      [
        { text: t('common.cancel'), style: 'cancel' },
        {
          text: t('common.confirm'),
          onPress: async () => {
            try {
              const baseDir = FileSystem.documentDirectory ?? '';
              const cacheDir = FileSystem.cacheDirectory ?? '';
              const fs = new ExpoMaintenanceFs();
              const db = new ExpoMaintenanceDb(mobileBean);
              const report = await runMaintenance(
                fs, db, new Set(),
                {
                  attachments: `${baseDir}attachments/`,
                  thumbnails: `${baseDir}thumbnails/`,
                  cache: cacheDir,
                },
              );
              Alert.alert(
                t('sync.syncSuccess'),
                t('sync.maintenanceResult', {
                  count: report.cleanedCount,
                  size: report.totalOrphanSize,
                }),
              );
            } catch (e) {
              Alert.alert(t('sync.optimizeFail'), String(e));
            }
          },
        },
      ],
    );
  };

  // === 导出 Excel ===
  const handleExportExcel = async () => {
    try {
      const XLSX = (await import('xlsx')).default;
      const { exportToExcel } = await import('../../services/data/exportToExcel');
      const { transactions } = ledger!;
      const workbook = XLSX.utils.book_new();
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const exportPath = FileSystem.documentDirectory + `transactions-${timestamp}.xlsx`;
      let base64Content = '';
      // 用 xlsx 库创建 workbook wrapper
      const wbWrapper = {
        addSheet: (name: string, rows: Record<string, unknown>[]) => {
          const ws = XLSX.utils.json_to_sheet(rows);
          XLSX.utils.book_append_sheet(workbook, ws, name);
        },
        write: (path: string) => {
          base64Content = XLSX.write(workbook, { type: 'base64', bookType: 'xlsx' });
          return FileSystem.writeAsStringAsync(path, base64Content, { encoding: FileSystem.EncodingType.Base64 });
        },
      };
      await exportToExcel(transactions, wbWrapper as unknown as ExcelWorkbook, exportPath);

      // Android 特殊处理：使用 SAF 直接保存到本地公开目录
      if (Platform.OS === 'android') {
        try {
          const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
          if (permissions.granted) {
            const fileUri = await FileSystem.StorageAccessFramework.createFileAsync(
              permissions.directoryUri,
              `transactions-${timestamp}`,
              'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            );
            await FileSystem.writeAsStringAsync(fileUri, base64Content, { encoding: FileSystem.EncodingType.Base64 });
            Alert.alert(t('sync.exportSuccess'), 'Excel 账单已成功保存到所选文件夹！');
            return;
          }
        } catch (safError) {
          console.warn('SAF Excel export failed, falling back to sharing:', safError);
        }
      }

      if (await Sharing.isAvailableAsync()) {
        await Sharing.shareAsync(exportPath, { mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
      }
      Alert.alert(t('sync.exportSuccess'));
    } catch (e) {
      Alert.alert(t('sync.exportFail'), String(e));
    }
  };

  // === 导出规则 ===
  const handleExportRules = async () => {
    try {
      const { exportRules, MockRuleFileSync } = await import('../../services/ruleSync');
      const rules = useMetadataStore.getState().rules;
      const categories = useMetadataStore.getState().categories;
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const exportPath = FileSystem.documentDirectory + `rules-${timestamp}.json`;
      const fs = new MockRuleFileSync();
      // MockRuleFileSync 是内存的，需要真实写入
      await exportRules(rules, categories, fs, exportPath);
      // 获取 Mock 写入的内容，用真实 FileSystem 写
      const content = await fs.read(exportPath);
      await FileSystem.writeAsStringAsync(exportPath, content);

      // Android 特殊处理：使用 SAF 直接保存到本地公开目录
      if (Platform.OS === 'android') {
        try {
          const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync();
          if (permissions.granted) {
            const fileUri = await FileSystem.StorageAccessFramework.createFileAsync(
              permissions.directoryUri,
              `rules-${timestamp}`,
              'application/json',
            );
            await FileSystem.writeAsStringAsync(fileUri, content);
            Alert.alert(t('sync.exportSuccess'), '匹配规则已成功保存到所选文件夹！');
            return;
          }
        } catch (safError) {
          console.warn('SAF Rules export failed, falling back to sharing:', safError);
        }
      }

      if (await Sharing.isAvailableAsync()) {
        await Sharing.shareAsync(exportPath, { mimeType: 'application/json' });
      }
      Alert.alert(t('sync.exportSuccess'));
    } catch (e) {
      Alert.alert(t('sync.exportFail'), String(e));
    }
  };

  // === 导入规则 ===
  const handleImportRules = async () => {
    try {
      const res = await DocumentPicker.getDocumentAsync({ type: 'application/json', copyToCacheDirectory: true });
      if (res.canceled) return;
      const file = res.assets[0];
      const content = await FileSystem.readAsStringAsync(file.uri);
      const { parseRuleBundle, mergeRules } = await import('../../services/ruleSync');
      const bundle = parseRuleBundle(content);
      const existingRules = useMetadataStore.getState().rules;
      const merged = mergeRules(existingRules, bundle.rules);
      // 用合并后的规则更新 store（需要逐条添加新规则）
      const newRules = merged.filter(r => !existingRules.some(e => e.id === r.id));
      for (const rule of newRules) {
        useMetadataStore.getState().addRule(rule);
      }
      Alert.alert(t('sync.importRulesSuccess', { count: newRules.length }));
    } catch (e) {
      Alert.alert(t('sync.exportFail'), e instanceof Error ? e.message : String(e));
    }
  };

  const isAndroid = Platform.OS === 'android';

  return (
    <SafeAreaView style={[styles.page, { backgroundColor: theme.colors.bgPrimary }]} edges={['top', 'bottom']}>
      <ScreenHeader title={t('sync.title')} />

      <ScrollView contentContainerStyle={[styles.content, { gap: theme.spacing.md }]}>
        {/* 云同步配置与云端操作 */}
        <Card title={t('sync.cloudTitle')}>
          <View style={styles.syncBtnRow}>
            <View style={{ flex: 1 }}>
              <Button label={t('sync.configWebdav')} onPress={() => setWebdavModalVisible(true)} variant="secondary" />
            </View>
            <View style={{ flex: 1 }}>
              <Button label={t('sync.configGit')} onPress={() => setGitModalVisible(true)} variant="secondary" />
            </View>
          </View>
          <View style={{ marginTop: 8, gap: 8 }}>
            <Button label={t('sync.webdavSyncNow')} onPress={handleWebDAVSync} />
            <Button label={t('sync.gitSyncNow')} onPress={handleGitSync} variant="secondary" />
            {!isAndroid && (
              <Button label={t('sync.iCloudSync')} onPress={handleICloudSync} variant="secondary" />
            )}
          </View>
          {isAndroid && (
            <Text style={[theme.typography.caption, { color: theme.colors.fgSecondary, marginTop: 8 }]}>
              {t('sync.iCloudUnavailable')}
            </Text>
          )}
        </Card>

        {/* 本地备份与维护 */}
        <Card title={t('sync.backupTitle')}>
          <View style={styles.buttonRow}>
            <View style={{ flex: 1 }}>
              <Button label={t('sync.backupNow')} onPress={handleBackup} />
            </View>
            <View style={{ flex: 1 }}>
              <Button label={t('sync.restoreNow')} onPress={handleRestore} variant="secondary" />
            </View>
          </View>
          <View style={{ gap: 8, marginTop: 8 }}>
            <Button label={t('sync.loadLocalLedger')} onPress={handleLoadLocalLedger} />
            <Button label={t('sync.maintenance')} onPress={handleMaintenance} variant="secondary" />
          </View>
        </Card>

        {/* 数据导出与分享 */}
        <Card title={t('sync.exportTitle')}>
          <View style={{ gap: 8 }}>
            <Button label={t('sync.exportExcel')} onPress={handleExportExcel} />
            <Button label={t('sync.exportRules')} onPress={handleExportRules} variant="secondary" />
            <Button label={t('sync.importRules')} onPress={handleImportRules} variant="secondary" />
          </View>
        </Card>
      </ScrollView>

      {/* WebDAV 凭据配置 */}
      <FormModal
        visible={webdavModalVisible}
        title={t('sync.webdavConfigTitle')}
        fields={webdavFields}
        onConfirm={saveWebDAV}
        onCancel={() => setWebdavModalVisible(false)}
      />

      {/* Git 凭据配置 */}
      <FormModal
        visible={gitModalVisible}
        title={t('sync.gitConfigTitle')}
        fields={gitFields}
        onConfirm={saveGit}
        onCancel={() => setGitModalVisible(false)}
      />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  page: { flex: 1 },
  content: { padding: 16 },
  syncBtnRow: { flexDirection: 'row', gap: 8 },
  buttonRow: { flexDirection: 'row', gap: 8 },
});
