import { useEffect, useState } from 'react'
import Alert from '@mui/material/Alert'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Stack from '@mui/material/Stack'
import TableCell from '@mui/material/TableCell'
import TablePagination from '@mui/material/TablePagination'
import TableRow from '@mui/material/TableRow'
import TextField from '@mui/material/TextField'
import Typography from '@mui/material/Typography'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useUnit } from 'effector-react'
import { Controller, useForm } from 'react-hook-form'
import { Link as RouterLink } from 'react-router-dom'
import { createAdminUser, deleteAdminUser, fetchAdminUsers, updateAdminUser } from '@/entities/user/api/user-api'
import type { AdminUser } from '@/entities/user/model/types'
import { getErrorMessage } from '@/shared/lib/get-error-message'
import { invalidateQueryKeys } from '@/shared/lib/invalidate-query-keys'
import { useEditDialogState } from '@/shared/lib/use-edit-dialog-state'
import { $user } from '@/shared/model/auth'
import { AdminDialog } from '@/shared/ui/AdminDialog/AdminDialog'
import { AdminTable } from '@/shared/ui/AdminTable'
import { EntityRowActions } from '@/shared/ui/EntityRowActions'

type UserFormState = {
  email: string
  name: string
}

const emptyUserForm = (): UserFormState => ({ email: '', name: '' })

function formatDt(v: string) {
  try {
    const d = new Date(v)
    if (Number.isNaN(d.getTime())) return '—'
    return d.toLocaleString()
  } catch {
    return '—'
  }
}

