// 高级 Hyperdrive 使用示例 - 完整的 CRUD API
// 这个示例展示了如何构建一个生产级别的 API 服务

export interface Env {
  HYPERDRIVE: Hyperdrive;
  API_SECRET?: string;
}

interface User {
  id?: number;
  name: string;
  email: string;
  created_at?: string;
  updated_at?: string;
}

interface ApiResponse<T = any> {
  status: 'success' | 'error';
  data?: T;
  message?: string;
  meta?: {
    total?: number;
    page?: number;
    limit?: number;
  };
}

// CORS 配置
const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-API-Key',
};

// 响应工具函数
function jsonResponse<T>(data: ApiResponse<T>, status = 200): Response {
  return new Response(JSON.stringify(data, null, 2), {
    status,
    headers: {
      'Content-Type': 'application/json',
      ...corsHeaders,
    },
  });
}

// 错误响应
function errorResponse(message: string, status = 500): Response {
  return jsonResponse({ status: 'error', message }, status);
}

// 输入验证
function validateUser(data: any): { valid: boolean; errors: string[] } {
  const errors: string[] = [];
  
  if (!data.name || typeof data.name !== 'string' || data.name.trim().length < 2) {
    errors.push('Name must be at least 2 characters');
  }
  
  if (!data.email || typeof data.email !== 'string' || !data.email.includes('@')) {
    errors.push('Valid email is required');
  }
  
  return { valid: errors.length === 0, errors };
}

// API 密钥验证
function validateApiKey(request: Request, env: Env): boolean {
  if (!env.API_SECRET) return true; // 如果没有设置密钥，跳过验证
  
  const apiKey = request.headers.get('X-API-Key') || request.headers.get('Authorization')?.replace('Bearer ', '');
  return apiKey === env.API_SECRET;
}

// 数据库连接工具
async function withDatabase<T>(env: Env, operation: (client: any) => Promise<T>): Promise<T> {
  const { Client } = await import('pg');
  const client = new Client({ connectionString: env.HYPERDRIVE.connectionString });
  
  try {
    await client.connect();
    return await operation(client);
  } finally {
    await client.end();
  }
}

// 用户 CRUD 操作
class UserService {
  static async getUsers(env: Env, page = 1, limit = 10, search?: string): Promise<{ users: User[]; total: number }> {
    return withDatabase(env, async (client) => {
      let query = 'SELECT id, name, email, created_at, updated_at FROM users';
      let countQuery = 'SELECT COUNT(*) FROM users';
      const params: any[] = [];
      
      if (search) {
        query += ' WHERE name ILIKE $1 OR email ILIKE $1';
        countQuery += ' WHERE name ILIKE $1 OR email ILIKE $1';
        params.push(`%${search}%`);
      }
      
      query += ` ORDER BY created_at DESC LIMIT $${params.length + 1} OFFSET $${params.length + 2}`;
      params.push(limit, (page - 1) * limit);
      
      const [usersResult, countResult] = await Promise.all([
        client.query(query, params),
        client.query(countQuery, search ? [`%${search}%`] : [])
      ]);
      
      return {
        users: usersResult.rows,
        total: parseInt(countResult.rows[0].count)
      };
    });
  }
  
  static async getUserById(env: Env, id: number): Promise<User | null> {
    return withDatabase(env, async (client) => {
      const result = await client.query(
        'SELECT id, name, email, created_at, updated_at FROM users WHERE id = $1',
        [id]
      );
      return result.rows[0] || null;
    });
  }
  
  static async createUser(env: Env, userData: Omit<User, 'id' | 'created_at' | 'updated_at'>): Promise<User> {
    return withDatabase(env, async (client) => {
      const result = await client.query(
        'INSERT INTO users (name, email, created_at, updated_at) VALUES ($1, $2, NOW(), NOW()) RETURNING id, name, email, created_at, updated_at',
        [userData.name.trim(), userData.email.toLowerCase().trim()]
      );
      return result.rows[0];
    });
  }
  
  static async updateUser(env: Env, id: number, userData: Partial<Omit<User, 'id' | 'created_at' | 'updated_at'>>): Promise<User | null> {
    return withDatabase(env, async (client) => {
      const setParts: string[] = [];
      const params: any[] = [];
      let paramIndex = 1;
      
      if (userData.name !== undefined) {
        setParts.push(`name = $${paramIndex++}`);
        params.push(userData.name.trim());
      }
      
      if (userData.email !== undefined) {
        setParts.push(`email = $${paramIndex++}`);
        params.push(userData.email.toLowerCase().trim());
      }
      
      if (setParts.length === 0) {
        throw new Error('No fields to update');
      }
      
      setParts.push(`updated_at = NOW()`);
      params.push(id);
      
      const result = await client.query(
        `UPDATE users SET ${setParts.join(', ')} WHERE id = $${paramIndex} RETURNING id, name, email, created_at, updated_at`,
        params
      );
      
      return result.rows[0] || null;
    });
  }
  
