import { Injectable } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { UserPreferencesService } from '../user-preferences/user-preferences.service';
import { Prisma, ApprovalStatus } from '@prisma/client';

export interface DashboardStats {
  users?: {
    total: number;
    active: number;
    newThisMonth: number;
  };
  departments: {
    total: number;
    active: number;
  };
  employees?: {
    total: number;
    active: number;
  };
  absences?: {
    pending: number;
    approved: number;
    total: number;
  };
  // Basic stats for all users
  myDepartment?: {
    name: string;
    employeeCount: number;
  };
}

export interface WidgetType {
  id: string;
  name: string;
  description: string;
  minWidth: number;
  minHeight: number;
  maxWidth: number;
  maxHeight: number;
  category: string;
  requiredPermissions?: string[];
}

@Injectable()
export class DashboardService {
  constructor(
    private readonly prisma: PrismaService,
    private readonly preferencesService: UserPreferencesService,
  ) {}

  /**
   * Get dashboard statistics based on user role
   * - Admin/Manager: Full statistics
   * - Department Head: Department-specific statistics
   * - Employee: Basic statistics only
   */
  async getStats(userId: string, userRoles: string[]): Promise<DashboardStats> {
    const isAdmin = userRoles.includes('admin');
    const isManager = userRoles.includes('manager') || userRoles.includes('hr-manager');
    const isDeptHead = userRoles.includes('department_head') || userRoles.includes('team-lead');

    const now = new Date();
    const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);

    // Basic stats for all users - department count only
    const [totalDepartments, activeDepartments] = await Promise.all([
      this.prisma.department.count(),
      this.prisma.department.count({ where: { isActive: true } }),
    ]);

    const baseStats: DashboardStats = {
      departments: {
        total: totalDepartments,
        active: activeDepartments,
      },
    };

    // Admin and Manager get full statistics
    if (isAdmin || isManager) {
      const [
        totalUsers,
        activeUsers,
        newUsersThisMonth,
        totalEmployees,
        activeEmployees,
        pendingAbsences,
        approvedAbsences,
        totalAbsences,
      ] = await Promise.all([
        this.prisma.user.count(),
        this.prisma.user.count({ where: { isActive: true } }),
        this.prisma.user.count({ where: { createdAt: { gte: startOfMonth } } }),
        this.prisma.employee.count(),
        this.prisma.employee.count({ where: { isActive: true } }),
        this.prisma.absence.count({ where: { status: ApprovalStatus.PENDING } }),
        this.prisma.absence.count({ where: { status: ApprovalStatus.APPROVED } }),
        this.prisma.absence.count(),
      ]);

      return {
        ...baseStats,
        users: { total: totalUsers, active: activeUsers, newThisMonth: newUsersThisMonth },
        employees: { total: totalEmployees, active: activeEmployees },
        absences: { pending: pendingAbsences, approved: approvedAbsences, total: totalAbsences },
      };
    }

    // Department Head gets department-specific stats
    if (isDeptHead) {
      const user = await this.prisma.user.findUnique({
        where: { id: userId },
        include: { department: true },
      });

      if (user?.departmentId) {
        const [deptEmployees, deptAbsences] = await Promise.all([
          this.prisma.employee.count({ where: { user: { departmentId: user.departmentId } } }),
          this.prisma.absence.count({
            where: {
              employee: { user: { departmentId: user.departmentId } },
              status: ApprovalStatus.PENDING,
            },
          }),
        ]);

        return {
          ...baseStats,
          myDepartment: {
            name: user.department?.name || 'Unknown',
            employeeCount: deptEmployees,
          },
          absences: { pending: deptAbsences, approved: 0, total: 0 },
        };
      }
    }

