const swaggerJsdoc = require('swagger-jsdoc');
const swaggerUi = require('swagger-ui-express');

/**
 * Swagger/OpenAPI Configuration
 * Generates API documentation for the Overseas Appointment Backend
 */

const options = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: '海外预约小程序 API',
      version: '1.0.0',
      description: `
# 海外预约小程序后端 API 文档

本文档描述了海外预约小程序后端系统的所有 API 接口。

## 功能模块

- **认证模块**: 微信登录、Token刷新、登出
- **用户模块**: 用户信息管理、语言偏好设置
- **服务模块**: 服务分类、服务列表、服务详情
- **预约模块**: 创建预约、查询预约、更新预约、取消预约
- **通知模块**: 通知列表、标记已读、删除通知
- **邀请模块**: 生成邀请码、邀请统计、邀请记录
- **提现模块**: 申请提现、提现记录
- **文件上传**: 图片上传和处理
- **管理后台**: 用户管理、订单管理、提现审核、服务管理、统计分析、翻译管理

## 认证方式

大部分 API 需要 JWT Token 认证。在请求头中添加:
\`\`\`
Authorization: Bearer <your_token>
\`\`\`

## 多语言支持

系统支持三种语言: 中文(zh)、英文(en)、西班牙语(es)

可通过以下方式指定语言:
1. 请求头: \`Accept-Language: zh\`
2. 查询参数: \`?language=zh\`
3. 用户偏好设置
      `,
      contact: {
        name: 'API Support',
        email: 'support@example.com',
      },
      license: {
        name: 'ISC',
      },
    },
    servers: [
      {
        url: 'http://localhost:3000',
        description: '开发服务器',
      },
      {
        url: 'https://api.example.com',
        description: '生产服务器',
      },
    ],
    tags: [
      { name: 'Health', description: '健康检查' },
      { name: 'Auth', description: '用户认证' },
      { name: 'Users', description: '用户管理' },
      { name: 'Home', description: '首页内容（公开）' },
      { name: 'Services', description: '服务管理' },
      { name: 'Appointments', description: '预约管理' },
      { name: 'Notifications', description: '通知管理' },
      { name: 'Invitations', description: '邀请奖励' },
      { name: 'Withdrawals', description: '提现管理' },
      { name: 'Upload', description: '文件上传' },
      { name: 'Config', description: '公开配置' },
      { name: 'Admin Auth', description: '管理员认证' },
      { name: 'Admin Users', description: '管理后台 - 用户管理' },
      { name: 'Admin Appointments', description: '管理后台 - 订单管理' },
      { name: 'Admin Withdrawals', description: '管理后台 - 提现审核' },
      { name: 'Admin Categories', description: '管理后台 - 分类管理' },
      { name: 'Admin Services', description: '管理后台 - 服务管理' },
      { name: 'Admin Home', description: '管理后台 - 首页内容管理' },
      { name: 'Admin Statistics', description: '管理后台 - 统计分析' },
      { name: 'Admin Translations', description: '管理后台 - 翻译管理' },
      { name: 'Admin - Config', description: '管理后台 - 系统配置' },
    ],
    components: {
      securitySchemes: {
        bearerAuth: {
          type: 'http',
          scheme: 'bearer',
          bearerFormat: 'JWT',
          description: 'JWT Token 认证',
        },
      },
      schemas: {
        // Common response schemas
        SuccessResponse: {
          type: 'object',
          properties: {
            success: { type: 'boolean', example: true },
            data: { type: 'object' },
          },
        },
        ErrorResponse: {
          type: 'object',
          properties: {
            success: { type: 'boolean', example: false },
            error: {
              type: 'object',
              properties: {
                code: { type: 'string', example: 'INVALID_INPUT' },
                message: { type: 'string', example: 'Validation failed' },
                details: { type: 'object' },
              },
            },
          },
        },
        PaginationMeta: {
          type: 'object',
          properties: {
            page: { type: 'integer', example: 1 },
            limit: { type: 'integer', example: 10 },
            total: { type: 'integer', example: 100 },
            totalPages: { type: 'integer', example: 10 },
          },
        },

        // User schemas
        User: {
          type: 'object',
          properties: {
            id: { type: 'string', format: 'uuid', example: '550e8400-e29b-41d4-a716-446655440000' },
            wechatOpenId: { type: 'string', example: 'oXXXX-XXXXX' },
            nickname: { type: 'string', example: '用户昵称' },
            avatar: { type: 'string', example: 'https://example.com/avatar.jpg' },
            realName: { type: 'string', example: '张三' },
            phone: { type: 'string', example: '+86 13800138000' },
            whatsapp: { type: 'string', example: '+1 234 567 8900' },
            wechatId: { type: 'string', example: 'wxid_xxxxx' },
            language: { type: 'string', enum: ['zh', 'en', 'es'], example: 'zh' },
            balance: { type: 'number', format: 'decimal', example: 100.50 },
            invitationCode: { type: 'string', example: 'ABC123' },
            status: { type: 'string', enum: ['active', 'suspended'], example: 'active' },
            createdAt: { type: 'string', format: 'date-time' },
            updatedAt: { type: 'string', format: 'date-time' },
          },
        },
        // Category schema
        Category: {
          type: 'object',
          properties: {
            id: { type: 'string', format: 'uuid' },
            key: { type: 'string', example: 'airport' },
            nameZh: { type: 'string', example: '机场接送' },
            nameEn: { type: 'string', example: 'Airport Transfer' },
            nameEs: { type: 'string', example: 'Transferencia del Aeropuerto' },
            icon: { type: 'string', example: 'airport-icon.png' },
            sortOrder: { type: 'integer', example: 1 },
          },
        },
        // Service schema
        Service: {
          type: 'object',
          properties: {
            id: { type: 'string', format: 'uuid' },
            categoryId: { type: 'string', format: 'uuid' },
            serviceType: {
              type: 'string',
              description: '服务具体类型，用于跳转对应预约表单',
              enum: ['flight', 'hotel', 'lounge', 'airport_transfer', 'unaccompanied_minor', 'train', 'telemedicine', 'special_passenger', 'pet_transport', 'guide_translation', 'visa', 'exhibition', 'air_logistics', 'sea_freight', 'travel_planning', 'insurance'],
              example: 'flight',
            },
            titleZh: { type: 'string', example: '机场接机服务' },
            titleEn: { type: 'string', example: 'Airport Pickup Service' },
            titleEs: { type: 'string', example: 'Servicio de Recogida en el Aeropuerto' },
            descriptionZh: { type: 'string' },
            descriptionEn: { type: 'string' },
            descriptionEs: { type: 'string' },
            image: { type: 'string', example: '/uploads/service.jpg' },
            price: { type: 'number', format: 'decimal', example: 299.00 },
            status: { type: 'string', enum: ['active', 'inactive'], example: 'active' },
            sortOrder: { type: 'integer', example: 1 },
          },
        },
        // ServiceType enum reference
        ServiceType: {
          type: 'string',
          description: '服务具体类型枚举',
          enum: ['flight', 'hotel', 'lounge', 'airport_transfer', 'unaccompanied_minor', 'train', 'telemedicine', 'special_passenger', 'pet_transport', 'guide_translation', 'visa', 'exhibition', 'air_logistics', 'sea_freight', 'travel_planning', 'insurance'],
          'x-enum-descriptions': {
            flight: '全球机票代理',
            hotel: '全球酒店预定',
            lounge: '全球机场贵宾室服务',
            airport_transfer: '机场接/送机服务',
            unaccompanied_minor: '无成人陪伴儿童代办',
            train: '高铁票代订',
            telemedicine: '远程医疗问诊代理服务',
            special_passenger: '特殊（特护）旅客定制服务代办',
            pet_transport: '宠物托运代理',
            guide_translation: '西班牙语专业导游/翻译服务',
            visa: '签证咨询',
            exhibition: '墨西哥展会咨询与协办服务',
            air_logistics: '跨境航空物流/快递一站式服务',
            sea_freight: '海运/清关一站式服务',
            travel_planning: '旅游线路规划/咨询',
            insurance: '跨境出行意外保险/国际财产保险咨询',
          },
        },
        // Banner schema
        Banner: {
          type: 'object',
          properties: {
            id: { type: 'integer', example: 1 },
            image_url: { type: 'string', example: '/uploads/banner1.jpg' },
            link_url: { type: 'string', example: '/pages/service-detail/service-detail?id=xxx' },
            sort_order: { type: 'integer', example: 0 },
            is_active: { type: 'boolean', example: true },
            created_at: { type: 'string', format: 'date-time' },
            updated_at: { type: 'string', format: 'date-time' },
          },
        },
        // HotService schema
        HotService: {
          type: 'object',
          properties: {
            id: { type: 'integer', example: 1 },
            name_zh: { type: 'string', example: '全球机票代理' },
            name_en: { type: 'string', example: 'Global Flight Booking' },
            name_es: { type: 'string', example: 'Reserva de Vuelos Global' },
            service_type: {
              type: 'string',
              description: '服务具体类型',
              enum: ['flight', 'hotel', 'lounge', 'airport_transfer', 'unaccompanied_minor', 'train', 'telemedicine', 'special_passenger', 'pet_transport', 'guide_translation', 'visa', 'exhibition', 'air_logistics', 'sea_freight', 'travel_planning', 'insurance'],
              example: 'flight',
            },
            image_url: { type: 'string', example: '/uploads/hot-service1.jpg' },
            detail_image: { type: 'string', example: '/uploads/hot-service1-detail.jpg' },
            link_url: { type: 'string' },
            sort_order: { type: 'integer', example: 0 },
            is_active: { type: 'boolean', example: true },
            created_at: { type: 'string', format: 'date-time' },
            updated_at: { type: 'string', format: 'date-time' },
          },
        },
        // Appointment schema
        Appointment: {
          type: 'object',
          properties: {
            id: { type: 'string', format: 'uuid' },
            userId: { type: 'string', format: 'uuid' },
            serviceId: { type: 'string', format: 'uuid' },
            appointmentNo: { type: 'string', example: 'APT20231201001' },
            realName: { type: 'string', example: '张三' },
            contactMethod: { type: 'string', enum: ['phone', 'whatsapp', 'wechat'], example: 'phone' },
            contactValue: { type: 'string', example: '+86 13800138000' },
            appointmentDate: { type: 'string', format: 'date', example: '2023-12-15' },
            appointmentTime: { type: 'string', example: '14:30' },
            notes: { type: 'string', example: '请准时到达' },
            status: { type: 'string', enum: ['pending', 'confirmed', 'in-progress', 'completed', 'cancelled'], example: 'pending' },
            amount: { type: 'number', format: 'decimal', example: 299.00 },
            paidAt: { type: 'string', format: 'date-time' },
            createdAt: { type: 'string', format: 'date-time' },
            updatedAt: { type: 'string', format: 'date-time' },
          },
        },
        // Notification schema
        Notification: {
          type: 'object',
          properties: {
            id: { type: 'string', format: 'uuid' },
            userId: { type: 'string', format: 'uuid' },
            type: { type: 'string', enum: ['system', 'activity', 'service'], example: 'system' },
            titleZh: { type: 'string', example: '系统通知' },
            titleEn: { type: 'string', example: 'System Notification' },
            titleEs: { type: 'string', example: 'Notificación del Sistema' },
            contentZh: { type: 'string' },
            contentEn: { type: 'string' },
            contentEs: { type: 'string' },
            isRead: { type: 'boolean', example: false },
            readAt: { type: 'string', format: 'date-time' },
            createdAt: { type: 'string', format: 'date-time' },
          },
        },
        // Invitation schema
        Invitation: {
          type: 'object',
          properties: {
            id: { type: 'string', format: 'uuid' },
            inviterId: { type: 'string', format: 'uuid' },
            inviteeId: { type: 'string', format: 'uuid' },
            invitationCode: { type: 'string', example: 'ABC123' },
            registeredAt: { type: 'string', format: 'date-time' },
            firstPaymentAt: { type: 'string', format: 'date-time' },
            firstPaymentAmount: { type: 'number', format: 'decimal', example: 299.00 },
            rewardAmount: { type: 'number', format: 'decimal', example: 29.90 },
            rewardStatus: { type: 'string', enum: ['pending', 'credited', 'cancelled'], example: 'pending' },
          },
        },
        // Withdrawal schema
        Withdrawal: {
          type: 'object',
          properties: {
            id: { type: 'string', format: 'uuid' },
            userId: { type: 'string', format: 'uuid' },
            withdrawalNo: { type: 'string', example: 'WD20231201001' },
            amount: { type: 'number', format: 'decimal', example: 100.00 },
            paymentMethod: { type: 'string', enum: ['wechat', 'alipay', 'bank'], example: 'wechat' },
            paymentDetails: { type: 'object' },
            status: { type: 'string', enum: ['waiting', 'processing', 'completed', 'rejected'], example: 'waiting' },
            reviewedBy: { type: 'string', format: 'uuid' },
            reviewedAt: { type: 'string', format: 'date-time' },
            rejectionReason: { type: 'string' },
            completedAt: { type: 'string', format: 'date-time' },
            createdAt: { type: 'string', format: 'date-time' },
          },
        },
        // Admin schema
        Admin: {
          type: 'object',
          properties: {
            id: { type: 'string', format: 'uuid' },
            username: { type: 'string', example: 'admin' },
            email: { type: 'string', format: 'email', example: 'admin@example.com' },
            role: { type: 'string', enum: ['super_admin', 'admin', 'operator'], example: 'admin' },
            status: { type: 'string', enum: ['active', 'inactive'], example: 'active' },
            lastLoginAt: { type: 'string', format: 'date-time' },
          },
        },
      },
    },
  },
  apis: ['./src/docs/*.js'], // Path to the API docs
};