  static async deleteUser(env: Env, id: number): Promise<boolean> {
    return withDatabase(env, async (client) => {
      const result = await client.query('DELETE FROM users WHERE id = $1', [id]);
      return result.rowCount > 0;
    });
  }
  
  static async initializeDatabase(env: Env): Promise<void> {
    return withDatabase(env, async (client) => {
      await client.query(`
        CREATE TABLE IF NOT EXISTS users (
          id SERIAL PRIMARY KEY,
          name VARCHAR(255) NOT NULL,
          email VARCHAR(255) UNIQUE NOT NULL,
          created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
          updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
        )
      `);
      
      // 创建索引
      await client.query('CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)');
      await client.query('CREATE INDEX IF NOT EXISTS idx_users_created_at ON users(created_at)');
    });
  }
}

// 路由处理
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);
    const path = url.pathname;
    const method = request.method;
    
    // 处理 CORS 预检请求
    if (method === 'OPTIONS') {
      return new Response(null, { headers: corsHeaders });
    }
    
    // API 密钥验证
    if (!validateApiKey(request, env)) {
      return errorResponse('Unauthorized', 401);
    }
    
    try {
      // 路由匹配
      if (path === '/init' && method === 'POST') {
        await UserService.initializeDatabase(env);
        return jsonResponse({ status: 'success', message: 'Database initialized' });
      }
      
      if (path === '/users' && method === 'GET') {
        const page = parseInt(url.searchParams.get('page') || '1');
        const limit = Math.min(parseInt(url.searchParams.get('limit') || '10'), 100);
        const search = url.searchParams.get('search') || undefined;
        
        const { users, total } = await UserService.getUsers(env, page, limit, search);
        
        return jsonResponse({
          status: 'success',
          data: users,
          meta: {
            total,
            page,
            limit,
          }
        });
      }
      
      if (path.match(/^\/users\/\d+$/) && method === 'GET') {
        const id = parseInt(path.split('/')[2]);
        const user = await UserService.getUserById(env, id);
        
        if (!user) {
          return errorResponse('User not found', 404);
        }
        
        return jsonResponse({ status: 'success', data: user });
      }
      
      if (path === '/users' && method === 'POST') {
        const body = await request.json() as any;
        const validation = validateUser(body);
        
        if (!validation.valid) {
          return errorResponse(`Validation failed: ${validation.errors.join(', ')}`, 400);
        }
        
        const user = await UserService.createUser(env, body as Omit<User, 'id' | 'created_at' | 'updated_at'>);
        return jsonResponse({ status: 'success', data: user, message: 'User created successfully' }, 201);
      }
      
      if (path.match(/^\/users\/\d+$/) && method === 'PUT') {
        const id = parseInt(path.split('/')[2]);
        const body = await request.json() as any;
        
        // 部分验证（只验证提供的字段）
        if (body.name !== undefined || body.email !== undefined) {
          const validation = validateUser({ name: body.name || 'valid', email: body.email || 'valid@email.com' });
          if (!validation.valid) {
            return errorResponse(`Validation failed: ${validation.errors.join(', ')}`, 400);
          }
        }
        
        const user = await UserService.updateUser(env, id, body as Partial<Omit<User, 'id' | 'created_at' | 'updated_at'>>);
        
        if (!user) {
          return errorResponse('User not found', 404);
        }
        
        return jsonResponse({ status: 'success', data: user, message: 'User updated successfully' });
      }
      
      if (path.match(/^\/users\/\d+$/) && method === 'DELETE') {
        const id = parseInt(path.split('/')[2]);
        const deleted = await UserService.deleteUser(env, id);
        
        if (!deleted) {
          return errorResponse('User not found', 404);
        }
        
        return jsonResponse({ status: 'success', message: 'User deleted successfully' });
      }
      
      // 健康检查
      if (path === '/health') {
        return jsonResponse({
          status: 'success',
          data: {
            service: 'hyperdrive-api',
            timestamp: new Date().toISOString(),
            version: '1.0.0'
          }
        });
      }
      
      // API 文档
      if (path === '/docs') {
        const docs = {
          endpoints: {
            'POST /init': 'Initialize database tables',
            'GET /users': 'List users (supports ?page, ?limit, ?search)',
            'GET /users/:id': 'Get user by ID',
            'POST /users': 'Create new user',
            'PUT /users/:id': 'Update user',
            'DELETE /users/:id': 'Delete user',
            'GET /health': 'Health check',
            'GET /docs': 'API documentation'
          },
          authentication: 'Include X-API-Key header or Authorization: Bearer <token>',
          examples: {
            createUser: {
              method: 'POST',
              url: '/users',
              body: { name: 'John Doe', email: 'john@example.com' }
            },
            listUsers: {
              method: 'GET',
              url: '/users?page=1&limit=10&search=john'
            }
          }
        };
        
        return jsonResponse({ status: 'success', data: docs });
      }
      
      return errorResponse('Not found', 404);
      
    } catch (error) {
      console.error('API Error:', error);
      return errorResponse('Internal server error', 500);
    }
  },
};