import { useRef, useState } from 'react'
import Alert from '@mui/material/Alert'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Checkbox from '@mui/material/Checkbox'
import Dialog from '@mui/material/Dialog'
import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent'
import DialogTitle from '@mui/material/DialogTitle'
import FormControl from '@mui/material/FormControl'
import FormControlLabel from '@mui/material/FormControlLabel'
import FormHelperText from '@mui/material/FormHelperText'
import InputLabel from '@mui/material/InputLabel'
import MenuItem from '@mui/material/MenuItem'
import Select from '@mui/material/Select'
import Stack from '@mui/material/Stack'
import Switch from '@mui/material/Switch'
import Table from '@mui/material/Table'
import TableBody from '@mui/material/TableBody'
import TableCell from '@mui/material/TableCell'
import TableHead from '@mui/material/TableHead'
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 { Controller, useForm } from 'react-hook-form'
import { fetchAdminGallery } from '@/entities/gallery'
import {
  createProduct,
  deleteProduct,
  fetchAdminProducts,
  fetchCategories,
  updateProduct,
  uploadAdminProductImages,
} from '@/entities/product/api/product-api'
import type { Category, Product } from '@/entities/product/model/types'
import { formatAdminImageMaxSizeHint } from '@/shared/constants/upload-limits'
import { formatPriceRub } from '@/shared/lib/format-price'
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 { EntityRowActions } from '@/shared/ui/EntityRowActions'
import { OptimizedImage } from '@/shared/ui/OptimizedImage'

type FormState = {
  title: string
  slug: string
  shortDescription: string
  description: string
  quantity: string
  materials: string
  priceRub: string
  imageUrls: string[]
  published: boolean
  categoryId: string
}

const emptyForm = (): FormState => ({
  title: '',
  slug: '',
  shortDescription: '',
  description: '',
  quantity: '0',
  materials: '',
  priceRub: '',
  imageUrls: [],
  published: true,
  categoryId: '',
})