const swaggerSpec = swaggerJsdoc(options);

/**
 * Setup Swagger UI middleware
 * @param {Express} app - Express application
 */
const setupSwagger = (app) => {
  // Swagger UI options
  const swaggerUiOptions = {
    explorer: true,
    customCss: '.swagger-ui .topbar { display: none }',
    customSiteTitle: '海外预约小程序 API 文档',
  };

  // Serve Swagger UI
  app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, swaggerUiOptions));

  // Serve OpenAPI spec as JSON
  app.get('/api-docs.json', (req, res) => {
    res.setHeader('Content-Type', 'application/json');
    res.send(swaggerSpec);
  });

  // Serve OpenAPI spec as YAML
  app.get('/api-docs.yaml', (req, res) => {
    const yaml = require('swagger-jsdoc/node_modules/yaml');
    res.setHeader('Content-Type', 'text/yaml');
    res.send(yaml.stringify(swaggerSpec));
  });
};

/**
 * Generate Postman Collection from OpenAPI spec
 * @returns {Object} Postman Collection
 */
const generatePostmanCollection = () => {
  const collection = {
    info: {
      name: '海外预约小程序 API',
      description: swaggerSpec.info.description,
      schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json',
    },
    auth: {
      type: 'bearer',
      bearer: [
        {
          key: 'token',
          value: '{{access_token}}',
          type: 'string',
        },
      ],
    },
    variable: [
      {
        key: 'base_url',
        value: 'http://localhost:3000',
        type: 'string',
      },
      {
        key: 'access_token',
        value: '',
        type: 'string',
      },
    ],
    item: [],
  };

  // Group endpoints by tags
  const tagGroups = {};
  swaggerSpec.tags.forEach((tag) => {
    tagGroups[tag.name] = {
      name: tag.name,
      description: tag.description,
      item: [],
    };
  });

  // Convert paths to Postman items
  Object.entries(swaggerSpec.paths || {}).forEach(([path, methods]) => {
    Object.entries(methods).forEach(([method, spec]) => {
      const tag = spec.tags?.[0] || 'Other';
      const item = {
        name: spec.summary || path,
        request: {
          method: method.toUpperCase(),
          header: [
            {
              key: 'Content-Type',
              value: 'application/json',
            },
            {
              key: 'Accept-Language',
              value: 'zh',
            },
          ],
          url: {
            raw: `{{base_url}}${path}`,
            host: ['{{base_url}}'],
            path: path.split('/').filter(Boolean),
          },
          description: spec.description,
        },
      };

      // Add request body if present
      if (spec.requestBody?.content?.['application/json']?.schema) {
        item.request.body = {
          mode: 'raw',
          raw: JSON.stringify(spec.requestBody.content['application/json'].example || {}, null, 2),
        };
      }

      // Add query parameters
      if (spec.parameters) {
        const queryParams = spec.parameters.filter((p) => p.in === 'query');
        if (queryParams.length > 0) {
          item.request.url.query = queryParams.map((p) => ({
            key: p.name,
            value: p.example || '',
            description: p.description,
            disabled: !p.required,
          }));
        }
      }

      if (tagGroups[tag]) {
        tagGroups[tag].item.push(item);
      }
    });
  });

  collection.item = Object.values(tagGroups).filter((g) => g.item.length > 0);
  return collection;
};

module.exports = {
  swaggerSpec,
  setupSwagger,
  generatePostmanCollection,
};
