import {
  getOrCreateUnspecifiedCategory,
  isUnspecifiedCategorySlug,
  UNSPECIFIED_CATEGORY_SLUG,
} from '../../lib/default-category.js'
import { prisma } from '../../lib/prisma.js'

export async function registerAdminCategoryRoutes(fastify) {
  fastify.get(
    '/api/admin/categories',
    { preHandler: [fastify.verifyAdmin] },
    async () => {
      const items = await prisma.category.findMany({
        orderBy: [{ sort: 'asc' }, { name: 'asc' }],
      })
      return { items }
    },
  )

  fastify.post(
    '/api/admin/categories',
    { preHandler: [fastify.verifyAdmin] },
    async (request, reply) => {
      const body = request.body ?? {}
      const name = String(body.name ?? '').trim()
      if (!name) {
        reply.code(400).send({ error: 'Укажите название категории' })
        return
      }
      const slug = String(body.slug ?? '').trim() || request.server.slugify(name) || `cat-${Date.now()}`
      if (isUnspecifiedCategorySlug(slug)) {
        reply.code(400).send({ error: `Slug «${UNSPECIFIED_CATEGORY_SLUG}» зарезервирован` })
        return
      }
      const sort = body.sort !== undefined && body.sort !== null && body.sort !== '' ? Number(body.sort) : undefined
      const exists = await prisma.category.findUnique({ where: { slug } })
      if (exists) {
        reply.code(409).send({ error: 'Такой slug уже занят' })
        return
      }
      const category = await prisma.category.create({
        data: {
          name,
          slug,
          sort: Number.isFinite(sort) ? Math.round(sort) : 0,
        },
      })
      reply.code(201).send(category)
    },
  )

  fastify.patch(
    '/api/admin/categories/:id',
    { preHandler: [fastify.verifyAdmin] },
    async (request, reply) => {
      const { id } = request.params
      const body = request.body ?? {}
      const existing = await prisma.category.findUnique({ where: { id } })
      if (!existing) {
        reply.code(404).send({ error: 'Категория не найдена' })
        return
      }

      const data = {}
      if (body.name !== undefined) data.name = String(body.name ?? '').trim()
      if (body.sort !== undefined) {
        const s = Number(body.sort)
        if (!Number.isFinite(s)) {
          reply.code(400).send({ error: 'Некорректный sort' })
          return
        }
        data.sort = Math.round(s)
      }
      if (body.slug !== undefined) {
        const s = String(body.slug ?? '').trim()
        if (isUnspecifiedCategorySlug(existing.slug) && s !== UNSPECIFIED_CATEGORY_SLUG) {
          reply.code(400).send({ error: 'Нельзя сменить slug служебной категории «Не указано»' })
          return
        }
        if (!s) {
          reply.code(400).send({ error: 'Slug не может быть пустым' })
          return
        }
        if (s !== existing.slug) {
          if (isUnspecifiedCategorySlug(s)) {
            reply.code(400).send({ error: `Slug «${UNSPECIFIED_CATEGORY_SLUG}» зарезервирован` })
            return
          }
          const clash = await prisma.category.findFirst({ where: { slug: s, NOT: { id } } })
          if (clash) {
            reply.code(409).send({ error: 'Такой slug уже занят' })
            return
          }
        }
        data.slug = s
      }

      if (Object.keys(data).length === 0) {
        return existing
      }
      if (data.name !== undefined && !data.name) {
        reply.code(400).send({ error: 'Укажите название' })
        return
      }

      const updated = await prisma.category.update({ where: { id }, data })
      return updated
    },
  )

  fastify.delete(
    '/api/admin/categories/:id',
    { preHandler: [fastify.verifyAdmin] },
    async (request, reply) => {
      const { id } = request.params
      const existing = await prisma.category.findUnique({ where: { id } })
      if (!existing) {
        reply.code(404).send({ error: 'Категория не найдена' })
        return
      }
      if (isUnspecifiedCategorySlug(existing.slug)) {
        reply.code(409).send({ error: 'Служебную категорию «Не указано» нельзя удалить' })
        return
      }

      const fallback = await getOrCreateUnspecifiedCategory()
      await prisma.$transaction([
        prisma.product.updateMany({
          where: { categoryId: id },
          data: { categoryId: fallback.id },
        }),
        prisma.category.delete({ where: { id } }),
      ])
      return reply.code(204).send()
    },
  )
}
