import { logger } from '@goodgo/logger';
import { Application } from 'express';
import swaggerJSDoc from 'swagger-jsdoc';
import swaggerUi from 'swagger-ui-express';

import { appConfig } from '../config/app.config';

/**
 * EN: Swagger/OpenAPI configuration for API documentation
 * VI: Cấu hình Swagger/OpenAPI cho tài liệu API
 */

const options = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'Microservice Template API',
      version: '1.0.0',
      description: 'A production-ready microservice template with comprehensive features',
      contact: {
        name: 'Development Team',
        email: 'dev@goodgo.com',
      },
      license: {
        name: 'MIT',
        url: 'https://opensource.org/licenses/MIT',
      },
    },
    servers: [
      {
        url: 'http://localhost:{port}',
        description: 'Development server',
        variables: {
          port: {
            default: String(appConfig.port),
            description: 'Port number for the development server',
          },
        },
      },
      {
        url: 'https://api.example.com',
        description: 'Production server',
      },
    ],
    components: {
      securitySchemes: {
        bearerAuth: {
          type: 'http',
          scheme: 'bearer',
          bearerFormat: 'JWT',
          description: 'JWT Authorization header using the Bearer scheme',
        },
      },
      schemas: {
        ApiResponse: {
          type: 'object',
          properties: {
            success: {
              type: 'boolean',
              description: 'Indicates if the request was successful',
            },
            data: {
              description: 'Response data (varies by endpoint)',
            },
            message: {
              type: 'string',
              description: 'Human-readable message',
            },
            timestamp: {
              type: 'string',
              format: 'date-time',
              description: 'ISO 8601 timestamp of the response',
            },
          },
          required: ['success', 'timestamp'],
        },
        ErrorResponse: {
          type: 'object',
          properties: {
            success: {
              type: 'boolean',
              example: false,
            },
            error: {
              type: 'object',
              properties: {
                code: {
                  type: 'string',
                  description: 'Error code for programmatic handling',
                  example: 'VALIDATION_ERROR',
                },
                message: {
                  type: 'string',
                  description: 'Human-readable error message',
                  example: 'Validation failed',
                },
                details: {
                  description: 'Additional error details (optional)',
                },
              },
              required: ['code', 'message'],
            },
            timestamp: {
              type: 'string',
              format: 'date-time',
            },
          },
          required: ['success', 'error', 'timestamp'],
        },
        RegisterRequest: {
          type: 'object',
          properties: {
            email: { type: 'string', format: 'email', example: 'user@example.com' },
            password: { type: 'string', minLength: 8, example: 'StrongP@ssw0rd!' },
            username: { type: 'string', minLength: 3, example: 'johndoe' },
          },
          required: ['email', 'password'],
        },
        RegisterResponse: {
          type: 'object',
          properties: {
            user: { $ref: '#/components/schemas/User' },
            token: { type: 'string' },
          },
        },
        LoginRequest: {
          type: 'object',
          properties: {
            email: { type: 'string', format: 'email', example: 'user@example.com' },
            password: { type: 'string', example: 'StrongP@ssw0rd!' },
          },
          required: ['email', 'password'],
        },
        LoginResponse: {
          type: 'object',
          properties: {
            accessToken: { type: 'string' },
            refreshToken: { type: 'string' },
            user: { $ref: '#/components/schemas/User' },
          },
        },
        User: {
          type: 'object',
          properties: {
            id: { type: 'string', example: 'cuid12345' },
            email: { type: 'string', format: 'email' },
            username: { type: 'string' },
            firstName: { type: 'string' },
            lastName: { type: 'string' },
            isActive: { type: 'boolean' },
            isEmailVerified: { type: 'boolean' },
            createdAt: { type: 'string', format: 'date-time' },
            updatedAt: { type: 'string', format: 'date-time' },
          },
        },
        CreateUserRequest: {
          type: 'object',
          properties: {
            email: { type: 'string', format: 'email' },
            username: { type: 'string' },
            firstName: { type: 'string' },
            lastName: { type: 'string' },
            phone: { type: 'string' },
          },
          required: ['email'],
        },
        Organization: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            name: { type: 'string' },
            domain: { type: 'string' },
            isActive: { type: 'boolean' },
            parentId: { type: 'string' },
            createdAt: { type: 'string', format: 'date-time' },
            updatedAt: { type: 'string', format: 'date-time' },
          },
        },
        CreateOrganizationRequest: {
          type: 'object',
          properties: {
            name: { type: 'string' },
            domain: { type: 'string' },
            parentId: { type: 'string' },
            settings: { type: 'object' },
          },
          required: ['name'],
        },
        UpdateOrganizationRequest: {
          type: 'object',
          properties: {
            name: { type: 'string' },
            domain: { type: 'string' },
            parentId: { type: 'string' },
            settings: { type: 'object' },
            isActive: { type: 'boolean' },
          },
        },
        Group: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            name: { type: 'string' },
            description: { type: 'string' },
            organizationId: { type: 'string' },
            isActive: { type: 'boolean' },
            createdAt: { type: 'string', format: 'date-time' },
            updatedAt: { type: 'string', format: 'date-time' },
          },
        },
        CreateGroupRequest: {
          type: 'object',
          properties: {
            name: { type: 'string' },
            description: { type: 'string' },
            organizationId: { type: 'string' },
          },
          required: ['name'],
        },
        UpdateGroupRequest: {
          type: 'object',
          properties: {
            name: { type: 'string' },
            description: { type: 'string' },
            isActive: { type: 'boolean' },
          },
        },
        UserProfile: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            userId: { type: 'string' },
            avatarUrl: { type: 'string' },
            bio: { type: 'string' },
            phoneNumber: { type: 'string' },
            address: { type: 'string' },
            preferences: { type: 'object' },
          },
        },
        UpdateProfileRequest: {
          type: 'object',
          properties: {
            firstName: { type: 'string' },
            lastName: { type: 'string' },
            phone: { type: 'string' },
            avatarUrl: { type: 'string' },
            preferences: { type: 'object' },
          },
        },
        UpdateUserRequest: {
          type: 'object',
          properties: {
            username: { type: 'string' },
            email: { type: 'string', format: 'email' },
            isActive: { type: 'boolean' },
            organizationId: { type: 'string' },
          },
        },
        AccessRequest: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            resource: { type: 'string' },
            action: { type: 'string' },
            status: { type: 'string', enum: ['PENDING', 'APPROVED', 'REJECTED'] },
            reason: { type: 'string' },
            requesterId: { type: 'string' },
            createdAt: { type: 'string', format: 'date-time' },
          },
        },
        CreateAccessRequest: {
          type: 'object',
          properties: {
            resource: { type: 'string' },
            action: { type: 'string' },
            reason: { type: 'string' },
            expiresAt: { type: 'string', format: 'date-time' },
          },
          required: ['resource', 'action'],
        },
        AccessReview: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            name: { type: 'string' },
            status: { type: 'string' },
            type: { type: 'string' },
            startDate: { type: 'string', format: 'date-time' },
            endDate: { type: 'string', format: 'date-time' },
          },
        },
        CreateAccessReviewRequest: {
          type: 'object',
          properties: {
            name: { type: 'string' },
            type: { type: 'string', enum: ['PERIODIC', 'ADHOC'] },
            startDate: { type: 'string', format: 'date-time' },
            endDate: { type: 'string', format: 'date-time' },
          },
          required: ['name', 'type'],
        },
        Policy: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            name: { type: 'string' },
            type: { type: 'string' },
            content: { type: 'object' },
            isActive: { type: 'boolean' },
          },
        },
        ComplianceReport: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            type: { type: 'string' },
            status: { type: 'string' },
            generatedAt: { type: 'string', format: 'date-time' },
            url: { type: 'string' },
          },
        },
        GenerateComplianceReportRequest: {
          type: 'object',
          properties: {
            type: { type: 'string' },
            periodStart: { type: 'string', format: 'date-time' },
            periodEnd: { type: 'string', format: 'date-time' },
          },
          required: ['type'],
        },
        Session: {
          type: 'object',
          properties: {
            id: { type: 'string' },
            userId: { type: 'string' },
            deviceId: { type: 'string' },
            deviceName: { type: 'string' },
            ipAddress: { type: 'string' },
            userAgent: { type: 'string' },
            isActive: { type: 'boolean' },
            expiresAt: { type: 'string', format: 'date-time' },
            createdAt: { type: 'string', format: 'date-time' },
            lastActivityAt: { type: 'string', format: 'date-time' },
          },
        },
        Feature: {
          type: 'object',
          properties: {
            id: {
              type: 'string',
              description: 'Unique identifier',
              example: 'clh1x8qkq0000abcdefghijk',
            },
            name: {
              type: 'string',
              description: 'Unique feature name',
              example: 'user-management',
            },
            title: {
              type: 'string',
              description: 'Human-readable title',
              example: 'User Management',
            },
            description: {
              type: 'string',
              description: 'Detailed description',
              example: 'Complete user management system',
            },
            config: {
              type: 'object',
              description: 'Feature-specific configuration',
              example: { enabled: true, priority: 1 },
            },
            enabled: {
              type: 'boolean',
              description: 'Whether the feature is enabled',
              example: true,
            },
            version: {
              type: 'string',
              description: 'Feature version',
              example: '1.0.0',
            },
            tags: {
              type: 'array',
              items: { type: 'string' },
              description: 'Categorization tags',
              example: ['auth', 'users'],
            },
            createdAt: {
              type: 'string',
              format: 'date-time',
              description: 'Creation timestamp',
            },
            updatedAt: {
              type: 'string',
              format: 'date-time',
              description: 'Last update timestamp',
            },
          },
          required: ['id', 'name', 'enabled', 'tags', 'createdAt', 'updatedAt'],
        },
        CreateFeatureRequest: {
          type: 'object',
          properties: {
            name: {
              type: 'string',
              minLength: 1,
              maxLength: 100,
              description: 'Unique feature name',
              example: 'new-feature',
            },
            title: {
              type: 'string',
              maxLength: 200,
              description: 'Human-readable title',
              example: 'New Feature',
            },
            description: {
              type: 'string',
              maxLength: 1000,
              description: 'Detailed description',
              example: 'A new feature for the system',
            },
            config: {
              type: 'object',
              description: 'Feature configuration',
              example: { enabled: true },
            },
            tags: {
              type: 'array',
              items: { type: 'string' },
              description: 'Categorization tags',
              example: ['feature', 'new'],
            },
          },
          required: ['name'],
        },
        UpdateFeatureRequest: {
          type: 'object',
          properties: {
            title: {
              type: 'string',
              maxLength: 200,
              description: 'Human-readable title',
            },
            description: {
              type: 'string',
              maxLength: 1000,
              description: 'Detailed description',
            },
            config: {
              type: 'object',
              description: 'Feature configuration',
            },
            enabled: {
              type: 'boolean',
              description: 'Whether the feature is enabled',
            },
            tags: {
              type: 'array',
              items: { type: 'string' },
              description: 'Categorization tags',
            },
          },
        },
        UserInfo: {
          type: 'object',
          properties: {
            userId: {
              type: 'string',
              description: 'Unique user identifier',
              example: 'user-123',
            },
            email: {
              type: 'string',
              format: 'email',
              description: 'User email address',
              example: 'user@example.com',
            },
            role: {
              type: 'string',
              description: 'User role',
              example: 'admin',
              enum: ['admin', 'user', 'moderator'],
            },
            iat: {
              type: 'number',
              description: 'Token issued at timestamp',
            },
            exp: {
              type: 'number',
              description: 'Token expiration timestamp',
            },
          },
          required: ['userId', 'email', 'role'],
        },
        HealthResponse: {
          type: 'object',
          properties: {
            success: { type: 'boolean', example: true },
            data: {
              type: 'object',
              properties: {
                status: { type: 'string', example: 'ok' },
                timestamp: { type: 'string', format: 'date-time' },
              },
            },
            timestamp: { type: 'string', format: 'date-time' },
          },
        },
        ReadinessResponse: {
          type: 'object',
          properties: {
            success: { type: 'boolean', example: true },
            data: {
              type: 'object',
              properties: {
                status: { type: 'string', example: 'ready' },
              },
            },
            timestamp: { type: 'string', format: 'date-time' },
          },
        },
        LivenessResponse: {
          type: 'object',
          properties: {
            success: { type: 'boolean', example: true },
            data: {
              type: 'object',
              properties: {
                status: { type: 'string', example: 'live' },
              },
            },
            timestamp: { type: 'string', format: 'date-time' },
          },
        },
      },
    },
    security: [
      {
        bearerAuth: [],
      },
    ],
  },
  apis: [
    './src/routes/*.ts',
    './src/modules/auth/*.routes.ts',
    './src/modules/session/*.routes.ts',
    './src/modules/oidc/*.routes.ts',
    './src/modules/rbac/*.routes.ts',
    './src/modules/mfa/*.routes.ts',
    './src/modules/identity/*.routes.ts',
    './src/modules/access/*.routes.ts',
    './src/modules/governance/*.routes.ts'
  ],
};

