<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { usersApi } from '@/api'
import type { ApiUserRole, UserDto } from '@/api/types'
import GlassCard from '@/components/ui/GlassCard.vue'
import DataTable from '@/components/ui/DataTable.vue'
import EmptyState from '@/components/ui/EmptyState.vue'

const search = ref('')
const roleFilter = ref('Все роли')
const instituteFilter = ref('Все институты')
const users = ref<UserDto[]>([])
const loading = ref(false)
const error = ref('')

type DataTableColumn = { key: string; label: string; align?: 'left' | 'center' | 'right' }

const columns: DataTableColumn[] = [
  { key: 'name', label: 'Имя' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Роль', align: 'center' },
  { key: 'institute', label: 'Институт' },
  { key: 'activity', label: 'Активность', align: 'center' },
  { key: 'created', label: 'Дата регистрации' },
  { key: 'actions', label: 'Действия', align: 'right' },
]

const allRoles: ApiUserRole[] = ['Student', 'Teacher', 'Admin']
const roleLabels = { Student: 'Студент', Teacher: 'Преподаватель', Admin: 'Администратор' } as const
const roleApi = { Студент: 'Student', Преподаватель: 'Teacher', Администратор: 'Admin' } as const
const roleBadgeClasses: Record<ApiUserRole, string> = {
  Student: 'badge-green',
  Teacher: 'badge-blue',
  Admin: 'badge-purple',
}

const rows = computed(() =>
  users.value.map((user) => ({
    id: user.id,
    name: user.displayName || user.email,
    email: user.email,
    role: user.roles.map((role) => roleLabels[role]).join(', '),
    apiRoles: user.roles,
    institute: 'ЮФУ',
    activity: user.isActive ? 'Активен' : 'Заблокирован',
    isActive: user.isActive,
    created: new Date(user.createdAt).toLocaleDateString('ru-RU'),
  })),
)

async function fetchUsers() {
  loading.value = true
  error.value = ''
  try {
    users.value = await usersApi.list({
      Search: search.value || undefined,
      Role:
        roleFilter.value === 'Все роли'
          ? undefined
          : roleApi[roleFilter.value as keyof typeof roleApi],
      PageSize: 100,
    })
  } catch (err) {
    error.value = err instanceof Error ? err.message : 'Не удалось загрузить пользователей.'
  } finally {
    loading.value = false
  }
}

async function toggleActive(row: Record<string, unknown>) {
  const id = Number(row.id)
  const isActive = Boolean(row.isActive)
  await usersApi.setActive(id, !isActive)
  await fetchUsers()
}

function getRowRoles(row: Record<string, unknown>) {
  const apiRoles = Array.isArray(row.apiRoles) ? row.apiRoles : []
  return Array.from(
    new Set(apiRoles.filter((role): role is ApiUserRole => allRoles.includes(role as ApiUserRole))),
  )
}

function hasRole(row: Record<string, unknown>, role: ApiUserRole) {
  return getRowRoles(row).includes(role)
}

function getRoleChipClass(row: Record<string, unknown>, role: ApiUserRole) {
  return hasRole(row, role)
    ? ['badge', roleBadgeClasses[role]]
    : ['btn-ghost', 'role-chip-inactive']
}

async function toggleRole(row: Record<string, unknown>, role: ApiUserRole) {
  const id = Number(row.id)
  const currentRoles = getRowRoles(row)
  const nextRoles = currentRoles.includes(role)
    ? currentRoles.filter((currentRole) => currentRole !== role)
    : [...currentRoles, role]

  if (!nextRoles.length) return

  await usersApi.setRole(id, nextRoles)
  await fetchUsers()
}

onMounted(fetchUsers)
</script>

<template>
  <div class="admin-users page-content">
    <div class="header">
      <h1 class="page-title">Пользователи</h1>
    </div>

    <GlassCard>
      <div class="filters">
        <input v-model="search" class="glass-input" placeholder="Поиск по имени или email" />
        <select v-model="roleFilter" class="glass-input" @change="fetchUsers">
          <option>Все роли</option>
          <option>Студент</option>
          <option>Преподаватель</option>
          <option>Администратор</option>
        </select>
        <select v-model="instituteFilter" class="glass-input">
          <option>Все институты</option>
          <option>ИКТИБ</option>
          <option>ИФиМКН</option>
          <option>АГиС</option>
          <option>ЮФ</option>
        </select>
      </div>

      <EmptyState v-if="error" title="Не удалось загрузить пользователей" :subtitle="error" />
      <EmptyState
        v-else-if="!rows.length && !loading"
        title="Пользователей не найдено"
        subtitle="Попробуйте изменить фильтры."
      />
      <DataTable :columns="columns" :rows="rows">
        <template #role="{ row }">
          <div class="role-chips">
            <button
              v-for="role in allRoles"
              :key="role"
              class="role-chip"
              :class="getRoleChipClass(row, role)"
              type="button"
              @click="toggleRole(row, role)"
            >
              {{ roleLabels[role] }}
            </button>
          </div>
        </template>
        <template #activity="{ value }">
          <span class="badge" :class="value === 'Активен' ? 'badge-green' : 'badge-orange'">{{
            value
          }}</span>
        </template>
        <template #actions="{ row }">
          <div class="actions">
            <button class="btn-ghost" @click="toggleActive(row)">
              {{ row.isActive ? 'Заблокировать' : 'Активировать' }}
            </button>
          </div>
        </template>
      </DataTable>
    </GlassCard>
  </div>
</template>

<style scoped>
.admin-users {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}
.actions {
  display: flex;
  gap: 6px;
  justify-content: flex-end;
  flex-wrap: wrap;
}
.role-chips {
  display: flex;
  gap: 6px;
  justify-content: center;
  flex-wrap: wrap;
}
.role-chip {
  cursor: pointer;
  border: 0;
  transition:
    transform 0.15s ease,
    box-shadow 0.15s ease,
    opacity 0.15s ease;
}
.role-chip:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px var(--color-primary-a15);
}
.role-chip:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.role-chip-inactive {
  opacity: 0.75;
}
</style>
