/**
 * 同步功能抽象（plan.md「Phase 6 同步功能」）。
 * 定义同步引擎接口、冲突解决策略、各后端（Git/WebDAV/iCloud）抽象。
 * 具体实现需文件系统/网络访问，在 services 层注入。
 */

/** 同步变更记录（增量同步用）。 */
export interface SyncChange {
  id: string;
  entityType: 'transaction' | 'rule' | 'category' | 'tag' | 'attachment';
  entityId: string;
  operation: 'create' | 'update' | 'delete';
  payload: string;
  timestamp: string;
}

/** 冲突解决策略。 */
export type ConflictResolution = 'last-writer-wins' | 'manual' | 'prefer-local' | 'prefer-remote';

export interface SyncConflict {
  entityType: string;
  entityId: string;
  local: string;
  remote: string;
  resolution: ConflictResolution;
}

/** 同步后端抽象。 */
export interface SyncBackend {
  readonly type: 'git' | 'webdav' | 'icloud' | 'supabase' | 's3' | 'none';
  /** 上传 main.bean 全量快照。 */
  push(content: string): Promise<void>;
  /** 拉取 main.bean 全量快照。 */
  pull(): Promise<string | null>;
  /** 获取远程最后修改时间。 */
  getRemoteLastModified(): Promise<string | null>;
}

/** 快照同步（全量上传/下载，plan.md「6.1 快照同步」）。 */
export async function snapshotSync(
  backend: SyncBackend,
  localContent: string,
  lastSyncTime: string,
  onConflict?: (conflict: SyncConflict) => Promise<SyncConflict>,
  lastLocalModified?: string,
): Promise<{ action: 'pushed' | 'pulled' | 'conflict' | 'noop'; content: string }> {
  const remoteModified = await backend.getRemoteLastModified();
  const remoteContent = await backend.pull();

  // 无远程内容 → 直接推送
  if (remoteContent === null) {
    await backend.push(localContent);
    return { action: 'pushed', content: localContent };
  }

  // 内容相同 → 无操作
  if (remoteContent === localContent) {
    return { action: 'noop', content: localContent };
  }

  // 远程有更新且本地也有更新 → 冲突
  const remoteChanged = remoteModified !== null && remoteModified > lastSyncTime;
  const localChanged = lastLocalModified !== undefined
    ? lastLocalModified > lastSyncTime
    : true;  // 未提供时默认为有变更（向后兼容）

  if (remoteChanged && localChanged) {
    if (onConflict) {
      const conflict: SyncConflict = {
        entityType: 'main.bean',
        entityId: 'main.bean',
        local: localContent,
        remote: remoteContent,
        resolution: 'manual',
      };
      const resolved = await onConflict(conflict);
      const content = resolved.resolution === 'prefer-remote' ? remoteContent : localContent;
      await backend.push(content);
      return { action: 'conflict', content };
    }
    // 默认 last-writer-wins
    return { action: 'conflict', content: localContent };
  }

  // 仅远程更新 → 拉取
  if (remoteChanged) {
    return { action: 'pulled', content: remoteContent };
  }

  // 仅本地更新 → 推送
  await backend.push(localContent);
  return { action: 'pushed', content: localContent };
}

/** 内存同步后端（测试用）。 */
export class MemorySyncBackend implements SyncBackend {
  readonly type = 'none' as const;
  private content: string | null = null;
  private lastModified: string | null = null;

  constructor(initial?: string) {
    if (initial !== undefined) {
      this.content = initial;
      this.lastModified = new Date().toISOString();
    }
  }

  async push(content: string): Promise<void> {
    this.content = content;
    this.lastModified = new Date().toISOString();
  }
  async pull(): Promise<string | null> {
    return this.content;
  }
  async getRemoteLastModified(): Promise<string | null> {
    return this.lastModified;
  }
  /** 测试辅助：模拟远程修改。 */
  simulateRemoteChange(content: string): void {
    this.content = content;
    this.lastModified = new Date().toISOString();
  }
}

/** 同步错误记录（plan.md「6.5 同步错误持久化」）。 */
export interface SyncError {
  id: string;
  operation: 'push' | 'pull' | 'merge';
  entityType: string;
  entityId: string;
  message: string;
  createdAt: string;
  resolved: 0 | 1 | 2;  // 0=未解决, 1=已重试, 2=已跳过
}
