import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { createMinioShareTool, minioShareInternals } from './minio-share.js';
import type { BackupConfig } from '../../config/schema.js';

function makeBackupConfig(overrides?: Partial<BackupConfig>): 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-shared',
      prefix: 'flynn',
      secure: false,
    },
    ...overrides,
  };
}

describe('minio share internals', () => {
  it('parses share URL from json output', () => {
    const out = '{"status":"success","share":"https://minio.local/share/some-token"}\n';
    expect(minioShareInternals.parseShareUrl(out)).toBe('https://minio.local/share/some-token');
  });

  it('parses share URL from plain text output', () => {
    const out = 'Share: https://minio.local/share/some-token\n';
    expect(minioShareInternals.parseShareUrl(out)).toBe('https://minio.local/share/some-token');
  });
});

describe('createMinioShareTool', () => {
  let tempDir = '';

  afterEach(() => {
    if (tempDir) {
      rmSync(tempDir, { recursive: true, force: true });
      tempDir = '';
    }
  });

  it('uploads file and returns share URL', async () => {
    tempDir = mkdtempSync(join(tmpdir(), 'flynn-minio-share-'));
    const filePath = join(tempDir, 'report.csv');
    writeFileSync(filePath, 'a,b\n1,2\n');

    const execRunner = vi.fn(async (_file: string, args: string[]) => {
      if (args[0] === 'share') {
        return { stdout: '{"share":"https://minio.local/share/abc"}\n', stderr: '' };
      }
      return { stdout: '', stderr: '' };
    });

    const tool = createMinioShareTool(makeBackupConfig({
      minio: {
        enabled: true,
        endpoint: 'localhost:9000',
        access_key: 'minio-admin',
        secret_key: 'minio-secret',
        bucket: 'flynn-shared',
        prefix: 'flynn',
        secure: false,
        mc_path: '/opt/bin/mc',
      },
    }), {
      execRunner,
      now: () => new Date('2026-02-16T10:00:00.000Z'),
    });

    const result = await tool.execute({ path: filePath, expires: '12h', prefix: 'exports' });
    expect(result.success).toBe(true);
    expect(result.output).toContain('https://minio.local/share/abc');
    expect(execRunner).toHaveBeenCalledTimes(3);
    expect(execRunner.mock.calls[0]?.[0]).toBe('/opt/bin/mc');
    expect(execRunner.mock.calls[1]?.[1]).toContain('cp');
    expect(execRunner.mock.calls[2]?.[1]).toContain('share');
  });

  it('returns error when minio is disabled', async () => {
    const tool = createMinioShareTool(makeBackupConfig({
      minio: {
        enabled: false,
        endpoint: undefined,
        access_key: undefined,
        secret_key: undefined,
        bucket: undefined,
        prefix: 'flynn',
        secure: true,
      },
    }));

    const result = await tool.execute({ path: '/tmp/test.txt' });
    expect(result.success).toBe(false);
    expect(result.error).toContain('backup.minio.enabled=true');
  });
});
