import { OpenAPIHono } from '@hono/zod-openapi';
import { Hono } from 'hono';
import { vi } from 'vitest';

/**
 * 创建测试服务器实例
 */
export function createTestServer(app: OpenAPIHono | Hono) {
  const server = app as any;

  return {
    get: (path: string) => makeRequest('GET', path),
    post: (path: string, body?: any) => makeRequest('POST', path, body),
    put: (path: string, body?: any) => makeRequest('PUT', path, body),
    delete: (path: string) => makeRequest('DELETE', path),
    patch: (path: string, body?: any) => makeRequest('PATCH', path, body)
  };

  async function makeRequest(method: string, path: string, body?: any) {
    const url = new URL(path, 'http://localhost:8080');

    const request = new Request(url.toString(), {
      method,
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer mock-token',
      },
      body: body ? JSON.stringify(body) : undefined,
    });

    try {
      const response = await server.fetch(request);
      return {
        status: response.status,
        headers: response.headers,
        json: async () => response.json(),
        text: async () => response.text()
      };
    } catch (error) {
      throw new Error(`Request failed: ${error}`);
    }
  }
}

/**
 * 创建模拟的认证上下文
 */
export function createMockAuthContext() {
  return {
    req: {
      header: (name: string) => {
        if (name === 'authorization') return 'Bearer mock-token';
        return null;
      }
    },
    set: vi.fn(),
    json: vi.fn().mockImplementation((data, status = 200) => ({
      status,
      body: data
    })),
    env: {},
    var: {}
  };
}

/**
 * 创建模拟的用户实体
 */
export function createMockUser(overrides: Partial<any> = {}) {
  return {
    id: 1,
    username: 'testuser',
    email: 'test@example.com',
    password: 'hashed_password',
    phone: '13800138000',
    nickname: 'Test User',
    status: 1,
    createdAt: new Date(),
    updatedAt: new Date(),
    roles: [],
    ...overrides
  };
}

/**
 * 等待指定时间
 */
export function wait(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}