    // Regular employee - basic stats only
    return baseStats;
  }

  /**
   * Get available widget types
   */
  getWidgetTypes(): WidgetType[] {
    return [
      {
        id: 'statistics',
        name: 'Statistics Overview',
        description: 'Display key metrics and statistics',
        minWidth: 2,
        minHeight: 1,
        maxWidth: 4,
        maxHeight: 2,
        category: 'overview',
      },
      {
        id: 'activity',
        name: 'Recent Activity',
        description: 'Show recent system activity and events',
        minWidth: 2,
        minHeight: 2,
        maxWidth: 4,
        maxHeight: 4,
        category: 'overview',
        requiredPermissions: ['audit:view'],
      },
      {
        id: 'actions',
        name: 'Quick Actions',
        description: 'Shortcuts to common actions',
        minWidth: 1,
        minHeight: 1,
        maxWidth: 2,
        maxHeight: 2,
        category: 'productivity',
      },
      {
        id: 'absences',
        name: 'Upcoming Absences',
        description: 'View upcoming team absences',
        minWidth: 2,
        minHeight: 2,
        maxWidth: 4,
        maxHeight: 4,
        category: 'hr',
        requiredPermissions: ['absences:view'],
      },
      {
        id: 'team',
        name: 'Team Overview',
        description: 'Quick view of your team members',
        minWidth: 2,
        minHeight: 2,
        maxWidth: 4,
        maxHeight: 4,
        category: 'hr',
        requiredPermissions: ['employees:view'],
      },
      {
        id: 'calendar',
        name: 'Calendar',
        description: 'View upcoming events and deadlines',
        minWidth: 2,
        minHeight: 2,
        maxWidth: 4,
        maxHeight: 4,
        category: 'productivity',
      },
      {
        id: 'time-tracking',
        name: 'Time Tracking',
        description: 'Quick time entry and overview',
        minWidth: 2,
        minHeight: 1,
        maxWidth: 4,
        maxHeight: 2,
        category: 'productivity',
        requiredPermissions: ['time_entries:view'],
      },
      {
        id: 'announcements',
        name: 'Announcements',
        description: 'System and company announcements',
        minWidth: 2,
        minHeight: 2,
        maxWidth: 4,
        maxHeight: 3,
        category: 'overview',
      },
      {
        id: 'department-stats',
        name: 'Department Statistics',
        description: 'Statistics for managed departments',
        minWidth: 2,
        minHeight: 2,
        maxWidth: 4,
        maxHeight: 4,
        category: 'hr',
        requiredPermissions: ['departments:view'],
      },
      {
        id: 'pending-approvals',
        name: 'Pending Approvals',
        description: 'Requests waiting for your approval',
        minWidth: 2,
        minHeight: 2,
        maxWidth: 4,
        maxHeight: 4,
        category: 'hr',
        requiredPermissions: ['absences:approve'],
      },
    ];
  }

  /**
   * Get user's dashboard layout
   */
  async getLayout(userId: string) {
    const preferences = await this.preferencesService.findByUserId(userId);
    return {
      layout: preferences.dashboardLayout || this.getDefaultLayout(),
    };
  }

  /**
   * Save user's dashboard layout
   */
  async saveLayout(userId: string, layout: unknown[]) {
    return this.preferencesService.updateDashboardLayout(userId, layout);
  }

  /**
   * Get recent activity for dashboard widget
   * Admins see all activity, others see only their own
   */
  async getRecentActivity(userId: string, userRoles: string[], limit = 10) {
    const isAdmin = userRoles.includes('admin');
    const isManager = userRoles.includes('manager') || userRoles.includes('hr-manager');

    // Only admins and managers can see all activity
    const where = isAdmin || isManager ? {} : { userId };

    return this.prisma.auditLog.findMany({
      where,
      take: limit,
      orderBy: { createdAt: 'desc' },
      include: {
        user: {
          select: {
            id: true,
            firstName: true,
            lastName: true,
            email: true,
          },
        },
      },
    });
  }

  /**
   * Get upcoming absences for dashboard widget
   * Filtered by user role and department
   */
  async getUpcomingAbsences(userId: string, userRoles: string[], limit = 5) {
    const today = new Date();
    today.setHours(0, 0, 0, 0);

    const isAdmin = userRoles.includes('admin');
    const isManager = userRoles.includes('manager') || userRoles.includes('hr-manager');
    const isDeptHead = userRoles.includes('department_head') || userRoles.includes('team-lead');

    // Build where clause based on role
    let additionalWhere = {};

    if (!isAdmin && !isManager) {
      if (isDeptHead) {
        // Department head sees their department's absences
        const user = await this.prisma.user.findUnique({
          where: { id: userId },
          select: { departmentId: true },
        });
        if (user?.departmentId) {
          additionalWhere = { employee: { user: { departmentId: user.departmentId } } };
        }
      } else {
        // Regular employee sees only their own absences
        additionalWhere = { employee: { userId } };
      }
    }

    return this.prisma.absence.findMany({
      where: {
        startDate: { gte: today },
        status: { in: [ApprovalStatus.PENDING, ApprovalStatus.APPROVED] },
        ...additionalWhere,
      },
      take: limit,
      orderBy: { startDate: 'asc' },
      include: {
        employee: {
          include: {
            user: {
              select: {
                id: true,
                firstName: true,
                lastName: true,
              },
            },
          },
        },
      },
    });
  }

  /**
   * Get pending approvals count
   */
  async getPendingApprovalsCount() {
    return this.prisma.absence.count({
      where: { status: 'PENDING' },
    });
  }

  /**
   * Default dashboard layout
   */
  private getDefaultLayout(): Prisma.JsonArray {
    return [
      { id: 'stats-overview', type: 'statistics', x: 0, y: 0, w: 4, h: 1 },
      { id: 'recent-activity', type: 'activity', x: 0, y: 1, w: 2, h: 2 },
      { id: 'quick-actions', type: 'actions', x: 2, y: 1, w: 2, h: 2 },
      { id: 'upcoming-absences', type: 'absences', x: 0, y: 3, w: 2, h: 2 },
      { id: 'team-overview', type: 'team', x: 2, y: 3, w: 2, h: 2 },
    ];
  }
}
