import {
  ConflictException,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import type {
  CategoriesResponse,
  Category,
  CategoryCreate,
  CategoryUpdate,
} from '@siop/shared';
import { Prisma } from '@prisma/client';
import { PrismaService } from '../prisma/prisma.service';

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

  async list(): Promise<CategoriesResponse> {
    const rows = await this.prisma.category.findMany({
      include: { _count: { select: { assets: true, components: true } } },
      orderBy: [{ kind: 'asc' }, { name: 'asc' }],
    });
    return {
      categories: rows.map((c) => ({
        id: c.id,
        kind: c.kind,
        name: c.name,
        isActive: c.isActive,
        usageCount: c.kind === 'EQUIPMENT' ? c._count.assets : c._count.components,
      })),
    };
  }

  async create(dto: CategoryCreate): Promise<Category> {
    try {
      const created = await this.prisma.category.create({ data: dto });
      return { ...created, usageCount: 0 };
    } catch (e) {
      if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
        throw new ConflictException('Ce nom existe déjà pour ce référentiel');
      }
      throw e;
    }
  }

  /** Renommage / (dés)activation — la suppression n'existe pas (invariant R1). */
  async update(id: string, dto: CategoryUpdate): Promise<Category> {
    try {
      const updated = await this.prisma.category.update({
        where: { id },
        data: dto,
        include: { _count: { select: { assets: true, components: true } } },
      });
      return {
        id: updated.id,
        kind: updated.kind,
        name: updated.name,
        isActive: updated.isActive,
        usageCount:
          updated.kind === 'EQUIPMENT'
            ? updated._count.assets
            : updated._count.components,
      };
    } catch (e) {
      if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2025') {
        throw new NotFoundException('Catégorie inconnue');
      }
      if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2002') {
        throw new ConflictException('Ce nom existe déjà pour ce référentiel');
      }
      throw e;
    }
  }
}
