import { APIGatewayEvent } from 'aws-lambda'
import { HttpError } from './error'
import jwt from 'jsonwebtoken'
import { firebaseApp } from 'services/firebase/firebase'
import { getOrganization } from 'services/organization'

export type Role = 'admin' | 'user' | 'organization'
export type Authorization = {
    userEmail?: string
    organizationIdentity?: string
    role: Role
}

export const authorize = async (event: APIGatewayEvent): Promise<Authorization> => {
    const authorization = event.headers['Authorization'] || event.headers['authorization']
    if (!authorization) {
        throw new HttpError(401, 'Unauthorized')
    }

    if (!process.env.JWT_SECRET) {
        throw new Error('JWT_SECRET is not defined')
    }

    const [scheme, token] = authorization.split(' ')
    if (scheme !== 'Bearer') {
        throw new HttpError(401, 'Authorization scheme not supported')
    }

    try {
        const verified = jwt.verify(token, process.env.JWT_SECRET)
        const { userEmail, organizationIdentity: organizationId, role } = verified as Authorization
        return { userEmail, organizationIdentity: organizationId, role }
    } catch {
        try {
            const idToken = await firebaseApp.auth().verifyIdToken(token)
            if (!idToken.email) {
                throw new HttpError(401, 'Unauthorized')
            }

            let email = idToken.email
            const role = idToken.email?.endsWith('@copykit.com.br') ? 'admin' : 'user'
            if (role === 'admin' && event.headers['x-delegated-user']) {
                email = event.headers['x-delegated-user']
            }

            return {
                userEmail: email,
                role,
            }
        } catch {
            throw new HttpError(401, 'Invalid token')
        }
    }
}

export const createOrganizationAuth = async (
    organizationIdentity: string,
    accessKey: string,
    userEmail?: string,
): Promise<string> => {
    if (!process.env.JWT_SECRET) {
        throw new Error('JWT_SECRET is not defined')
    }

    const authorization: Authorization = {
        organizationIdentity: organizationIdentity,
        userEmail,
        role: 'organization',
    }

    const organization = await getOrganization(organizationIdentity)
    if (!organization) {
        throw new HttpError(404, 'Organization not found')
    }

    if (organization.accessKey !== accessKey) {
        throw new HttpError(401, 'Invalid access key')
    }

    const token = jwt.sign(authorization, process.env.JWT_SECRET)
    return token
}
