import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { Prisma } from '@prisma/client';
import {
  CreateAITicketDto,
  UpdateAITicketDto,
  AssignAITicketDto,
  ResolveAITicketDto,
  QueryAITicketDto,
  TicketStatus,
  AssigneeTeam,
} from '../dto';
import {
  ConversationNotFoundException,
  AITicketNotFoundException,
  AITicketAccessDeniedException,
  TicketNotConfirmedException,
  TicketAlreadyResolvedException,
} from '../exceptions';

/**
 * AI 工单服务
 */
@Injectable()
export class TicketService {
  private readonly logger = new Logger(TicketService.name);

  /**
   * 分类到团队的映射
   */
  private readonly categoryToTeam: Record<string, AssigneeTeam> = {
    IT: AssigneeTeam.IT,
    HR: AssigneeTeam.HR,
    ADMIN: AssigneeTeam.ADMIN,
    FINANCE: AssigneeTeam.FINANCE,
    OTHER: AssigneeTeam.IT, // 默认分配给 IT
  };

  constructor(private readonly prisma: PrismaService) {}

  /**
   * 创建工单（升级问题）
   */
  async createTicket(dto: CreateAITicketDto, userId: string) {
    // 验证二次确认
    if (!dto.confirmed) {
      throw new TicketNotConfirmedException();
    }

    // 验证对话存在
    const conversation = await this.prisma.aIConversation.findFirst({
      where: { id: dto.conversationId },
      include: {
        messages: {
          orderBy: { createdAt: 'desc' },
          take: 10,
        },
      },
    });

    if (!conversation) {
      throw new ConversationNotFoundException(dto.conversationId);
    }

    // 生成工单标题
    const title = this.generateTicketTitle(conversation, dto.category);

    // 确定分配团队
    const assigneeTeam = this.categoryToTeam[dto.category] || AssigneeTeam.IT;

    // 创建工单
    const ticket = await this.prisma.aIAssistantTicket.create({
      data: {
        conversationId: dto.conversationId,
        category: dto.category,
        priority: dto.priority || 'MEDIUM',
        status: 'OPEN',
        title,
        description: dto.description,
        assigneeTeam,
      },
    });

    // 更新对话状态
    await this.prisma.aIConversation.update({
      where: { id: dto.conversationId },
      data: { status: 'ESCALATED' },
    });

    // 添加升级消息到对话
    await this.prisma.aIMessage.create({
      data: {
        conversationId: dto.conversationId,
        role: 'SYSTEM',
        source: 'ESCALATION',
        content: `您的问题已升级为工单，工单编号：${ticket.id.slice(0, 8).toUpperCase()}。${assigneeTeam} 团队将尽快为您处理。`,
      },
    });

    this.logger.log(`创建工单: ${ticket.id}, 分配给: ${assigneeTeam}`);

    return {
      id: ticket.id,
      conversationId: ticket.conversationId,
      source: 'AI_ASSISTANT',
      category: ticket.category,
      priority: ticket.priority,
      status: ticket.status,
      title: ticket.title,
      description: ticket.description,
      assigneeId: ticket.assigneeId,
      assigneeTeam: ticket.assigneeTeam,
      assignedAt: ticket.assignedAt,
      createdAt: ticket.createdAt,
      conversationSummary: {
        messageCount: conversation.messages.length,
        includedInTicket: true,
      },
    };
  }

  /**
   * 获取工单列表
   */
  async findTickets(
    query: QueryAITicketDto,
    userId: string,
    isAdmin: boolean = false,
  ) {
    const {
      page = 1,
      limit = 20,
      status,
      category,
      priority,
      assigneeTeam,
      view,
      sortBy = 'createdAt',
      sortOrder = 'desc',
    } = query;

    const where: Prisma.AIAssistantTicketWhereInput = {};

    // 视图过滤
    if (view === 'my_created') {
      where.conversation = { userId };
    } else if (view === 'my_assigned') {
      where.assigneeId = userId;
    } else if (!isAdmin) {
      // 非管理员只能看自己创建的或分配给自己的
      where.OR = [
        { conversation: { userId } },
        { assigneeId: userId },
      ];
    }

    if (status) {
      where.status = status;
    }

    if (category) {
      where.category = category;
    }

    if (priority) {
      where.priority = priority;
    }

    if (assigneeTeam) {
      where.assigneeTeam = assigneeTeam;
    }

    const [total, tickets] = await Promise.all([
      this.prisma.aIAssistantTicket.count({ where }),
      this.prisma.aIAssistantTicket.findMany({
        where,
        orderBy: { [sortBy]: sortOrder },
        skip: (page - 1) * limit,
        take: limit,
        include: {
          conversation: {
            select: {
              id: true,
              userId: true,
              title: true,
            },
          },
        },
      }),
    ]);

    const totalPages = Math.ceil(total / limit);

    return {
      items: tickets.map((ticket) => this.formatTicketListItem(ticket)),
      total,
      page,
      limit,
      totalPages,
      hasNext: page < totalPages,
      hasPrev: page > 1,
    };
  }

  /**
   * 获取工单详情
   */
  async findTicket(id: string, userId: string, isAdmin: boolean = false) {
    const ticket = await this.prisma.aIAssistantTicket.findFirst({
      where: { id },
      include: {
        conversation: {
          include: {
            messages: {
              orderBy: { createdAt: 'asc' },
            },
          },
        },
      },
    });

    if (!ticket) {
      throw new AITicketNotFoundException(id);
    }

    // 权限检查
    if (!isAdmin) {
      const isCreator = ticket.conversation.userId === userId;
      const isAssignee = ticket.assigneeId === userId;

      if (!isCreator && !isAssignee) {
        throw new AITicketAccessDeniedException();
      }
    }

    return this.formatTicketDetail(ticket);
  }

