import { describe, it, expect, vi, beforeEach } from 'vitest';
import { SyncService } from '../../src/main/services/SyncService.js';

vi.mock('../../src/main/services/GitClient.js');
import { GitClient } from '../../src/main/services/GitClient.js';

describe('SyncService.resolveConflict', () => {
  let svc: SyncService;
  let importSvc: { applySyncFromDir: ReturnType<typeof vi.fn> };
  let gitInstance: {
    run: ReturnType<typeof vi.fn>;
    addAll: ReturnType<typeof vi.fn>;
    push: ReturnType<typeof vi.fn>;
  };

  beforeEach(() => {
    importSvc = { applySyncFromDir: vi.fn(async () => ({ changedCount: 0 })) };
    gitInstance = {
      run: vi.fn(async () => ({ stdout: '', stderr: '', exitCode: 0 })),
      addAll: vi.fn(async () => {}),
      push: vi.fn(async () => {})
    };
    (GitClient as unknown as ReturnType<typeof vi.fn>).mockImplementation(function () { return gitInstance; });
    svc = new SyncService('/tmp', {} as never, importSvc as never);
  });

  it('local 선택 → checkout --ours + add + rebase --continue + push', async () => {
    const r = await svc.resolveConflict('notes/note-id.md', 'local');
    expect(gitInstance.run).toHaveBeenCalledWith(['checkout', '--ours', 'notes/note-id.md']);
    expect(gitInstance.run).toHaveBeenCalledWith(['rebase', '--continue']);
    expect(gitInstance.push).toHaveBeenCalled();
    expect(r.ok).toBe(true);
  });

  it('remote 선택 → checkout --theirs + add + rebase --continue + applySyncFromDir + push', async () => {
    const r = await svc.resolveConflict('notes/note-id.md', 'remote');
    expect(gitInstance.run).toHaveBeenCalledWith(['checkout', '--theirs', 'notes/note-id.md']);
    expect(importSvc.applySyncFromDir).toHaveBeenCalled();
    expect(gitInstance.push).toHaveBeenCalled();
    expect(r.ok).toBe(true);
  });

  it('checkout 실패 → ok:false + reason 반환', async () => {
    gitInstance.run.mockResolvedValueOnce({ stdout: '', stderr: 'fail', exitCode: 1 });
    const r = await svc.resolveConflict('notes/note-id.md', 'local');
    expect(r.ok).toBe(false);
    expect((r as { reason: string }).reason).toContain('checkout failed');
    expect(gitInstance.push).not.toHaveBeenCalled();
  });

  it('rebase --continue 실패 (다른 파일 미해결) → ok:false', async () => {
    gitInstance.run
      .mockResolvedValueOnce({ stdout: '', stderr: '', exitCode: 0 })  // checkout
      .mockResolvedValueOnce({ stdout: '', stderr: 'still unresolved', exitCode: 1 }); // rebase --continue
    const r = await svc.resolveConflict('notes/note-id.md', 'local');
    expect(r.ok).toBe(false);
    expect((r as { reason: string }).reason).toContain('rebase --continue failed');
    expect(gitInstance.push).not.toHaveBeenCalled();
  });
});
