import { describe, it, expect, vi, beforeEach } from 'vitest';

// Mock auth module
vi.mock('../../auth.js', () => ({
  signIn: vi.fn(),
  saveSession: vi.fn(),
}));

// Mock daemon to avoid file-system reads
vi.mock('./daemon.js', () => ({
  readMeta: vi.fn().mockReturnValue({
    host: 'localhost',
    port: 14242,
    version: '1.0.0',
    installedAt: '',
    entryPoint: '',
  }),
}));

import { runLogin, getGatewayUrl } from './login.js';
import { signIn, saveSession } from '../../auth.js';
import { readMeta } from './daemon.js';

const mockSignIn = vi.mocked(signIn);
const mockSaveSession = vi.mocked(saveSession);
const mockReadMeta = vi.mocked(readMeta);

describe('getGatewayUrl', () => {
  it('returns override URL when provided', () => {
    expect(getGatewayUrl('http://my-gateway:9999')).toBe('http://my-gateway:9999');
  });

  it('builds URL from meta.json when no override given', () => {
    mockReadMeta.mockReturnValueOnce({
      host: 'myhost',
      port: 8080,
      version: '1.0.0',
      installedAt: '',
      entryPoint: '',
    });
    expect(getGatewayUrl()).toBe('http://myhost:8080');
  });

  it('falls back to default when meta is null', () => {
    mockReadMeta.mockReturnValueOnce(null);
    expect(getGatewayUrl()).toBe('http://localhost:14242');
  });
});

describe('runLogin', () => {
  const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {});

  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('calls signIn and saveSession on success', async () => {
    const fakeAuth = {
      cookie: 'better-auth.session_token=abc',
      userId: 'u1',
      email: 'admin@test.com',
    };
    mockSignIn.mockResolvedValueOnce(fakeAuth);

    await runLogin({
      gatewayUrl: 'http://localhost:14242',
      email: 'admin@test.com',
      password: 'password123',
    });

    expect(mockSignIn).toHaveBeenCalledWith(
      'http://localhost:14242',
      'admin@test.com',
      'password123',
    );
    expect(mockSaveSession).toHaveBeenCalledWith('http://localhost:14242', fakeAuth);
    expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('admin@test.com'));
  });

  it('propagates signIn errors', async () => {
    mockSignIn.mockRejectedValueOnce(new Error('Sign-in failed (401): invalid credentials'));

    await expect(
      runLogin({ gatewayUrl: 'http://localhost:14242', email: 'bad@test.com', password: 'wrong' }),
    ).rejects.toThrow('Sign-in failed (401)');
  });
});
