<script setup lang="ts">
import type { AdminRole, AdminUser, AdminUserProfile } from "~/composables/useAdmin"

const auth = useAuthStore()
const route = useRoute()
const router = useRouter()
const toast = useToast()
const admin = useAdmin()

const userId = route.params.id as string
const loading = ref(true)
const saving = ref(false)

const userForm = ref<AdminUser | null>(null)
const roles = ref<AdminRole[]>([])
const tenants = ref<{ id: number; name: string; short: string }[]>([])
const unassignedProfiles = ref<AdminUserProfile[]>([])

const tenantOptions = computed(() =>
  tenants.value.map((tenant) => ({
    label: `${tenant.name} (${tenant.short})`,
    value: tenant.id,
  }))
)

const getRoleOptionsForTenant = (tenantId: number) =>
  roles.value
    .filter((role) => role.tenant_id === null || role.tenant_id === tenantId)
    .map((role) => ({
      label: role.tenant_id === null ? `${role.name} (global)` : role.name,
      value: role.id,
    }))

const getFreeProfilesForTenant = (tenantId: number) =>
  unassignedProfiles.value.filter((profile) => profile.tenant_id === tenantId)

const normalizeUserAssignments = () => {
  if (!userForm.value) return

  const uniqueTenantIds = Array.from(new Set((userForm.value.tenant_ids || []).map(Number))).sort((a, b) => a - b)
  const assignmentsByTenant = new Map<number, string>()
  const profileAssignmentByTenant = new Map<number, string | null>()

  for (const assignment of userForm.value.role_assignments || []) {
    if (!uniqueTenantIds.includes(Number(assignment.tenant_id))) continue
    if (assignmentsByTenant.has(Number(assignment.tenant_id))) continue
    assignmentsByTenant.set(Number(assignment.tenant_id), assignment.role_id)
  }

  for (const assignment of userForm.value.profile_assignments || []) {
    if (!uniqueTenantIds.includes(Number(assignment.tenant_id))) continue
    profileAssignmentByTenant.set(Number(assignment.tenant_id), assignment.profile_id || null)
  }

  userForm.value.tenant_ids = uniqueTenantIds
  userForm.value.role_assignments = uniqueTenantIds
    .map((tenantId) => {
      const roleId = assignmentsByTenant.get(tenantId)
      return roleId ? { tenant_id: tenantId, role_id: roleId } : null
    })
    .filter(Boolean) as { tenant_id: number; role_id: string }[]
  userForm.value.profile_assignments = uniqueTenantIds.map((tenantId) => ({
    tenant_id: tenantId,
    profile_id: profileAssignmentByTenant.get(tenantId) || null,
  }))
}

const updateUserTenants = (tenantIds: number[] = []) => {
  if (!userForm.value) return
  userForm.value.tenant_ids = tenantIds
  normalizeUserAssignments()
}

const setRoleForTenant = (tenantId: number, roleId?: string | null) => {
  if (!userForm.value) return
  userForm.value.role_assignments = (userForm.value.role_assignments || []).filter((assignment) => assignment.tenant_id !== tenantId)
  if (roleId) {
    userForm.value.role_assignments.push({ tenant_id: tenantId, role_id: roleId })
  }
}

const getRoleForTenant = (tenantId: number) =>
  userForm.value?.role_assignments?.find((assignment) => assignment.tenant_id === tenantId)?.role_id || null

const setProfileAssignmentForTenant = (tenantId: number, profileId?: string | null) => {
  if (!userForm.value) return
  userForm.value.profile_assignments = (userForm.value.profile_assignments || []).filter((assignment) => assignment.tenant_id !== tenantId)
  userForm.value.profile_assignments.push({
    tenant_id: tenantId,
    profile_id: profileId || null,
  })
}

const getProfileAssignmentForTenant = (tenantId: number) =>
  userForm.value?.profile_assignments?.find((assignment) => assignment.tenant_id === tenantId)?.profile_id || null

const fetchUser = async () => {
  loading.value = true

  try {
    const overview = await admin.getOverview()
    roles.value = overview.roles
    tenants.value = overview.tenants
    unassignedProfiles.value = overview.unassignedProfiles

    const user = overview.users.find((entry) => entry.id === userId)
    if (!user) {
      toast.add({ title: "Benutzer nicht gefunden", color: "red" })
      await router.push("/administration/users")
      return
    }

    userForm.value = {
      ...user,
      profile_defaults: { ...user.profile_defaults },
      tenant_ids: [...user.tenant_ids],
      role_assignments: [...user.role_assignments],
      profile_assignments: [...(user.profile_assignments || [])],
      profiles: [...user.profiles],
    }
    normalizeUserAssignments()
  } catch (err: any) {
    console.error("[administration/users/show]", err)
    toast.add({
      title: "Benutzer konnte nicht geladen werden",
      description: err?.data?.error || err?.message || "Unbekannter Fehler",
      color: "red",
    })
  } finally {
    loading.value = false
  }
}

const saveUser = async () => {
  if (!userForm.value || saving.value) return

  saving.value = true
  normalizeUserAssignments()

  try {
    await admin.updateUser(userForm.value.id, {
      email: userForm.value.email,
      multiTenant: userForm.value.multiTenant,
      must_change_password: userForm.value.must_change_password,
      is_admin: userForm.value.is_admin,
    })

    await admin.updateUserAccess(userForm.value.id, {
      tenant_ids: userForm.value.tenant_ids,
      role_assignments: userForm.value.role_assignments,
      profile_defaults: userForm.value.profile_defaults,
      profile_assignments: userForm.value.profile_assignments,
    })

    await fetchUser()
    await auth.fetchMe()

    toast.add({ title: "Benutzer gespeichert", color: "green" })
  } catch (err: any) {
    console.error("[administration/users/save]", err)
    toast.add({
      title: "Benutzer konnte nicht gespeichert werden",
      description: err?.data?.error || err?.message || "Unbekannter Fehler",
      color: "red",
    })
  } finally {
    saving.value = false
  }
}

