import { describe, expect, it, vi } from 'vitest';
import type { BackupConfig, MinioSyncAutomationConfig } from '../config/schema.js';
import type { MemoryStore } from '../memory/store.js';
import { MinioSyncScheduler } from './minioSync.js';

function makeBackupConfig(): BackupConfig {
  return {
    enabled: true,
    schedule: undefined,
    interval: '24h',
    run_on_start: false,
    notify: undefined,
    failure_threshold: 1,
    notify_recovery: true,
    local_dir: '~/.local/share/flynn/backups',
    include_vectors: true,
    minio: {
      enabled: true,
      endpoint: 'localhost:9000',
      access_key: 'minio-admin',
      secret_key: 'minio-secret',
      bucket: 'flynn-knowledge',
      prefix: 'flynn',
      secure: false,
    },
  };
}

function makeAutomationConfig(overrides?: Partial<MinioSyncAutomationConfig>): MinioSyncAutomationConfig {
  return {
    enabled: true,
    interval: '6h',
    run_on_start: false,
    tasks: [{
      prefix: 'knowledge/',
      bucket: undefined,
      namespace_base: 'global/knowledge/minio',
      mode: 'append',
      max_objects: 20,
      max_chars_per_object: 8000,
      force: false,
    }],
    notify: undefined,
    notify_on_success: false,
    ...overrides,
  };
}

describe('MinioSyncScheduler', () => {
  it('skips when memory store is unavailable', async () => {
    const scheduler = new MinioSyncScheduler({
      config: makeAutomationConfig(),
      backupConfig: makeBackupConfig(),
      memoryStore: undefined,
      channelLookup: { get: () => undefined },
    });

    const result = await scheduler.runOnce();
    expect(result).toEqual({ succeeded: 0, failed: 0, details: [] });
  });

  it('runs configured sync tasks and records success/failure counts', async () => {
    const memoryStore = { write: vi.fn() } as unknown as MemoryStore;
    const send = vi.fn(async () => undefined);
    const scheduler = new MinioSyncScheduler({
      config: makeAutomationConfig({
        tasks: [
          {
            prefix: 'knowledge/good/',
            bucket: undefined,
            namespace_base: 'global/knowledge/minio',
            mode: 'append',
            max_objects: 20,
            max_chars_per_object: 8000,
            force: false,
          },
          {
            prefix: 'knowledge/fail/',
            bucket: undefined,
            namespace_base: 'global/knowledge/minio',
            mode: 'append',
            max_objects: 20,
            max_chars_per_object: 8000,
            force: false,
          },
        ],
        notify: { channel: 'telegram', peer: '123' },
      }),
      backupConfig: makeBackupConfig(),
      memoryStore,
      channelLookup: { get: () => ({ send }) },
      createSyncTool: () => ({
        name: 'minio.sync',
        description: '',
        inputSchema: { type: 'object', properties: {} },
        execute: async (rawArgs: unknown) => {
          const prefix = (rawArgs as { prefix: string }).prefix;
          if (prefix === 'knowledge/fail/') {
            return { success: false, output: '', error: 'boom' };
          }
          return { success: true, output: 'ok' };
        },
      }),
    });

    const result = await scheduler.runOnce();
    expect(result.succeeded).toBe(1);
    expect(result.failed).toBe(1);
    expect(result.details).toContain('OK knowledge/good/');
    expect(result.details).toContain('FAIL knowledge/fail/: boom');
    expect(send).toHaveBeenCalledTimes(1);
    scheduler.stop();
  });
});