export function AdminUsersPage() {
  const queryClient = useQueryClient()
  const { dialogOpen, editing, openCreateDialog, openEditDialog, closeDialog } = useEditDialogState<AdminUser>()
  const [qInput, setQInput] = useState('')
  const [q, setQ] = useState('')
  const [page, setPage] = useState(0)
  const [rowsPerPage, setRowsPerPage] = useState(20)
  const currentUser = useUnit($user)
  const currentUserId = currentUser?.id

  const userForm = useForm<UserFormState>({
    defaultValues: emptyUserForm(),
    mode: 'onChange',
  })

  useEffect(() => {
    const t = window.setTimeout(() => {
      setQ(qInput.trim())
      setPage(0)
    }, 250)
    return () => window.clearTimeout(t)
  }, [qInput])

  const usersQuery = useQuery({
    queryKey: ['admin', 'users', { q, page, rowsPerPage }],
    queryFn: () =>
      fetchAdminUsers({
        q: q || undefined,
        page: page + 1,
        pageSize: rowsPerPage,
      }),
  })

  const createMut = useMutation({
    mutationFn: async () => {
      const v = userForm.getValues()
      await createAdminUser({
        email: v.email.trim(),
        name: v.name.trim() || null,
      })
    },
    onSuccess: () => {
      void invalidateQueryKeys(queryClient, [['admin', 'users']])
      closeDialog()
    },
  })

  const updateMut = useMutation({
    mutationFn: async () => {
      const v = userForm.getValues()
      await updateAdminUser(editing!.id, {
        email: v.email.trim(),
        name: v.name.trim() || null,
      })
    },
    onSuccess: () => {
      void invalidateQueryKeys(queryClient, [['admin', 'users']])
      closeDialog()
    },
  })

  const deleteMut = useMutation({
    mutationFn: async (id: string) => deleteAdminUser(id),
    onSuccess: () => {
      void invalidateQueryKeys(queryClient, [['admin', 'users']])
    },
  })

  const mutationError = createMut.error ?? updateMut.error ?? deleteMut.error

  const openCreate = () => {
    userForm.reset(emptyUserForm())
    openCreateDialog()
  }

  const openEdit = (u: AdminUser) => {
    openEditDialog(u)
    userForm.reset({
      email: u.email,
      name: u.name ?? '',
    })
  }

  const emailValue = userForm.watch('email')
  const isSaveDisabled = !emailValue.trim() || createMut.isPending || updateMut.isPending

  const users = usersQuery.data?.items ?? []
  const total = usersQuery.data?.total ?? 0

  return (
    <Box>
      <Stack
        direction={{ xs: 'column', sm: 'row' }}
        spacing={2}
        sx={{ mb: 2, alignItems: { sm: 'center' }, justifyContent: 'space-between' }}
      >
        <Typography variant="h4">Админка — пользователи</Typography>
        <Button component={RouterLink} to="/admin" variant="outlined">
          Товары
        </Button>
      </Stack>

      <Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
        Управление пользователями доступно пользователю с правами администратора.
      </Typography>
      <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} sx={{ mb: 2, alignItems: { sm: 'center' } }}>
        <Button variant="contained" onClick={openCreate}>
          Новый пользователь
        </Button>
        <TextField
          size="small"
          label="Поиск (email/имя)"
          value={qInput}
          onChange={(e) => setQInput(e.target.value)}
          fullWidth
        />
      </Stack>

      {usersQuery.isError && (
        <Alert severity="error" sx={{ mb: 2 }}>
          Ошибка загрузки. Проверьте, что сервер запущен, и у вас есть права администратора.
        </Alert>
      )}

      {mutationError && (
        <Alert severity="error" sx={{ mb: 2 }}>
          {getErrorMessage(mutationError)}
        </Alert>
      )}

      <AdminTable
        columns={[
          { key: 'email', label: 'Почта' },
          { key: 'name', label: 'Имя' },
          { key: 'createdAt', label: 'Создан' },
          { key: 'updatedAt', label: 'Обновлён' },
          { key: 'actions', label: 'Действия', align: 'right' },
        ]}
        loading={usersQuery.isLoading}
        error={usersQuery.isError ? 'Ошибка загрузки.' : null}
      >
        {users.length === 0 && !usersQuery.isLoading ? (
          <TableRow>
            <TableCell colSpan={5} sx={{ color: 'text.secondary' }}>
              Пользователей пока нет.
            </TableCell>
          </TableRow>
        ) : (
          users.map((u) => (
            <TableRow key={u.id} hover>
              <TableCell>{u.email}</TableCell>
              <TableCell>{u.name ?? '—'}</TableCell>
              <TableCell>{formatDt(u.createdAt)}</TableCell>
              <TableCell>{formatDt(u.updatedAt)}</TableCell>
              <TableCell align="right">
                <EntityRowActions
                  onEdit={() => openEdit(u)}
                  onDelete={u.id === currentUserId ? undefined : () => deleteMut.mutate(u.id)}
                  deleteDisabled={deleteMut.isPending}
                  confirmDeleteMessage={`Удалить пользователя ${u.email}?`}
                />
              </TableCell>
            </TableRow>
          ))
        )}
      </AdminTable>

      <TablePagination
        component="div"
        count={total}
        page={page}
        onPageChange={(_, p) => setPage(p)}
        rowsPerPage={rowsPerPage}
        onRowsPerPageChange={(e) => {
          setRowsPerPage(Number(e.target.value))
          setPage(0)
        }}
        rowsPerPageOptions={[10, 20, 50, 100]}
      />

      <AdminDialog
        open={dialogOpen}
        onClose={closeDialog}
        title={editing ? 'Редактировать пользователя' : 'Новый пользователь'}
        maxWidth="xs"
        actions={
          <>
            <Button onClick={closeDialog}>Отмена</Button>
            <Button
              variant="contained"
              onClick={() => (editing ? updateMut.mutate() : createMut.mutate())}
              disabled={isSaveDisabled}
            >
              {editing ? 'Сохранить' : 'Создать'}
            </Button>
          </>
        }
      >
        <Stack spacing={2} sx={{ mt: 1 }}>
          <Controller
            control={userForm.control}
            name="email"
            render={({ field }) => (
              <TextField
                label="Почта"
                fullWidth
                required
                disabled={Boolean(editing && editing.id === currentUserId)}
                {...field}
              />
            )}
          />
          <Controller
            control={userForm.control}
            name="name"
            render={({ field }) => <TextField label="Имя/ник" fullWidth {...field} />}
          />
        </Stack>
      </AdminDialog>
    </Box>
  )
}
