import { Prisma } from "@/generated/prisma/client"
import { paginate } from "@/lib/paginate"
import prisma from "@/lib/prisma"
import {
  Item,
  ItemSummary,
  ItemWithAssetAndMovementCount,
  ItemWithAssetCount,
} from "@/lib/types"

export const ItemService = {
  findAllItemsCount: async (): Promise<number> => {
    return prisma.item.count({ where: { deletedAt: { equals: null } } })
  },

  findAllWithAssetCount: async ({
    page,
    pageSize,
    search,
  }: {
    page?: number
    pageSize?: number
    search?: string
  }) => {
    return paginate<ItemWithAssetCount>({
      model: prisma.item,
      page,
      pageSize,
      where: {
        deletedAt: null,
        ...(search
          ? {
              name: { contains: search, mode: "insensitive" },
            }
          : {}),
      },
      orderBy: { name: "asc" },
      select: {
        id: true,
        name: true,
        stock: true,
        category: { select: { id: true, name: true } },
        _count: { select: { assets: true } },
      },
    })
  },

  findAll: async (opts?: {
    includeCategory?: boolean
    includeAssets?: boolean
    includeMovements?: boolean
  }): Promise<Item[]> => {
    return prisma.item.findMany({
      include: {
        category: opts?.includeCategory ? true : false,
        assets: opts?.includeAssets
          ? { select: { id: true, serialNumber: true, status: true } }
          : false,
        movements: opts?.includeMovements
          ? { select: { id: true, type: true, quantity: true } }
          : false,
      },
    })
  },

  findAllAssignable: async (): Promise<Item[]> => {
    return prisma.item.findMany({
      where: {
        deletedAt: null,
        OR: [
          {
            stock: { gt: 0 },
            assets: { some: {} },
          },
          {
            stock: 0,
            assets: { some: {} },
          },
          {
            stock: 0,
            assets: { none: {} },
          },
        ],
      },
      orderBy: { name: "asc" },
    }) as Promise<Item[]>
  },

  findByIdWithCategory: async (id: string): Promise<ItemSummary | null> => {
    return prisma.item.findUnique({
      where: { id },
      include: {
        category: { select: { id: true, name: true } },
      },
    })
  },

  findByIdWithAssetCount: async (
    id: string,
  ): Promise<ItemWithAssetCount | null> => {
    return prisma.item.findUnique({
      where: { id },
      include: {
        category: { select: { id: true, name: true } },
        _count: { select: { assets: true } },
      },
    })
  },

  findByIdWithAssetAndMovementCount: async (
    id: string,
  ): Promise<ItemWithAssetAndMovementCount | null> => {
    return prisma.item.findUnique({
      where: { id },
      include: {
        category: { select: { id: true, name: true } },
        _count: { select: { assets: true, movements: true } },
      },
    })
  },

  findByName: async (name: string): Promise<Item | null> => {
    return prisma.item.findFirst({
      where: { name },
      include: { category: true, assets: true, movements: true },
    }) as Promise<Item | null>
  },

  findById: async (id: string): Promise<Item | null> => {
    return prisma.item.findUnique({
      where: { id },
      include: { category: true, assets: true, movements: true },
    }) as Promise<Item | null>
  },

  findAllWithStock: async (): Promise<Item[]> => {
    return prisma.item.findMany({
      orderBy: { name: "asc" },
      where: {
        stock: { gt: 0 },
        deletedAt: { equals: null },
      },
      include: {
        category: true,
        assets: { select: { id: true, serialNumber: true, status: true } },
        movements: { select: { id: true, type: true, quantity: true } },
      },
    }) as Promise<Item[]>
  },

  create: async (data: Prisma.ItemCreateInput): Promise<Item> => {
    return prisma.item.create({ data })
  },

  update: async (id: string, data: Prisma.ItemUpdateInput): Promise<Item> => {
    return prisma.item.update({ where: { id }, data })
  },

  updateStock: async (id: string, quantity: number): Promise<Item> => {
    return prisma.item.update({
      where: { id },
      data: { stock: { increment: quantity } },
    })
  },

  delete: async (id: string): Promise<Item> => {
    return prisma.item.update({
      where: { id },
      data: { deletedAt: new Date() },
    })
  },
}
