import { randomUUID } from 'crypto'
import { getUserByEmail } from 'services/firebase/firebase'
import { createOrganization, getOrganization, getOrganizationsByMember } from 'services/organization'
import { authorize, createOrganizationAuth } from 'utils/authorization'
import { lfunction } from 'utils/aws'
import { HttpError } from 'utils/error'
import { deserialize } from 'utils/http'
import { z } from 'zod'

export const mine = lfunction(async (event) => {
    const authorization = await authorize(event)
    if (!authorization.userEmail) {
        throw new HttpError(401, 'Unauthorized')
    }

    let organizations = await getOrganizationsByMember(authorization.userEmail)

    // Everyone should have at least one organization
    if (organizations.length === 0) {
        const user = await getUserByEmail(authorization.userEmail)
        if (!user?.email) {
            throw new Error('User not found')
        }

        organizations = [
            await createOrganization({
                identity: randomUUID(),
                name: user.email,
                members: [user.email],
            }),
        ]
    }

    return organizations
})

export const get = lfunction(async (event) => {
    const authorization = await authorize(event)
    if (authorization.role !== 'admin') {
        throw new HttpError(403, 'Forbidden')
    }

    const organizationIdentity = event.pathParameters?.identity
    if (!organizationIdentity) {
        throw new HttpError(400, 'Bad Request')
    }

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

    return organization
})

const zOrganizationAuth = z.object({
    organizationIdentity: z.string(),
    accessKey: z.string(),
})

export const auth = lfunction(async (event) => {
    let userEmail
    try {
        const authorization = await authorize(event)
        userEmail = authorization.userEmail
    } catch (err) {
        // Ignore error
    }

    const organizationAuth = deserialize(event, zOrganizationAuth)
    const auth = await createOrganizationAuth(
        organizationAuth.organizationIdentity,
        organizationAuth.accessKey,
        userEmail,
    )
    return {
        grant_type: 'Bearer',
        access_token: auth,
    }
})