export function AdminProductsPage() {
  const queryClient = useQueryClient()
  const { dialogOpen, editing, openCreateDialog, openEditDialog, closeDialog } = useEditDialogState<Product>()
  const [galleryPickOpen, setGalleryPickOpen] = useState(false)
  const [gallerySelectedUrls, setGallerySelectedUrls] = useState<Set<string>>(() => new Set())

  const productForm = useForm<FormState>({
    defaultValues: emptyForm(),
    mode: 'onChange',
  })

  const titleValue = productForm.watch('title')

  const categoriesQuery = useQuery({
    queryKey: ['categories'],
    queryFn: () => fetchCategories(),
  })

  const productsQuery = useQuery({
    queryKey: ['admin', 'products'],
    queryFn: fetchAdminProducts,
  })

  const galleryForPickQuery = useQuery({
    queryKey: ['admin', 'gallery'],
    queryFn: fetchAdminGallery,
    enabled: galleryPickOpen,
  })

  const openCreate = () => {
    productForm.reset(emptyForm())
    openCreateDialog()
  }

  const openEdit = (p: Product) => {
    openEditDialog(p)
    const urls =
      (p.images ?? [])
        .slice()
        .sort((a, b) => a.sort - b.sort)
        .map((x) => x.url) ?? (p.imageUrl ? [p.imageUrl] : [])
    productForm.reset({
      title: p.title,
      slug: p.slug,
      shortDescription: p.shortDescription ?? '',
      description: p.description ?? '',
      quantity: String(p.quantity),
      materials: (p.materials ?? []).join(', '),
      priceRub: String(p.priceCents / 100),
      imageUrls: urls,
      published: p.published,
      categoryId: p.categoryId,
    })
  }

  const createMut = useMutation({
    mutationFn: async () => {
      const form = productForm.getValues()
      const priceCents = Math.round(Number(form.priceRub.replace(',', '.')) * 100)
      if (!Number.isFinite(priceCents) || priceCents <= 0) throw new Error('Цена должна быть больше 0')
      if (priceCents > 10_000_00) throw new Error('Цена не может превышать 10 000 ₽')
      if (!form.categoryId) throw new Error('Выберите категорию')
      const qty = form.quantity.trim()
      if (!qty) throw new Error('Укажите количество')
      const qtyNum = Number(qty)
      if (!Number.isInteger(qtyNum) || qtyNum < 0 || qtyNum > 10) throw new Error('Количество — целое число от 0 до 10')
      const materials = form.materials
        .split(',')
        .map((x) => x.trim())
        .filter(Boolean)
      await createProduct({
        title: form.title.trim(),
        slug: form.slug.trim() || undefined,
        shortDescription: form.shortDescription.trim() || null,
        description: form.description.trim() || null,
        quantity: Math.floor(qtyNum),
        materials,
        priceCents,
        imageUrls: form.imageUrls,
        published: form.published,
        categoryId: form.categoryId,
      })
    },
    onSuccess: () => {
      void invalidateQueryKeys(queryClient, [['admin', 'products'], ['products']])
      closeDialog()
    },
  })

  const updateMut = useMutation({
    mutationFn: async () => {
      const form = productForm.getValues()
      const priceCents = Math.round(Number(form.priceRub.replace(',', '.')) * 100)
      if (!Number.isFinite(priceCents) || priceCents <= 0) throw new Error('Цена должна быть больше 0')
      if (priceCents > 10_000_00) throw new Error('Цена не может превышать 10 000 ₽')
      if (!form.categoryId) throw new Error('Выберите категорию')
      const qty = form.quantity.trim()
      if (!qty) throw new Error('Укажите количество')
      const qtyNum = Number(qty)
      if (!Number.isInteger(qtyNum) || qtyNum < 0 || qtyNum > 10) throw new Error('Количество — целое число от 0 до 10')
      const materials = form.materials
        .split(',')
        .map((x) => x.trim())
        .filter(Boolean)
      await updateProduct(editing!.id, {
        title: form.title.trim(),
        slug: form.slug.trim(),
        shortDescription: form.shortDescription.trim() || null,
        description: form.description.trim() || null,
        quantity: Math.floor(qtyNum),
        materials,
        priceCents,
        imageUrls: form.imageUrls,
        published: form.published,
        categoryId: form.categoryId,
      })
    },
    onSuccess: () => {
      void invalidateQueryKeys(queryClient, [['admin', 'products'], ['products']])
      closeDialog()
    },
  })

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

  const handleSubmit = () => {
    if (editing) updateMut.mutate()
    else createMut.mutate()
  }

  const productImagesInputRef = useRef<HTMLInputElement>(null)

  const uploadImagesMut = useMutation({
    mutationFn: (picked: File[]) => uploadAdminProductImages(picked),
    onSuccess: (urls) => {
      const current = productForm.getValues('imageUrls')
      productForm.setValue('imageUrls', [...current, ...urls], { shouldDirty: true })
      if (productImagesInputRef.current) {
        productImagesInputRef.current.value = ''
      }
    },
  })

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

  const removeImage = (url: string) => {
    const current = productForm.getValues('imageUrls')
    productForm.setValue(
      'imageUrls',
      current.filter((u) => u !== url),
      { shouldDirty: true },
    )
  }

  const toggleGalleryPickUrl = (url: string) => {
    setGallerySelectedUrls((prev) => {
      const next = new Set(prev)
      if (next.has(url)) {
        next.delete(url)
      } else {
        next.add(url)
      }
      return next
    })
  }

  const appendGalleryUrlsToForm = () => {
    const current = productForm.getValues('imageUrls')
    const merged = [...current]
    for (const url of gallerySelectedUrls) {
      if (!merged.includes(url)) {
        merged.push(url)
      }
    }
    productForm.setValue('imageUrls', merged, { shouldDirty: true })
    setGalleryPickOpen(false)
    setGallerySelectedUrls(new Set())
  }

  return (
    <Box>
      <Typography variant="h4" gutterBottom>
        Управление товарами
      </Typography>

      <Stack direction="row" spacing={2} sx={{ mb: 2 }}>
        <Button variant="contained" onClick={openCreate}>
          Новый товар
        </Button>
      </Stack>

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

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

      <Table size="small">
        <TableHead>
          <TableRow>
            <TableCell>Название</TableCell>
            <TableCell>Категория</TableCell>
            <TableCell>Цена</TableCell>
            <TableCell>Витрина</TableCell>
            <TableCell align="right">Действия</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {(productsQuery.data ?? []).map((p) => (
            <TableRow key={p.id} hover>
              <TableCell>{p.title}</TableCell>
              <TableCell>{p.category?.name ?? '—'}</TableCell>
              <TableCell>{formatPriceRub(p.priceCents)}</TableCell>
              <TableCell>{p.published ? 'да' : 'нет'}</TableCell>
              <TableCell align="right">
                <EntityRowActions onEdit={() => openEdit(p)} onDelete={() => deleteMut.mutate(p.id)} />
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>

      <Dialog open={dialogOpen} onClose={closeDialog} fullWidth maxWidth="sm">
        <DialogTitle>{editing ? 'Редактировать товар' : 'Новый товар'}</DialogTitle>
        <DialogContent>
          <Stack spacing={2} sx={{ mt: 1 }}>
            <Controller
              control={productForm.control}
              name="title"
              render={({ field }) => <TextField label="Название" fullWidth required {...field} />}
            />
            <Controller
              control={productForm.control}
              name="slug"
              render={({ field }) => (
                <TextField
                  label="Slug (URL)"
                  fullWidth
                  {...field}
                  helperText="Можно оставить пустым при создании — сгенерируется из названия"
                />
              )}
            />
            <Controller
              control={productForm.control}
              name="shortDescription"
              render={({ field }) => (
                <TextField label="Краткое описание (для каталога)" fullWidth multiline minRows={2} {...field} />
              )}
            />
            <Controller
              control={productForm.control}
              name="description"
              render={({ field }) => <TextField label="Описание" fullWidth multiline minRows={2} {...field} />}
            />
            <Controller
              control={productForm.control}
              name="materials"
              render={({ field }) => (
                <TextField
                  label="Материалы"
                  fullWidth
                  {...field}
                  helperText="Список через запятую (например: хлопок, дерево, акрил)"
                />
              )}
            />
            <Controller
              control={productForm.control}
              name="quantity"
              rules={{
                validate: (v) => {
                  const n = Number(v)
                  if (!Number.isInteger(n) || n < 0 || n > 10) return 'Целое число от 0 до 10'
                  return true
                },
              }}
              render={({ field, fieldState }) => (
                <TextField
                  label="Количество"
                  fullWidth
                  {...field}
                  inputMode="numeric"
                  onChange={(e) => {
                    const v = e.target.value.replace(/[^0-9]/g, '')
                    field.onChange(v)
                  }}
                  helperText={fieldState.error?.message ?? '0 = нет в наличии'}
                  error={!!fieldState.error}
                />
              )}
            />
            <Controller
              control={productForm.control}
              name="priceRub"
              rules={{
                required: 'Укажите цену',
                validate: (v) => {
                  const n = Number(v.replace(',', '.'))
                  if (!Number.isFinite(n) || n <= 0) return 'Цена должна быть больше 0'
                  if (n > 10_000) return 'Цена не может превышать 10 000 ₽'
                  if (!Number.isInteger(Math.round(n * 100))) return 'Не более 2 знаков после запятой'
                  return true
                },
              }}
              render={({ field, fieldState }) => (
                <TextField
                  label="Цена, ₽"
                  fullWidth
                  {...field}
                  inputMode="decimal"
                  onChange={(e) => {
                    const v = e.target.value.replace(/[^0-9.,]/g, '')
                    field.onChange(v)
                  }}
                  helperText={fieldState.error?.message}
                  error={!!fieldState.error}
                />
              )}
            />
            <Box>
              <Typography variant="subtitle2" sx={{ mb: 0.5 }}>
                Фото (загрузка)
              </Typography>
              <FormHelperText sx={{ mt: 0, mb: 1 }}>
                PNG, JPEG или WebP, до {formatAdminImageMaxSizeHint()} на файл. Крестик на превью убирает фото только из
                карточки; файл остаётся на сервере и в галерее.
              </FormHelperText>
              <Box
                sx={{
                  display: 'flex',
                  gap: 2,
                  alignItems: { sm: 'center' },
                  flexDirection: { xs: 'column', sm: 'row' },
                  flexWrap: 'wrap',
                }}
              >
                <Button component="label" variant="outlined" disabled={uploadImagesMut.isPending}>
                  Выбрать файлы
                  <input
                    ref={productImagesInputRef}
                    hidden
                    type="file"
                    accept="image/png,image/jpeg,image/webp"
                    multiple
                    onChange={(e) => {
                      const files = e.target.files
                      if (!files || files.length === 0) return
                      uploadImagesMut.mutate(Array.from(files))
                    }}
                  />
                </Button>
                <Button
                  variant="outlined"
                  onClick={() => {
                    setGallerySelectedUrls(new Set())
                    setGalleryPickOpen(true)
                  }}
                >
                  Из галереи
                </Button>
                {uploadImagesMut.isPending && <Typography color="text.secondary">Загрузка…</Typography>}
                {uploadImagesMut.isError && <Typography color="error">Не удалось загрузить фото</Typography>}
              </Box>

              {productForm.watch('imageUrls').length > 0 && (
                <Box sx={{ mt: 2, display: 'flex', gap: 1, flexWrap: 'wrap' }}>
                  {productForm.watch('imageUrls').map((url) => (
                    <Box
                      key={url}
                      sx={{
                        width: 92,
                        height: 92,
                        borderRadius: 1,
                        border: 1,
                        borderColor: 'divider',
                        overflow: 'hidden',
                        position: 'relative',
                      }}
                      title={url}
                    >
                      <OptimizedImage
                        src={url}
                        alt="Фото товара"
                        widths={[320, 640]}
                        sizes="80px"
                        sx={{ width: '100%', height: '100%', objectFit: 'cover' }}
                      />
                      <Button
                        size="small"
                        color="error"
                        variant="contained"
                        onClick={() => removeImage(url)}
                        aria-label="Убрать из карточки"
                        title="Убрать из карточки"
                        sx={{
                          position: 'absolute',
                          top: 4,
                          right: 4,
                          minWidth: 0,
                          px: 0.75,
                          py: 0,
                          lineHeight: 1.2,
                        }}
                      >
                        ×
                      </Button>
                    </Box>
                  ))}
                </Box>
              )}
            </Box>
            <Controller
              control={productForm.control}
              name="categoryId"
              render={({ field }) => (
                <FormControl fullWidth error={!field.value}>
                  <InputLabel id="cat-label">Категория</InputLabel>
                  <Select labelId="cat-label" label="Категория" {...field}>
                    {(categoriesQuery.data ?? []).map((c: Category) => (
                      <MenuItem key={c.id} value={c.id}>
                        {c.name}
                      </MenuItem>
                    ))}
                  </Select>
                  {!field.value && <FormHelperText>Выберите категорию</FormHelperText>}
                </FormControl>
              )}
            />
            <Controller
              control={productForm.control}
              name="published"
              render={({ field }) => (
                <FormControlLabel
                  control={<Switch checked={field.value} onChange={(_, v) => field.onChange(v)} />}
                  label="Показывать в каталоге"
                />
              )}
            />
          </Stack>
        </DialogContent>
        <DialogActions>
          <Button onClick={closeDialog}>Отмена</Button>
          <Button
            variant="contained"
            onClick={handleSubmit}
            disabled={
              !titleValue.trim() ||
              !productForm.watch('categoryId') ||
              !productForm.watch('quantity').trim() ||
              !productForm.watch('priceRub').trim() ||
              !productForm.formState.isValid ||
              createMut.isPending ||
              updateMut.isPending
            }
          >
            {editing ? 'Сохранить' : 'Создать'}
          </Button>
        </DialogActions>
      </Dialog>

      <Dialog
        open={galleryPickOpen}
        onClose={() => {
          setGalleryPickOpen(false)
          setGallerySelectedUrls(new Set())
        }}
        fullWidth
        maxWidth="sm"
      >
        <DialogTitle>Изображения из галереи</DialogTitle>
        <DialogContent dividers>
          {galleryForPickQuery.isLoading && <Typography color="text.secondary">Загрузка списка…</Typography>}
          {galleryForPickQuery.isError && (
            <Alert severity="error">Не удалось загрузить галерею. Попробуйте ещё раз.</Alert>
          )}
          {galleryForPickQuery.data?.items.length === 0 && !galleryForPickQuery.isLoading && (
            <Typography color="text.secondary">В галерее пока нет файлов. Загрузите их в разделе «Галерея».</Typography>
          )}
          <Box
            sx={{
              display: 'grid',
              gridTemplateColumns: 'repeat(auto-fill, minmax(120px, 1fr))',
              gap: 1.5,
              pt: 1,
            }}
          >
            {(galleryForPickQuery.data?.items ?? []).map((item) => {
              const alreadyInCard = productForm.watch('imageUrls').includes(item.url)
              return (
                <FormControlLabel
                  key={item.id}
                  sx={{ m: 0, alignItems: 'flex-start' }}
                  control={
                    <Checkbox
                      checked={alreadyInCard || gallerySelectedUrls.has(item.url)}
                      disabled={alreadyInCard}
                      onChange={() => toggleGalleryPickUrl(item.url)}
                    />
                  }
                  label={
                    <Box sx={{ width: '100%', maxHeight: 100, borderRadius: 1, overflow: 'hidden' }}>
                      <OptimizedImage
                        src={item.url}
                        alt=""
                        widths={[320, 640]}
                        sizes="120px"
                        sx={{ width: '100%', height: '100%', objectFit: 'cover' }}
                      />
                    </Box>
                  }
                />
              )
            })}
          </Box>
        </DialogContent>
        <DialogActions>
          <Button
            onClick={() => {
              setGalleryPickOpen(false)
              setGallerySelectedUrls(new Set())
            }}
          >
            Отмена
          </Button>
          <Button
            variant="contained"
            onClick={appendGalleryUrlsToForm}
            disabled={![...gallerySelectedUrls].some((u) => !productForm.watch('imageUrls').includes(u))}
          >
            Добавить
          </Button>
        </DialogActions>
      </Dialog>
    </Box>
  )
}
