import { describe, expect, it, vi } from 'vitest';
import { createK8sTools } from './k8s.js';
import type { K8sConfig } from '../../config/index.js';

function makeConfig(overrides?: Partial<NonNullable<K8sConfig>>): NonNullable<K8sConfig> {
  return {
    enabled: true,
    kubectl_path: 'kubectl',
    default_namespace: 'default',
    allowed_namespaces: [],
    ...overrides,
  };
}

describe('createK8sTools', () => {
  it('lists pods', async () => {
    const runner = vi.fn(async () => ({
      stdout: JSON.stringify({
        items: [{
          metadata: { namespace: 'default', name: 'api-123' },
          status: {
            phase: 'Running',
            containerStatuses: [{ ready: true, restartCount: 1 }],
          },
        }],
      }),
      stderr: '',
    }));
    const tools = createK8sTools(makeConfig(), { runner });
    const podsTool = tools.find((t) => t.name === 'k8s.pods');
    if (!podsTool) {throw new Error('k8s.pods tool missing');}

    const result = await podsTool.execute({});
    expect(result.success).toBe(true);
    expect(result.output).toContain('default/api-123');
    expect(result.output).toContain('phase=Running');
    expect(runner).toHaveBeenCalledWith('kubectl', ['get', 'pods', '-o', 'json', '-n', 'default'], expect.any(Object));
  });

  it('lists deployments across all namespaces', async () => {
    const runner = vi.fn(async () => ({
      stdout: JSON.stringify({
        items: [{
          metadata: { namespace: 'ops', name: 'worker' },
          spec: { replicas: 3 },
          status: { readyReplicas: 2, availableReplicas: 2 },
        }],
      }),
      stderr: '',
    }));
    const tools = createK8sTools(makeConfig(), { runner });
    const tool = tools.find((t) => t.name === 'k8s.deployments');
    if (!tool) {throw new Error('k8s.deployments tool missing');}

    const result = await tool.execute({ all_namespaces: true });
    expect(result.success).toBe(true);
    expect(result.output).toContain('ops/worker');
    expect(result.output).toContain('replicas=2/3');
  });

  it('fetches logs with tail + since', async () => {
    const runner = vi.fn(async () => ({
      stdout: 'line1\nline2\n',
      stderr: '',
    }));
    const tools = createK8sTools(makeConfig({ default_namespace: 'ops' }), { runner });
    const tool = tools.find((t) => t.name === 'k8s.logs');
    if (!tool) {throw new Error('k8s.logs tool missing');}

    const result = await tool.execute({ pod: 'api-123', lines: 50, since: '10m' });
    expect(result.success).toBe(true);
    expect(result.output).toContain('line1');
    expect(runner).toHaveBeenCalledWith(
      'kubectl',
      ['logs', 'api-123', '--tail', '50', '-n', 'ops', '--since', '10m'],
      expect.any(Object),
    );
  });

  it('blocks unauthorized namespaces', async () => {
    const runner = vi.fn();
    const tools = createK8sTools(makeConfig({ allowed_namespaces: ['observability'] }), { runner });
    const tool = tools.find((t) => t.name === 'k8s.logs');
    if (!tool) {throw new Error('k8s.logs tool missing');}

    const result = await tool.execute({ pod: 'api-123', namespace: 'default' });
    expect(result.success).toBe(false);
    expect(result.error).toContain('not allowed');
    expect(runner).not.toHaveBeenCalled();
  });
});
