/**
 * Tests for the GitHub Backup API client functions.
 */

import { describe, it, expect } from 'vitest';
import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';
import type {
  GitHubBackupConfig,
  GitHubBackupStatus,
  GitHubBackupLog,
} from '../../api/client';

// Mock API base URL
const API_BASE = 'http://localhost:5000/api/v1';

// Create MSW server
const server = setupServer();

beforeAll(() => server.listen({ onUnhandledRequest: 'bypass' }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

describe('GitHub Backup API Types', () => {
  it('GitHubBackupConfig has correct shape', () => {
    const config: GitHubBackupConfig = {
      id: 1,
      repository_url: 'https://github.com/test/repo',
      has_token: true,
      branch: 'main',
      schedule_enabled: true,
      schedule_type: 'daily',
      backup_kprofiles: true,
      backup_cloud_profiles: true,
      backup_settings: false,
      backup_spools: false,
      backup_archives: false,
      enabled: true,
      last_backup_at: '2026-01-27T10:00:00Z',
      last_backup_status: 'success',
      last_backup_message: null,
      last_backup_commit_sha: 'abc123',
      next_scheduled_run: '2026-01-28T00:00:00Z',
      created_at: '2026-01-01T00:00:00Z',
      updated_at: '2026-01-27T10:00:00Z',
    };

    expect(config.id).toBe(1);
    expect(config.has_token).toBe(true);
    expect(config.schedule_type).toBe('daily');
    expect(config.backup_spools).toBe(false);
    expect(config.backup_archives).toBe(false);
  });

  it('GitHubBackupStatus has correct shape', () => {
    const status: GitHubBackupStatus = {
      configured: true,
      enabled: true,
      is_running: false,
      progress: null,
      last_backup_at: '2026-01-27T10:00:00Z',
      last_backup_status: 'success',
      next_scheduled_run: '2026-01-28T00:00:00Z',
    };

    expect(status.configured).toBe(true);
    expect(status.is_running).toBe(false);
  });

  it('GitHubBackupStatus can have progress', () => {
    const status: GitHubBackupStatus = {
      configured: true,
      enabled: true,
      is_running: true,
      progress: 'Pushing to GitHub...',
      last_backup_at: null,
      last_backup_status: null,
      next_scheduled_run: null,
    };

    expect(status.is_running).toBe(true);
    expect(status.progress).toBe('Pushing to GitHub...');
  });

  it('GitHubBackupLog has correct shape', () => {
    const log: GitHubBackupLog = {
      id: 1,
      config_id: 1,
      started_at: '2026-01-27T10:00:00Z',
      completed_at: '2026-01-27T10:01:00Z',
      status: 'success',
      trigger: 'manual',
      commit_sha: 'abc123',
      files_changed: 5,
      error_message: null,
    };

    expect(log.status).toBe('success');
    expect(log.trigger).toBe('manual');
    expect(log.files_changed).toBe(5);
  });

  it('GitHubBackupConfig supports spool and archive backup toggles', () => {
    const config: GitHubBackupConfig = {
      id: 2,
      repository_url: 'https://github.com/test/full-backup',
      has_token: true,
      branch: 'main',
      schedule_enabled: false,
      schedule_type: 'daily',
      backup_kprofiles: true,
      backup_cloud_profiles: false,
      backup_settings: false,
      backup_spools: true,
      backup_archives: true,
      enabled: true,
      last_backup_at: null,
      last_backup_status: null,
      last_backup_message: null,
      last_backup_commit_sha: null,
      next_scheduled_run: null,
      created_at: '2026-04-01T00:00:00Z',
      updated_at: '2026-04-01T00:00:00Z',
    };

    expect(config.backup_spools).toBe(true);
    expect(config.backup_archives).toBe(true);
    expect(config.backup_cloud_profiles).toBe(false);
  });

  it('GitHubBackupLog can have error', () => {
    const log: GitHubBackupLog = {
      id: 2,
      config_id: 1,
      started_at: '2026-01-27T10:00:00Z',
      completed_at: '2026-01-27T10:00:30Z',
      status: 'failed',
      trigger: 'scheduled',
      commit_sha: null,
      files_changed: 0,
      error_message: 'Authentication failed',
    };

    expect(log.status).toBe('failed');
    expect(log.error_message).toBe('Authentication failed');
    expect(log.commit_sha).toBeNull();
  });
});

describe('GitHub Backup API Endpoints', () => {
  it('GET /github-backup/config returns null when not configured', async () => {
    server.use(
      http.get(`${API_BASE}/github-backup/config`, () => {
        return HttpResponse.json(null);
      })
    );

    const response = await fetch(`${API_BASE}/github-backup/config`);
    const data = await response.json();
    expect(data).toBeNull();
  });

  it('GET /github-backup/config returns config when exists', async () => {
    const mockConfig: GitHubBackupConfig = {
      id: 1,
      repository_url: 'https://github.com/test/repo',
      has_token: true,
      branch: 'main',
      schedule_enabled: false,
      schedule_type: 'daily',
      backup_kprofiles: true,
      backup_cloud_profiles: true,
      backup_settings: false,
      backup_spools: true,
      backup_archives: true,
      enabled: true,
      last_backup_at: null,
      last_backup_status: null,
      last_backup_message: null,
      last_backup_commit_sha: null,
      next_scheduled_run: null,
      created_at: '2026-01-01T00:00:00Z',
      updated_at: '2026-01-01T00:00:00Z',
    };

    server.use(
      http.get(`${API_BASE}/github-backup/config`, () => {
        return HttpResponse.json(mockConfig);
      })
    );

    const response = await fetch(`${API_BASE}/github-backup/config`);
    const data = await response.json();
    expect(data.repository_url).toBe('https://github.com/test/repo');
    expect(data.has_token).toBe(true);
  });

  it('GET /github-backup/status returns not configured status', async () => {
    const mockStatus: GitHubBackupStatus = {
      configured: false,
      enabled: false,
      is_running: false,
      progress: null,
      last_backup_at: null,
      last_backup_status: null,
      next_scheduled_run: null,
    };

    server.use(
      http.get(`${API_BASE}/github-backup/status`, () => {
        return HttpResponse.json(mockStatus);
      })
    );

    const response = await fetch(`${API_BASE}/github-backup/status`);
    const data = await response.json();
    expect(data.configured).toBe(false);
    expect(data.enabled).toBe(false);
  });

  it('GET /github-backup/logs returns empty list when no logs', async () => {
    server.use(
      http.get(`${API_BASE}/github-backup/logs`, () => {
        return HttpResponse.json([]);
      })
    );

    const response = await fetch(`${API_BASE}/github-backup/logs`);
    const data = await response.json();
    expect(data).toEqual([]);
  });

  it('GET /github-backup/logs returns log entries', async () => {
    const mockLogs: GitHubBackupLog[] = [
      {
        id: 1,
        config_id: 1,
        started_at: '2026-01-27T10:00:00Z',
        completed_at: '2026-01-27T10:01:00Z',
        status: 'success',
        trigger: 'manual',
        commit_sha: 'abc123',
        files_changed: 5,
        error_message: null,
      },
    ];

    server.use(
      http.get(`${API_BASE}/github-backup/logs`, () => {
        return HttpResponse.json(mockLogs);
      })
    );

    const response = await fetch(`${API_BASE}/github-backup/logs`);
    const data = await response.json();
    expect(data.length).toBe(1);
    expect(data[0].status).toBe('success');
  });

  it('POST /github-backup/run returns 404 when not configured', async () => {
    server.use(
      http.post(`${API_BASE}/github-backup/run`, () => {
        return HttpResponse.json(
          { detail: 'No configuration found' },
          { status: 404 }
        );
      })
    );

    const response = await fetch(`${API_BASE}/github-backup/run`, {
      method: 'POST',
    });
    expect(response.status).toBe(404);
  });

  it('POST /github-backup/test returns success on valid credentials', async () => {
    server.use(
      http.post(`${API_BASE}/github-backup/test`, () => {
        return HttpResponse.json({
          success: true,
          message: 'Connection successful',
          repo_name: 'test/repo',
          default_branch: 'main',
        });
      })
    );

    const response = await fetch(
      `${API_BASE}/github-backup/test?repo_url=https://github.com/test/repo&token=ghp_test`,
      { method: 'POST' }
    );
    const data = await response.json();
    expect(data.success).toBe(true);
    expect(data.repo_name).toBe('test/repo');
  });

  it('POST /github-backup/test returns failure on invalid credentials', async () => {
    server.use(
      http.post(`${API_BASE}/github-backup/test`, () => {
        return HttpResponse.json({
          success: false,
          message: 'Authentication failed',
          repo_name: null,
          default_branch: null,
        });
      })
    );

    const response = await fetch(
      `${API_BASE}/github-backup/test?repo_url=https://github.com/test/repo&token=invalid`,
      { method: 'POST' }
    );
    const data = await response.json();
    expect(data.success).toBe(false);
    expect(data.message).toBe('Authentication failed');
  });
});
