import { and, eq, inArray } from "drizzle-orm"
import { FastifyInstance } from "fastify"

import { authProfileTeams, branches, teams } from "../../db/schema"

function normalizeTeamIds(values: any[]): number[] {
    return [...new Set(
        values
            .map((value) => {
                if (typeof value === "number") return value
                if (typeof value === "string" && value.trim()) return Number(value)
                if (value && typeof value === "object" && "id" in value) return Number(value.id)
                return NaN
            })
            .filter((value) => Number.isFinite(value))
    )]
}

export async function enrichProfilesWithTeams(server: FastifyInstance, profiles: any[]) {
    if (!profiles.length) return profiles

    const profileIds = profiles.map((profile) => profile.id).filter(Boolean)
    if (!profileIds.length) return profiles

    const profileTeamRows = await server.db
        .select()
        .from(authProfileTeams)
        .where(inArray(authProfileTeams.profile_id, profileIds))

    const teamIds = [...new Set(profileTeamRows.map((row) => row.team_id).filter(Boolean))]
    const teamRows = teamIds.length
        ? await server.db.select().from(teams).where(inArray(teams.id, teamIds))
        : []

    const branchIds = [...new Set(teamRows.map((team) => team.branch).filter(Boolean))]
    const branchRows = branchIds.length
        ? await server.db.select().from(branches).where(inArray(branches.id, branchIds))
        : []

    const branchMap = new Map(branchRows.map((branch) => [branch.id, branch]))
    const teamMap = new Map(teamRows.map((team) => [
        team.id,
        {
            ...team,
            branch: team.branch ? branchMap.get(team.branch) || null : null,
        },
    ]))
    const teamIdsByProfile = new Map<string, number[]>()

    for (const row of profileTeamRows) {
        const current = teamIdsByProfile.get(row.profile_id) || []
        current.push(row.team_id)
        teamIdsByProfile.set(row.profile_id, current)
    }

    return profiles.map((profile) => {
        const assignedTeamIds = [...new Set(teamIdsByProfile.get(profile.id) || [])]
        return {
            ...profile,
            teams: assignedTeamIds
                .map((teamId) => teamMap.get(teamId))
                .filter(Boolean),
            team_ids: assignedTeamIds,
        }
    })
}

export async function resolveTenantTeamIds(
    server: FastifyInstance,
    tenantId: number,
    values: any[],
) {
    const requestedTeamIds = normalizeTeamIds(values)

    if (!requestedTeamIds.length) {
        return []
    }

    const validTeams = await server.db
        .select({ id: teams.id })
        .from(teams)
        .where(
            and(
                eq(teams.tenant, tenantId),
                inArray(teams.id, requestedTeamIds)
            )
        )

    const validTeamIds = validTeams.map((team) => team.id)

    if (validTeamIds.length !== requestedTeamIds.length) {
        throw new Error("INVALID_TEAM_SELECTION")
    }

    return validTeamIds
}

export async function syncProfileTeams(
    server: FastifyInstance,
    profileId: string,
    teamIds: number[],
    userId?: string | null
) {
    await server.db
        .delete(authProfileTeams)
        .where(eq(authProfileTeams.profile_id, profileId))

    if (!teamIds.length) return

    await server.db
        .insert(authProfileTeams)
        .values(teamIds.map((teamId) => ({
            profile_id: profileId,
            team_id: teamId,
            created_by: userId || null,
        })))
}
