import {
  Injectable,
  NotFoundException,
  ConflictException,
} from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CreateItemTypeDto, UpdateItemTypeDto } from './dto/item-type.dto';
import { Prisma } from 'generated/prisma/client';
import { BootstrapTableRequestDto } from '../commons/dto/bootstrap-table-request.dto'
import { BootstrapTableResponseDto } from '../commons/dto/bootstrap-table-response.dto'
import { buildWhereClause } from 'src/commons/utils/prisma-query-builder';

@Injectable()
export class ItemTypeService {
  constructor(private readonly prisma: PrismaService) { }

  async findAll(query: BootstrapTableRequestDto) {
    const allowedFilters = {
      code: 'string',
      name: 'string',
      status: 'enum',
    } as const

    const where = buildWhereClause(
      query,
      allowedFilters,
      ['code', 'name'],
    )

    const allowedSortColumns = ['code', 'name', 'status', 'createdAt']

    const orderBy: Prisma.ItemTypeOrderByWithRelationInput = {}
    if (query.sort && allowedSortColumns.includes(query.sort)) {
      orderBy[query.sort] = query.sortOrder
    } else {
      orderBy.createdAt = 'desc'
    }

    const [total, rows] = await this.prisma.$transaction([
      this.prisma.itemType.count({ where }),
      this.prisma.itemType.findMany({
        where,
        skip: query.skip,
        take: query.take,
        orderBy,
      }),
    ])

    return new BootstrapTableResponseDto(total, rows)
  }

  async findOne(id: string) {
    const item = await this.prisma.itemType.findUnique({ where: { id } })
    if (!item) throw new NotFoundException(`ItemType with id ${id} not found`)
    return item
  }

  async create(dto: CreateItemTypeDto) {
    const existing = await this.prisma.itemType.findUnique({
      where: { code: dto.code },
    })
    if (existing)
      throw new ConflictException(`Code "${dto.code}" already exists`)

    return this.prisma.itemType.create({ data: dto })
  }

  async update(id: string, dto: UpdateItemTypeDto) {
    await this.findOne(id)

    if (dto.code) {
      const conflict = await this.prisma.itemType.findFirst({
        where: { code: dto.code, NOT: { id } },
      })
      if (conflict)
        throw new ConflictException(`Code "${dto.code}" already exists`)
    }

    return this.prisma.itemType.update({ where: { id }, data: dto })
  }

  async remove(id: string) {
    await this.findOne(id)
    return this.prisma.itemType.delete({ where: { id } })
  }
}