import { Injectable, ForbiddenException } from '@nestjs/common';
import { PrismaService } from '@chatapp/database';

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

  private async requireAdmin(wsId: string, userId: string) {
    const member = await this.prisma.workspaceMember.findUnique({
      where: {
        workspaceId_userId: { workspaceId: wsId, userId },
      },
    });
    if (!member || (member.role !== 'admin' && member.role !== 'owner')) {
      throw new ForbiddenException('Admin access required');
    }
    return member;
  }

  async getAnalytics(wsId: string, userId: string) {
    await this.requireAdmin(wsId, userId);

    const [messageCount, channelCount, activeChannels, memberCount, files, huddles] = await Promise.all([
      this.prisma.message.count({ where: { workspaceId: wsId, isDeleted: false } }),
      this.prisma.channel.count({ where: { workspaceId: wsId } }),
      this.prisma.channel.count({ where: { workspaceId: wsId, isArchived: false } }),
      this.prisma.workspaceMember.count({ where: { workspaceId: wsId, deactivatedAt: null } }),
      this.prisma.file.aggregate({
        where: { workspaceId: wsId, isDeleted: false },
        _sum: { sizeBytes: true },
        _count: true,
      }),
      this.prisma.huddle.aggregate({
        where: { workspaceId: wsId },
        _count: true,
      }),
    ]);

    // Get recent activity (last 7 days message count)
    const sevenDaysAgo = new Date();
    sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);

    const recentMessages = await this.prisma.message.count({
      where: {
        workspaceId: wsId,
        isDeleted: false,
        createdAt: { gte: sevenDaysAgo },
      },
    });

    // Active huddles
    const activeHuddles = await this.prisma.huddle.count({
      where: { workspaceId: wsId, status: 'active' },
    });

    return {
      messages: {
        total: messageCount,
        last_7_days: recentMessages,
      },
      channels: {
        total: channelCount,
        active: activeChannels,
      },
      members: {
        total: memberCount,
      },
      storage: {
        files_count: files._count,
        total_bytes: files._sum.sizeBytes?.toString() ?? '0',
      },
      huddles: {
        total: huddles._count,
        active: activeHuddles,
      },
    };
  }

  async getAuditLogs(wsId: string, userId: string, query: any) {
    await this.requireAdmin(wsId, userId);

    const limit = Math.min(parseInt(query.limit) || 50, 100);
    const page = parseInt(query.page) || 1;
    const skip = (page - 1) * limit;

    const where: any = { workspaceId: wsId };
    if (query.action) where.action = { contains: query.action, mode: 'insensitive' };
    if (query.actor_id) where.actorId = query.actor_id;

    const [logs, total] = await Promise.all([
      this.prisma.auditLog.findMany({
        where,
        orderBy: { createdAt: 'desc' },
        take: limit,
        skip,
        include: {
          actor: { select: { id: true, displayName: true, avatarUrl: true } },
        },
      }),
      this.prisma.auditLog.count({ where }),
    ]);

    return {
      logs: logs.map(l => ({
        id: l.id,
        actor: l.actor
          ? { id: l.actor.id, display_name: l.actor.displayName, avatar_url: l.actor.avatarUrl }
          : null,
        actor_type: l.actorType,
        action: l.action,
        entity_type: l.entityType,
        entity_id: l.entityId,
        details: l.details,
        ip_address: l.ipAddress,
        created_at: l.createdAt,
      })),
      total,
      page,
      limit,
      pages: Math.ceil(total / limit),
    };
  }

  async getMembers(wsId: string, userId: string, query: any) {
    await this.requireAdmin(wsId, userId);

    const limit = Math.min(parseInt(query.limit) || 50, 100);
    const page = parseInt(query.page) || 1;
    const skip = (page - 1) * limit;

    const where: any = { workspaceId: wsId };
    if (query.role) where.role = query.role;
    if (query.active === 'true') where.deactivatedAt = null;
    if (query.active === 'false') where.deactivatedAt = { not: null };

    const [members, total] = await Promise.all([
      this.prisma.workspaceMember.findMany({
        where,
        take: limit,
        skip,
        orderBy: { joinedAt: 'desc' },
        include: {
          user: {
            select: {
              id: true,
              email: true,
              displayName: true,
              realName: true,
              avatarUrl: true,
              title: true,
              isBot: true,
              lastActiveAt: true,
              presence: true,
            },
          },
          invitedByUser: { select: { id: true, displayName: true } },
          deactivatedByUser: { select: { id: true, displayName: true } },
        },
      }),
      this.prisma.workspaceMember.count({ where }),
    ]);

    return {
      members: members.map(m => ({
        id: m.id,
        user: {
          id: m.user.id,
          email: m.user.email,
          display_name: m.user.displayName,
          real_name: m.user.realName,
          avatar_url: m.user.avatarUrl,
          title: m.user.title,
          is_bot: m.user.isBot,
          last_active_at: m.user.lastActiveAt,
          presence: m.user.presence,
        },
        role: m.role,
        guest_type: m.guestType,
        display_name: m.displayName,
        title: m.title,
        joined_at: m.joinedAt,
        invited_by: m.invitedByUser,
        deactivated_at: m.deactivatedAt,
        deactivated_by: m.deactivatedByUser,
      })),
      total,
      page,
      limit,
      pages: Math.ceil(total / limit),
    };
  }

  async createEmoji(wsId: string, userId: string, dto: any) {
    await this.requireAdmin(wsId, userId);

    const emoji = await this.prisma.customEmoji.create({
      data: {
        workspaceId: wsId,
        name: dto.name,
        imageUrl: dto.image_url,
        aliases: dto.aliases || [],
        createdBy: userId,
      },
    });

    return emoji;
  }

  async listEmojis(wsId: string, userId: string) {
    await this.requireAdmin(wsId, userId);

    const emojis = await this.prisma.customEmoji.findMany({
      where: { workspaceId: wsId },
      orderBy: { name: 'asc' },
      include: {
        createdByUser: { select: { id: true, displayName: true } },
      },
    });

    return {
      emojis: emojis.map(e => ({
        id: e.id,
        name: e.name,
        image_url: e.imageUrl,
        aliases: e.aliases,
        created_by: e.createdByUser,
        created_at: e.createdAt,
      })),
    };
  }
}