/**
 * EN: Generate OpenAPI specification
 * VI: Tạo OpenAPI specification
 */
const specs = swaggerJSDoc(options);

/**
 * EN: Setup Swagger UI middleware
 * VI: Thiết lập Swagger UI middleware
 */
export const setupSwagger = (app: Application, basePath: string = '/api-docs') => {
  // EN: Swagger page
  // VI: Trang Swagger
  app.use(basePath, swaggerUi.serve, swaggerUi.setup(specs, {
    explorer: true,
    swaggerOptions: {
      persistAuthorization: true,
      displayRequestDuration: true,
      docExpansion: 'none',
      filter: true,
      showExtensions: true,
      showCommonExtensions: true,
      syntaxHighlight: {
        activate: true,
        theme: 'arta',
      },
    },
    customCss: `
      .swagger-ui .topbar { display: none }
      .swagger-ui .info .title { color: #3b4151 }
    `,
    customSiteTitle: 'Microservice Template API Documentation',
    customfavIcon: '/favicon.ico',
  }));

  // EN: Swagger JSON endpoint
  // VI: Endpoint Swagger JSON
  app.get(`${basePath}.json`, (_req, res) => {
    res.setHeader('Content-Type', 'application/json');
    res.send(specs);
  });

  // EN: Swagger YAML endpoint
  // VI: Endpoint Swagger YAML
  app.get(`${basePath}.yaml`, (_req, res) => {
    res.setHeader('Content-Type', 'application/yaml');
    // Note: Would need yaml package for full YAML support
    res.send(JSON.stringify(specs, null, 2));
  });

  logger.info(`📚 Swagger documentation available at: http://localhost:${appConfig.port}${basePath}`);
};

export { specs };
export default specs;