  /**
   * 更新工单
   */
  async updateTicket(
    id: string,
    dto: UpdateAITicketDto,
    userId: string,
    isAdmin: boolean = false,
  ) {
    const ticket = await this.prisma.aIAssistantTicket.findFirst({
      where: { id },
    });

    if (!ticket) {
      throw new AITicketNotFoundException(id);
    }

    // 权限检查（仅处理人或管理员可更新）
    if (!isAdmin && ticket.assigneeId !== userId) {
      throw new AITicketAccessDeniedException();
    }

    const updatedTicket = await this.prisma.aIAssistantTicket.update({
      where: { id },
      data: {
        priority: dto.priority,
        assigneeId: dto.assigneeId,
        assigneeTeam: dto.assigneeTeam,
      },
    });

    this.logger.log(`更新工单: ${id}`);

    return {
      id: updatedTicket.id,
      priority: updatedTicket.priority,
      assigneeId: updatedTicket.assigneeId,
      assigneeTeam: updatedTicket.assigneeTeam,
      updatedAt: updatedTicket.updatedAt,
    };
  }

  /**
   * 分配工单
   */
  async assignTicket(
    id: string,
    dto: AssignAITicketDto,
    userId: string,
    isAdmin: boolean = false,
  ) {
    const ticket = await this.prisma.aIAssistantTicket.findFirst({
      where: { id },
    });

    if (!ticket) {
      throw new AITicketNotFoundException(id);
    }

    if (!isAdmin) {
      throw new AITicketAccessDeniedException();
    }

    const updatedTicket = await this.prisma.aIAssistantTicket.update({
      where: { id },
      data: {
        assigneeId: dto.assigneeId,
        assigneeTeam: dto.assigneeTeam,
        assignedAt: new Date(),
        status: 'IN_PROGRESS',
      },
    });

    this.logger.log(`分配工单: ${id} -> ${dto.assigneeId || dto.assigneeTeam}`);

    return {
      id: updatedTicket.id,
      assigneeId: updatedTicket.assigneeId,
      assigneeTeam: updatedTicket.assigneeTeam,
      assignedAt: updatedTicket.assignedAt,
    };
  }

  /**
   * 解决工单
   */
  async resolveTicket(
    id: string,
    dto: ResolveAITicketDto,
    userId: string,
    isAdmin: boolean = false,
  ) {
    const ticket = await this.prisma.aIAssistantTicket.findFirst({
      where: { id },
      include: {
        conversation: {
          select: { userId: true },
        },
      },
    });

    if (!ticket) {
      throw new AITicketNotFoundException(id);
    }

    // 权限检查：管理员、处理人或创建者可以解决工单
    const isCreator = ticket.conversation.userId === userId;
    const isAssignee = ticket.assigneeId === userId;
    if (!isAdmin && !isAssignee && !isCreator) {
      throw new AITicketAccessDeniedException();
    }

    // 状态检查
    if (ticket.status === 'RESOLVED' || ticket.status === 'CLOSED') {
      throw new TicketAlreadyResolvedException();
    }

    const updatedTicket = await this.prisma.aIAssistantTicket.update({
      where: { id },
      data: {
        status: 'RESOLVED',
        resolution: dto.resolution,
        resolvedAt: new Date(),
      },
    });

    this.logger.log(`解决工单: ${id}`);

    return {
      id: updatedTicket.id,
      status: updatedTicket.status,
      resolution: updatedTicket.resolution,
      resolvedAt: updatedTicket.resolvedAt,
    };
  }

  /**
   * 生成工单标题
   */
  private generateTicketTitle(conversation: any, category: string): string {
    // 从对话标题或第一条用户消息生成
    if (conversation.title && conversation.title !== '新对话') {
      return conversation.title;
    }

    const firstUserMessage = conversation.messages
      .reverse()
      .find((m: any) => m.role === 'USER');

    if (firstUserMessage) {
      const content = firstUserMessage.content;
      return content.length > 50 ? content.substring(0, 50) + '...' : content;
    }

    return `${category} 问题咨询`;
  }

  /**
   * 格式化工单列表项
   */
  private formatTicketListItem(ticket: any) {
    return {
      id: ticket.id,
      category: ticket.category,
      priority: ticket.priority,
      status: ticket.status,
      title: ticket.title,
      description: ticket.description?.substring(0, 100),
      assignee: ticket.assigneeId
        ? { id: ticket.assigneeId, name: '' }
        : null,
      assigneeTeam: ticket.assigneeTeam,
      creator: {
        id: ticket.conversation.userId,
        name: '',
      },
      conversationId: ticket.conversationId,
      createdAt: ticket.createdAt,
      updatedAt: ticket.updatedAt,
    };
  }

  /**
   * 格式化工单详情
   */
  private formatTicketDetail(ticket: any) {
    return {
      id: ticket.id,
      category: ticket.category,
      priority: ticket.priority,
      status: ticket.status,
      title: ticket.title,
      description: ticket.description,
      assignee: ticket.assigneeId
        ? { id: ticket.assigneeId, name: '', email: '' }
        : null,
      assigneeTeam: ticket.assigneeTeam,
      creator: {
        id: ticket.conversation.userId,
        name: '',
      },
      conversation: {
        id: ticket.conversation.id,
        title: ticket.conversation.title,
        messages: ticket.conversation.messages.map((m: any) => ({
          id: m.id,
          role: m.role,
          source: m.source,
          content: m.content,
          createdAt: m.createdAt,
        })),
      },
      resolution: ticket.resolution,
      resolvedAt: ticket.resolvedAt,
      createdAt: ticket.createdAt,
      updatedAt: ticket.updatedAt,
    };
  }
}
