/**
 * Remote Token Uploader Tests
 *
 * Tests for uploadTokenToRemote and related functions.
 * Uses mock fetch to verify API interactions.
 */
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import { mockFetch, restoreFetch, getCapturedFetchRequests } from '../../mocks';

describe('remote-token-uploader', () => {
  let tempDir: string;
  let tempTokenFile: string;

  beforeEach(() => {
    // Create temp directory and token file
    tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ccs-test-'));
    tempTokenFile = path.join(tempDir, 'test-token.json');
    fs.writeFileSync(
      tempTokenFile,
      JSON.stringify({
        type: 'gemini',
        email: 'test@example.com',
        access_token: 'test-access-token',
        refresh_token: 'test-refresh-token',
      })
    );
  });

  afterEach(() => {
    restoreFetch();

    // Clean up temp files
    try {
      fs.unlinkSync(tempTokenFile);
      fs.rmdirSync(tempDir);
    } catch {
      // Ignore cleanup errors
    }
  });

  describe('uploadTokenToRemote', () => {
    it('should upload token file successfully', async () => {
      mockFetch([
        {
          url: /\/v0\/management\/auth-files/,
          method: 'POST',
          response: { status: 'ok', id: 'uploaded-123' },
        },
      ]);

      const url = 'http://127.0.0.1:8317/v0/management/auth-files';
      const tokenContent = fs.readFileSync(tempTokenFile, 'utf-8');
      const fileName = path.basename(tempTokenFile);

      const formData = new FormData();
      const blob = new Blob([tokenContent], { type: 'application/json' });
      formData.append('file', blob, fileName);

      const response = await fetch(url, {
        method: 'POST',
        headers: {
          Authorization: 'Bearer test-mgmt-key',
        },
        body: formData,
      });

      expect(response.ok).toBe(true);

      const result = await response.json();
      expect(result).toHaveProperty('status', 'ok');
      expect(result).toHaveProperty('id', 'uploaded-123');

      // Verify request was captured correctly
      const captured = getCapturedFetchRequests();
      expect(captured.length).toBe(1);
      expect(captured[0].url).toContain('/v0/management/auth-files');
      expect(captured[0].method).toBe('POST');
      // Headers should be captured (case-preserved from plain object)
      expect(captured[0].headers['Authorization']).toBe('Bearer test-mgmt-key');
    });

    it('should handle upload failure gracefully', async () => {
      mockFetch([
        {
          url: /\/v0\/management\/auth-files/,
          method: 'POST',
          response: { error: 'Unauthorized' },
          status: 401,
        },
      ]);

      const url = 'http://127.0.0.1:8317/v0/management/auth-files';
      const tokenContent = fs.readFileSync(tempTokenFile, 'utf-8');

      const formData = new FormData();
      formData.append('file', new Blob([tokenContent], { type: 'application/json' }), 'test.json');

      const response = await fetch(url, {
        method: 'POST',
        body: formData,
      });

      expect(response.ok).toBe(false);
      expect(response.status).toBe(401);
    });

    it('should handle connection timeout', async () => {
      // Test that delay mechanism works (simulates network latency)
      mockFetch([
        {
          url: /\/v0\/management\/auth-files/,
          method: 'POST',
          delay: 100, // Simulate slow response
          response: { status: 'ok' },
        },
      ]);

      const url = 'http://127.0.0.1:8317/v0/management/auth-files';
      const startTime = Date.now();

      const response = await fetch(url, {
        method: 'POST',
        body: new FormData(),
      });

      const elapsedTime = Date.now() - startTime;

      // Verify delay was applied (allow 5ms tolerance for system timing variance)
      expect(elapsedTime).toBeGreaterThanOrEqual(95);
      expect(response.ok).toBe(true);
    });

    it('should handle connection refused', async () => {
      // Try to connect to a port with nothing listening
      const url = 'http://127.0.0.1:59999/v0/management/auth-files';

      try {
        await fetch(url, {
          method: 'POST',
          body: new FormData(),
        });
        // Should not reach here in most cases
      } catch (error) {
        // Connection refused is expected
        expect(error).toBeDefined();
      }
    });
  });

  describe('isRemoteUploadEnabled', () => {
    it('should return false when not in remote mode', () => {
      // Test the logic directly
      const target = { isRemote: false, authToken: 'token' };
      const result = target.isRemote && Boolean(target.authToken);
      expect(result).toBe(false);
    });

    it('should return false when remote but no auth', () => {
      const target = { isRemote: true, authToken: undefined, managementKey: undefined };
      const result = target.isRemote && Boolean(target.managementKey ?? target.authToken);
      expect(result).toBe(false);
    });

    it('should return true when remote with authToken', () => {
      const target = { isRemote: true, authToken: 'token', managementKey: undefined };
      const result = target.isRemote && Boolean(target.managementKey ?? target.authToken);
      expect(result).toBe(true);
    });

    it('should return true when remote with managementKey', () => {
      const target = { isRemote: true, authToken: undefined, managementKey: 'mgmt-key' };
      const result = target.isRemote && Boolean(target.managementKey ?? target.authToken);
      expect(result).toBe(true);
    });

    it('should prefer managementKey over authToken', () => {
      const target = { isRemote: true, authToken: 'auth', managementKey: 'mgmt' };
      const key = target.managementKey ?? target.authToken;
      expect(key).toBe('mgmt');
    });
  });

  describe('token file validation', () => {
    it('should reject invalid JSON', async () => {
      // Create invalid token file
      const invalidTokenFile = path.join(tempDir, 'invalid.json');
      fs.writeFileSync(invalidTokenFile, 'not valid json {{{');

      try {
        const content = fs.readFileSync(invalidTokenFile, 'utf-8');
        JSON.parse(content);
        expect(true).toBe(false); // Should not reach
      } catch (error) {
        expect((error as Error).message).toContain('JSON');
      } finally {
        fs.unlinkSync(invalidTokenFile);
      }
    });

    it('should handle missing file', () => {
      try {
        fs.readFileSync('/nonexistent/path/token.json', 'utf-8');
        expect(true).toBe(false); // Should not reach
      } catch (error) {
        expect((error as Error).message).toContain('ENOENT');
      }
    });
  });

  describe('multipart/form-data construction', () => {
    it('should construct valid FormData with file field', () => {
      const tokenContent = JSON.stringify({ type: 'test', token: 'abc' });
      const fileName = 'oauth-token.json';

      const formData = new FormData();
      const blob = new Blob([tokenContent], { type: 'application/json' });
      formData.append('file', blob, fileName);

      // FormData should have the file
      expect(formData.has('file')).toBe(true);

      const file = formData.get('file') as File;
      expect(file).toBeDefined();
      expect(file.name).toBe(fileName);
      expect(file.type).toContain('application/json');
    });
  });

  describe('Authorization header', () => {
    it('should use Bearer token format', async () => {
      mockFetch([{ url: /\/test/, method: 'POST', response: { status: 'ok' } }]);

      const authToken = 'my-secret-token-123';
      await fetch('http://127.0.0.1:8317/test', {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${authToken}`,
        },
        body: new FormData(),
      });

      const captured = getCapturedFetchRequests();
      expect(captured.length).toBe(1);
      // Headers case-preserved from plain object
      expect(captured[0].headers['Authorization']).toBe(`Bearer ${authToken}`);
    });

    it('should not send Authorization when no token', async () => {
      mockFetch([{ url: /\/test/, method: 'POST', response: { status: 'ok' } }]);

      await fetch('http://127.0.0.1:8317/test', {
        method: 'POST',
        body: new FormData(),
      });

      const captured = getCapturedFetchRequests();
      expect(captured.length).toBe(1);
      // No authorization header should be present (check both cases)
      expect(captured[0].headers['Authorization']).toBeUndefined();
      expect(captured[0].headers['authorization']).toBeUndefined();
    });
  });

  describe('response parsing', () => {
    it('should accept status: ok response', async () => {
      mockFetch([{ url: /\/test/, method: 'POST', response: { status: 'ok' } }]);

      const response = await fetch('http://127.0.0.1:8317/test', { method: 'POST' });
      const result = (await response.json()) as { status?: string; success?: boolean; id?: string };

      const isSuccess = result.status === 'ok' || result.success || result.id;
      expect(isSuccess).toBe(true);
    });

    it('should accept success: true response', async () => {
      mockFetch([{ url: /\/test/, method: 'POST', response: { success: true } }]);

      const response = await fetch('http://127.0.0.1:8317/test', { method: 'POST' });
      const result = (await response.json()) as { status?: string; success?: boolean; id?: string };

      const isSuccess = result.status === 'ok' || result.success || result.id;
      expect(isSuccess).toBe(true);
    });

    it('should accept id in response', async () => {
      mockFetch([{ url: /\/test/, method: 'POST', response: { id: 'file-abc123' } }]);

      const response = await fetch('http://127.0.0.1:8317/test', { method: 'POST' });
      const result = (await response.json()) as { status?: string; success?: boolean; id?: string };

      // result.id is truthy when present
      const isSuccess = result.status === 'ok' || result.success === true || Boolean(result.id);
      expect(isSuccess).toBe(true);
    });

    it('should detect error response', async () => {
      mockFetch([{ url: /\/test/, method: 'POST', response: { error: 'Invalid token format' } }]);

      const response = await fetch('http://127.0.0.1:8317/test', { method: 'POST' });
      const result = (await response.json()) as {
        status?: string;
        success?: boolean;
        id?: string;
        error?: string;
      };

      // Error response: none of the success indicators are present
      const isSuccess = result.status === 'ok' || result.success === true || Boolean(result.id);
      expect(isSuccess).toBe(false);
      expect(result.error).toBe('Invalid token format');
    });
  });
});
