// tdd-guard:skip — Next.js server page that only fetches data and composes
// child components; no unit-testable logic of its own.
import { redirect } from'next/navigation'
import { createClient } from'@/lib/supabase/server'
import { getUserSession } from'@/lib/auth/permissions'
import type { RoleCode } from'@/lib/auth/permissions-shared'
import AppHeader from'@/components/layout/app-header'
import UsersClient from'@/components/admin/users-client'
import { resolveAvatarUrls } from'@/lib/avatar/avatar-url'
import { isOrphanUser } from'@/lib/users/orphan'
import type { DepartmentMasterData } from'@/lib/repository-types'

export default async function AdminUsersPage() {
 const session = await getUserSession()
 if (!session || (session.role !=='admin'&& session.role !=='masteradmin')) {
 redirect('/projektanlage')
 }

 const supabase = await createClient()

 const { data: users } = await supabase
 .from('user_profiles')
 .select(`
 id,
 auth_user_id,
 first_name,
 last_name,
 display_name,
 email,
 avatar_url,
 account_status,
 must_change_password,
 last_login_at,
 created_at,
 department_id,
 role_id,
 roles ( id, code, label ),
 department_master_data ( id, department_code, department_name )
 `)
 .is('deleted_at', null)
 .order('created_at', { ascending: false })

 // KAR-787 / R3 + R51/R52: consultants linked to an auth account. The auth-id
 // set drives the "orphan" flag; the per-auth-id map drives the linked-consultant
 // display + unlink in the edit modal.
 const { data: linkedConsultants } = await supabase
 .from('consultants')
 .select('id, auth_user_id, display_name, first_name, last_name')
 .not('auth_user_id', 'is', null)
 const linkedAuthIds = new Set(
 (linkedConsultants ?? []).map((c) => c.auth_user_id as string),
 )
 const consultantByAuthId = new Map(
 (linkedConsultants ?? []).map((c) => [
 c.auth_user_id as string,
 {
 id: c.id as string,
 name: (c.display_name as string | null)
 ?? [c.last_name, c.first_name].filter(Boolean).join(', ')
 ?? null,
 },
 ]),
 )

 // KAR-787 / R47: most recent invitation per user (user_audit_log).
 const { data: inviteEvents } = await supabase
 .from('user_audit_log')
 .select('target_user_id, created_at')
 .eq('action', 'user.invitation_sent')
 .order('created_at', { ascending: false })
 const lastInvitedByUser = new Map<string, string>()
 for (const ev of inviteEvents ?? []) {
 const uid = ev.target_user_id as string | null
 if (uid && !lastInvitedByUser.has(uid)) {
 lastInvitedByUser.set(uid, ev.created_at as string)
 }
 }

 const { data: departments } = await supabase
 .from('department_master_data')
 .select('id, department_code, department_name, organization_area, is_active, created_at, updated_at')
 .eq('is_active', true)
 .order('department_name')

 // KAR-787 / R53: roles loaded from the DB (set + ids), so the user modals no
 // longer carry a hardcoded ALL_ROLES list. Display labels stay curated via
 // lib/auth/role-labels.ts.
 const { data: roles } = await supabase
 .from('roles')
 .select('id, code, label')
 .order('id')

 // avatar_url holds a private-bucket storage key — swap it for a signed URL the
 // client can render directly in <img>.
 const userRows = users ?? []
 const avatarUrls = await resolveAvatarUrls(userRows.map((u) => u.avatar_url as string | null))
 const usersWithAvatars = userRows.map((u) => {
 const authId = u.auth_user_id as string | null
 const linked = authId ? consultantByAuthId.get(authId) : undefined
 return {
 ...u,
 avatar_url: u.avatar_url ? (avatarUrls.get(u.avatar_url as string) ?? null) : null,
 // KAR-787 / R3
 is_orphan: isOrphanUser(authId, linkedAuthIds),
 // KAR-787 / R47
 last_invited_at: lastInvitedByUser.get(u.id as string) ?? null,
 // KAR-787 / R51/R52
 linked_consultant_id: linked?.id ?? null,
 linked_consultant_name: linked?.name ?? null,
 }
 })

 return (
 <>
 <AppHeader title="Benutzerverwaltung"backHref="/projektanlage"/>
 <main className="px-4 py-6 pb-24 md:pb-8 max-w-7xl mx-auto w-full">
 <UsersClient
 initialUsers={usersWithAvatars}
 departments={(departments ?? []) as DepartmentMasterData[]}
 roles={(roles ?? []) as { code: RoleCode; id: string; label: string }[]}
 session={session}
 />
 </main>
 </>
 )
}