onMounted(async () => {
  if (!auth.user?.is_admin) {
    await router.push("/")
    return
  }

  await fetchUser()
})
</script>

<template>
  <UDashboardNavbar title="Administration: Benutzer">
    <template #left>
      <UButton icon="i-heroicons-chevron-left" variant="outline" @click="router.push('/administration/users')">
        Benutzer
      </UButton>
    </template>
    <template #right>
      <UButton color="primary" :loading="saving" @click="saveUser">
        Speichern
      </UButton>
    </template>
  </UDashboardNavbar>

  <UDashboardPanelContent>
    <UCard v-if="!loading && userForm">
      <div class="flex items-start justify-between gap-4 mb-6">
        <div>
          <h2 class="text-xl font-semibold">{{ userForm.display_name }}</h2>
          <p class="text-sm text-gray-500">{{ userForm.email }}</p>
        </div>
      </div>

      <USeparator label="Benutzer" />

      <UForm :state="userForm" class="grid grid-cols-1 md:grid-cols-2 gap-6 mt-4">
        <UFormField label="E-Mail">
          <UInput v-model="userForm.email" />
        </UFormField>

        <UFormField label="Profil Vorname">
          <UInput v-model="userForm.profile_defaults.first_name" />
        </UFormField>

        <UFormField label="Profil Nachname">
          <UInput v-model="userForm.profile_defaults.last_name" />
        </UFormField>

        <UFormField label="Tenants">
          <USelectMenu
            :model-value="userForm.tenant_ids"
            :items="tenantOptions"
            value-key="value"
            label-key="label"
            multiple
            @update:model-value="updateUserTenants"
          />
        </UFormField>

        <UFormField label="Administrative Freigabe">
          <div class="flex items-center gap-3 h-10">
            <USwitch v-model="userForm.is_admin" />
            <span class="text-sm text-gray-600">Darf Administrationsseiten und Admin-API nutzen</span>
          </div>
        </UFormField>

        <UFormField label="Multi-Tenant">
          <div class="flex items-center gap-3 h-10">
            <USwitch v-model="userForm.multiTenant" />
            <span class="text-sm text-gray-600">Mehrere Tenant-Zuordnungen erlauben</span>
          </div>
        </UFormField>

        <UFormField label="Passwortwechsel erzwingen">
          <div class="flex items-center gap-3 h-10">
            <USwitch v-model="userForm.must_change_password" />
            <span class="text-sm text-gray-600">Beim nächsten Login muss das Passwort geändert werden</span>
          </div>
        </UFormField>
      </UForm>
    </UCard>

    <UCard v-if="!loading && userForm" class="mt-3">
      <USeparator label="Rollen und Profile" />

      <div v-if="userForm.tenant_ids.length" class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
        <UCard
          v-for="tenantId in userForm.tenant_ids"
          :key="tenantId"
          class="border border-gray-200"
        >
          <div class="space-y-3">
            <div>
              <div class="font-medium">
                {{ tenants.find((tenant) => tenant.id === tenantId)?.name || `Tenant ${tenantId}` }}
              </div>
              <div class="text-sm text-gray-500">
                {{ tenants.find((tenant) => tenant.id === tenantId)?.short || "" }}
              </div>
            </div>

            <UFormField label="Rolle">
              <USelectMenu
                :model-value="getRoleForTenant(tenantId)"
                :items="getRoleOptionsForTenant(tenantId)"
                value-key="value"
                label-key="label"
                placeholder="Rolle auswählen"
                @update:model-value="(value) => setRoleForTenant(tenantId, value)"
              />
            </UFormField>

            <UFormField label="Freies Profil">
              <USelectMenu
                :model-value="getProfileAssignmentForTenant(tenantId)"
                :items="[
                  { label: 'Neues Profil erzeugen', value: null },
                  ...getFreeProfilesForTenant(tenantId).map((profile) => ({
                    label: profile.full_name || `${profile.first_name} ${profile.last_name}`,
                    value: profile.id,
                  }))
                ]"
                value-key="value"
                label-key="label"
                placeholder="Profil auswählen"
                @update:model-value="(value) => setProfileAssignmentForTenant(tenantId, value)"
              />
            </UFormField>
          </div>
        </UCard>
      </div>

      <UAlert
        v-else-if="!loading"
        title="Keine Tenant-Zuordnung"
        description="Weise dem Benutzer zuerst mindestens einen Tenant zu."
        color="amber"
        variant="soft"
        class="mt-4"
      />
    </UCard>

    <UCard v-if="!loading && userForm" class="mt-3">
      <USeparator label="Profile im System" />

      <div class="flex flex-wrap gap-2 mt-4">
        <UBadge
          v-for="profile in userForm.profiles"
          :key="profile.id"
          variant="subtle"
          color="gray"
        >
          {{ profile.full_name || `${profile.first_name} ${profile.last_name}` }} · Tenant {{ profile.tenant_id }}
        </UBadge>
      </div>
    </UCard>

    <USkeleton v-if="loading" class="h-80" />
  </UDashboardPanelContent>
</template>
