import {
  BadRequestException,
  ConflictException,
  ForbiddenException,
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { Prisma } from '../generated/prisma/client.js';
import { Role } from '../generated/prisma/enums.js';
import type { ActorContext } from '../common/actor-context.js';
import { MESSAGES } from '../common/messages.js';
import { PrismaService } from '../prisma.service.js';
import { CreateDictionaryItemDto } from './dto/create-dictionary-item.dto.js';
import { DictionaryQueryDto } from './dto/dictionary-query.dto.js';
import { UpdateDictionaryItemDto } from './dto/update-dictionary-item.dto.js';

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

  /**
   * 查询字典项列表。
   */
  async findAll(actor: ActorContext, query: DictionaryQueryDto) {
    const where: Prisma.DictionaryItemWhereInput = {};

    if (query.type) {
      where.type = query.type;
    }

    // 非系统管理员一律只看启用项，避免业务页面误拿到停用值。
    if (actor.role !== Role.SYSTEM_ADMIN || !query.includeDisabled) {
      where.enabled = true;
    }

    return this.prisma.dictionaryItem.findMany({
      where,
      orderBy: [{ type: 'asc' }, { sortOrder: 'asc' }, { id: 'asc' }],
    });
  }

  /**
   * 创建字典项：仅系统管理员可维护。
   */
  async create(actor: ActorContext, dto: CreateDictionaryItemDto) {
    this.assertSystemAdmin(actor);

    try {
      return await this.prisma.dictionaryItem.create({
        data: {
          type: dto.type,
          label: this.normalizeLabel(dto.label),
          sortOrder: dto.sortOrder ?? 0,
          enabled: dto.enabled ?? true,
        },
      });
    } catch (error) {
      this.handleDuplicate(error);
      throw error;
    }
  }

  /**
   * 更新字典项：支持调整分类、排序和启停状态。
   */
  async update(actor: ActorContext, id: number, dto: UpdateDictionaryItemDto) {
    this.assertSystemAdmin(actor);
    await this.ensureExists(id);

    const data: Prisma.DictionaryItemUpdateInput = {};
    if (dto.type !== undefined) {
      data.type = dto.type;
    }
    if (dto.label !== undefined) {
      data.label = this.normalizeLabel(dto.label);
    }
    if (dto.sortOrder !== undefined) {
      data.sortOrder = dto.sortOrder;
    }
    if (dto.enabled !== undefined) {
      data.enabled = dto.enabled;
    }

    try {
      return await this.prisma.dictionaryItem.update({
        where: { id },
        data,
      });
    } catch (error) {
      this.handleDuplicate(error);
      throw error;
    }
  }

  /**
   * 删除字典项。
   */
  async remove(actor: ActorContext, id: number) {
    this.assertSystemAdmin(actor);
    await this.ensureExists(id);

    return this.prisma.dictionaryItem.delete({
      where: { id },
    });
  }

  /**
   * 标准化字典名称并确保非空。
   */
  private normalizeLabel(value: string) {
    const label = value?.trim();
    if (!label) {
      throw new BadRequestException(MESSAGES.DICTIONARY.LABEL_REQUIRED);
    }
    return label;
  }

  /**
   * 校验系统管理员权限。
   */
  private assertSystemAdmin(actor: ActorContext) {
    if (actor.role !== Role.SYSTEM_ADMIN) {
      throw new ForbiddenException(
        MESSAGES.DICTIONARY.SYSTEM_ADMIN_ONLY_MAINTAIN,
      );
    }
  }

  /**
   * 确认字典项存在。
   */
  private async ensureExists(id: number) {
    const current = await this.prisma.dictionaryItem.findUnique({
      where: { id },
      select: { id: true },
    });

    if (!current) {
      throw new NotFoundException(MESSAGES.DICTIONARY.NOT_FOUND);
    }

    return current;
  }

  /**
   * 统一处理唯一键冲突。
   */
  private handleDuplicate(error: unknown) {
    if (
      error instanceof Prisma.PrismaClientKnownRequestError &&
      error.code === 'P2002'
    ) {
      throw new ConflictException(MESSAGES.DICTIONARY.DUPLICATE);
    }
  }
}
