import rateLimit from 'express-rate-limit'
import _cors from 'cors'
import _helmet from 'helmet'
import { Request, Response, NextFunction } from 'express'
import { MulterError } from 'multer'
import { connect } from 'mongoose'
import { S3Client as R2Client } from '@aws-sdk/client-s3'
import OpenAI from 'openai'
import firebaseAdmin, { ServiceAccount } from 'firebase-admin'
import firebaseAccount from '../../firebase.json'
import PQueue from 'p-queue'
import { SchedulerClient } from "@aws-sdk/client-scheduler"

const schedulerClient = new SchedulerClient({
	region: process.env.AWS_REGION,
	credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  }
})

const limiter = rateLimit({
	windowMs: 1 * 60 * 1000, // 1 minutes
	max: 80,
	handler: (_req, res) => res.status(429).json({ message: 'Too many requests' }),
})

// environment
const environment = process.env.NODE_ENV as 'development' | 'production'
const isProduction = environment === 'production'
const isDevelopment = environment === 'development'

// cors
const corsValue = isProduction ? {
	origin: [
		process.env.FRONTEND_HOST!,
		process.env.BACKEND_HOST!
	]
} : undefined
const cors = _cors(corsValue)

// helmet
const helmet = _helmet({ contentSecurityPolicy: false })

// error handler
const errorHandler = (error: any, _req: Request, res: Response, _next: NextFunction) => {
	console.log(error)
	if (!(error instanceof MulterError)) {
		return res.status(500).json({ message: 'server error' })
	}
	if (error.code === 'LIMIT_FILE_SIZE') {
		return res.status(413).json({ message: 'file size too large' })
	}
	return res.status(400).json({ message: error.message })
}

// mongoose connection
const mongooseConnection = connect(process.env.MONGO_URL!, {
  dbName: process.env.DATABASE!,
})

// firebase admin
firebaseAdmin.initializeApp({
	credential: firebaseAdmin.credential.cert(firebaseAccount as ServiceAccount),
})

const R2 = new R2Client({
	endpoint: process.env.R2_ENDPOINT,
	region: process.env.R2_REGION!,
	credentials: {
		accessKeyId: process.env.R2_ACCESS_KEY_ID!,
		secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
	},
})

const key = Buffer.from(process.env.AES_KEY!)
const iv = Buffer.from(process.env.AES_IV!)

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })

const compressionQueue = new PQueue({
	concurrency: +(process.env.MAX_PARALLEL_COMPRESSION || '3')
})

const config = {
  limiter,
  cors,
  helmet,
  isDevelopment,
  isProduction,
  errorHandler,
  mongooseConnection,
	firebaseAdmin,
  R2,
  key,
  iv,
	openai,
	compressionQueue,
	schedulerClient
}

export default config