import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import {
  CreateCategoryDto,
  UpdateCategoryDto,
  QueryCategoryDto,
} from '../dto';
import {
  TicketCategoryNotFoundException,
  TicketCategoryCodeExistsException,
  TicketCategoryHasChildrenException,
  TicketCategoryHasTicketsException,
} from '../exceptions';

@Injectable()
export class CategoryService {
  private readonly logger = new Logger(CategoryService.name);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * 创建分类
   */
  async create(createCategoryDto: CreateCategoryDto) {
    const { code, parentId, ...categoryData } = createCategoryDto;

    // 检查编码是否已存在
    const existing = await this.prisma.ticketCategory.findUnique({
      where: { code },
    });
    if (existing) {
      throw new TicketCategoryCodeExistsException(code);
    }

    // 验证父分类
    if (parentId) {
      const parent = await this.prisma.ticketCategory.findUnique({
        where: { id: parentId },
      });
      if (!parent) {
        throw new TicketCategoryNotFoundException(parentId);
      }
    }

    const category = await this.prisma.ticketCategory.create({
      data: {
        code,
        parentId,
        ...categoryData,
      },
      include: {
        parent: true,
        defaultAssigneeGroup: true,
        sla: true,
      },
    });

    this.logger.log(`分类创建成功: ${code}`);

    return category;
  }

  /**
   * 获取分类列表
   */
  async findAll(query: QueryCategoryDto) {
    const { isActive, includeChildren, parentId } = query;

    const where: any = {};

    if (isActive !== undefined) {
      where.isActive = isActive;
    }

    if (parentId !== undefined) {
      where.parentId = parentId;
    } else if (!includeChildren) {
      // 默认只获取顶级分类
      where.parentId = null;
    }

    const categories = await this.prisma.ticketCategory.findMany({
      where,
      orderBy: [{ sortOrder: 'asc' }, { name: 'asc' }],
      include: {
        children: includeChildren
          ? {
              where: isActive !== undefined ? { isActive } : undefined,
              orderBy: [{ sortOrder: 'asc' }, { name: 'asc' }],
            }
          : false,
        defaultAssigneeGroup: {
          select: { id: true, name: true, code: true },
        },
        sla: {
          select: { id: true, name: true },
        },
        _count: {
          select: { tickets: true },
        },
      },
    });

    return categories;
  }

  /**
   * 获取分类详情
   */
  async findOne(id: string) {
    const category = await this.prisma.ticketCategory.findUnique({
      where: { id },
      include: {
        parent: true,
        children: {
          orderBy: [{ sortOrder: 'asc' }, { name: 'asc' }],
        },
        defaultAssigneeGroup: true,
        sla: true,
        _count: {
          select: { tickets: true },
        },
      },
    });

    if (!category) {
      throw new TicketCategoryNotFoundException(id);
    }

    return category;
  }

  /**
   * 根据编码获取分类
   */
  async findByCode(code: string) {
    return this.prisma.ticketCategory.findUnique({
      where: { code },
      include: {
        defaultAssigneeGroup: true,
        sla: true,
      },
    });
  }

  /**
   * 更新分类
   */
  async update(id: string, updateCategoryDto: UpdateCategoryDto) {
    const category = await this.prisma.ticketCategory.findUnique({
      where: { id },
    });

    if (!category) {
      throw new TicketCategoryNotFoundException(id);
    }

    // 验证父分类
    if (updateCategoryDto.parentId !== undefined) {
      if (updateCategoryDto.parentId === id) {
        throw new TicketCategoryHasChildrenException();
      }

      if (updateCategoryDto.parentId) {
        const parent = await this.prisma.ticketCategory.findUnique({
          where: { id: updateCategoryDto.parentId },
        });
        if (!parent) {
          throw new TicketCategoryNotFoundException(updateCategoryDto.parentId);
        }
      }
    }

    const updatedCategory = await this.prisma.ticketCategory.update({
      where: { id },
      data: updateCategoryDto,
      include: {
        parent: true,
        defaultAssigneeGroup: true,
        sla: true,
      },
    });

    this.logger.log(`分类更新成功: ${updatedCategory.code}`);

    return updatedCategory;
  }

  /**
   * 删除分类
   */
  async remove(id: string) {
    const category = await this.prisma.ticketCategory.findUnique({
      where: { id },
      include: {
        children: true,
        _count: {
          select: { tickets: true },
        },
      },
    });

    if (!category) {
      throw new TicketCategoryNotFoundException(id);
    }

    // 检查是否有子分类
    if (category.children.length > 0) {
      throw new TicketCategoryHasChildrenException();
    }

    // 检查是否有工单
    if (category._count.tickets > 0) {
      throw new TicketCategoryHasTicketsException();
    }

    await this.prisma.ticketCategory.delete({
      where: { id },
    });

    this.logger.log(`分类删除成功: ${category.code}`);

    return { success: true };
  }

  /**
   * 获取分类树
   */
  async getCategoryTree(isActiveOnly: boolean = true) {
    const categories = await this.prisma.ticketCategory.findMany({
      where: isActiveOnly ? { isActive: true } : undefined,
      orderBy: [{ sortOrder: 'asc' }, { name: 'asc' }],
      include: {
        defaultAssigneeGroup: {
          select: { id: true, name: true },
        },
      },
    });

    // 构建树结构
    const categoryMap = new Map<string, any>();
    const roots: any[] = [];

    categories.forEach((cat) => {
      categoryMap.set(cat.id, { ...cat, children: [] });
    });

    categories.forEach((cat) => {
      const node = categoryMap.get(cat.id);
      if (cat.parentId) {
        const parent = categoryMap.get(cat.parentId);
        if (parent) {
          parent.children.push(node);
        }
      } else {
        roots.push(node);
      }
    });

    return roots;
  }
}
