import fs from 'node:fs/promises'
import path from 'node:path'
import { prisma } from '../../lib/prisma.js'
import { persistMultipartImages } from '../../lib/upload-images.js'
import {
  formatFileTooLargeMessage,
  getProductImageMaxFileBytes,
  isMultipartFileTooLargeError,
} from '../../lib/upload-limits.js'

export async function registerAdminGalleryRoutes(fastify) {
  fastify.get('/api/admin/gallery', { preHandler: [fastify.verifyAdmin] }, async () => {
    const items = await prisma.galleryImage.findMany({
      orderBy: { createdAt: 'desc' },
    })

    const urls = items.map((i) => i.url)
    const usedUrls = new Set()

    const productImages = await prisma.productImage.findMany({
      where: { url: { in: urls } },
      select: { url: true },
    })
    for (const pi of productImages) {
      usedUrls.add(pi.url)
    }

    const legacyProducts = await prisma.product.findMany({
      where: { imageUrl: { in: urls } },
      select: { imageUrl: true },
    })
    for (const p of legacyProducts) {
      if (p.imageUrl) usedUrls.add(p.imageUrl)
    }

    return {
      items: items.map((i) => ({
        id: i.id,
        url: i.url,
        isResized: i.isResized,
        createdAt: i.createdAt,
        inUse: usedUrls.has(i.url),
      })),
    }
  })

  fastify.post('/api/admin/gallery/upload', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => {
    try {
      const urls = await persistMultipartImages(request, {
        maxFiles: 10,
        maxFileBytes: getProductImageMaxFileBytes(),
        subdir: '',
        eager: false,
      })
      for (const url of urls) {
        await prisma.galleryImage.create({
          data: { url, isResized: false },
        })
      }
      return { urls }
    } catch (error) {
      let message = error instanceof Error ? error.message : 'Не удалось загрузить файлы'
      let statusCode =
        error && typeof error === 'object' && 'statusCode' in error && Number.isInteger(error.statusCode)
          ? Number(error.statusCode)
          : 400
      if (isMultipartFileTooLargeError(error)) {
        message = formatFileTooLargeMessage(getProductImageMaxFileBytes())
        statusCode = 413
      }
      return reply.code(statusCode).send({ error: message })
    }
  })

  fastify.post('/api/admin/gallery/:id/resize', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => {
    const { id } = request.params
    const row = await prisma.galleryImage.findUnique({ where: { id } })
    if (!row) {
      return reply.code(404).send({ error: 'Изображение не найдено' })
    }
    if (row.isResized) {
      return reply.code(409).send({ error: 'Изображение уже обработано' })
    }

    const urlParts = row.url.replace(/^\//, '').split('/')
    const fileName = urlParts[urlParts.length - 1]
    const uuid = path.parse(fileName).name

    try {
      const { generateAllSizes, convertOriginalToWebp } = await import('../../lib/image-resize.js')

      const fullPath = path.join(process.cwd(), urlParts.slice(0, -1).join('/'), fileName)
      await generateAllSizes(uuid, '', fullPath)
      const newUrl = await convertOriginalToWebp(uuid, '')

      await prisma.galleryImage.update({
        where: { id },
        data: { url: newUrl, isResized: true },
      })

      return { url: newUrl }
    } catch (error) {
      request.log.error(error, 'Resize failed')
      return reply.code(500).send({ error: 'Ошибка обработки изображения' })
    }
  })

  fastify.delete('/api/admin/gallery/:id', { preHandler: [fastify.verifyAdmin] }, async (request, reply) => {
    const { id } = request.params
    const row = await prisma.galleryImage.findUnique({ where: { id } })
    if (!row) {
      return reply.code(404).send({ error: 'Не найдено' })
    }

    const usedInImages = await prisma.productImage.count({ where: { url: row.url } })
    const usedAsLegacy = await prisma.product.count({ where: { imageUrl: row.url } })
    if (usedInImages > 0 || usedAsLegacy > 0) {
      return reply.code(409).send({ error: 'Изображение используется в карточке товара' })
    }

    const relative = row.url.replace(/^\//, '')
    const filePath = path.join(process.cwd(), relative)
    try {
      await fs.unlink(filePath)
    } catch (err) {
      if (err && typeof err === 'object' && 'code' in err && err.code !== 'ENOENT') {
        throw err
      }
    }

    await prisma.galleryImage.delete({ where: { id } })
    return reply.code(204).send()
  })
}
