import type { AdminUser } from '@core/admin/domain/entities/AdminUser';
import type { AdminUserRepository } from '@core/admin/domain/repositories/AdminUserRepository';
import { AuthorizationService } from '@core/admin/domain/services/AuthorizationService';
import { UserId } from '@core/admin/domain/value-objects/UserId';
import type { UserRole } from '@core/admin/domain/value-objects/UserRole';
import { Result } from '@core/shared/domain/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';

export interface DashboardStatsResult {
  totalUsers: number;
  activeUsers: number;
  suspendedUsers: number;
  deletedUsers: number;
  systemAdmins: number;
  recentLogins: number;
  newUsersToday: number;
  userGrowth: {
    label: string;
    value: number;
    color: string;
  }[];
  roleDistribution: {
    label: string;
    value: number;
    color: string;
  }[];
  statusDistribution: {
    active: number;
    suspended: number;
    deleted: number;
  };
  activityTimeline: {
    date: string;
    newUsers: number;
    logins: number;
  }[];
}

export type GetDashboardStatsInput = {
  actorId: string;
};

export type GetDashboardStatsErrorCode = 'AUTHORIZATION_ERROR' | 'REPOSITORY_ERROR';

export type GetDashboardStatsApplicationError = ApplicationErrorCode<GetDashboardStatsErrorCode, { message: string; details?: unknown }>;

export class GetDashboardStatsUseCase {
  constructor(
    private readonly adminUserRepo: AdminUserRepository,
  ) {}

  async execute(input: GetDashboardStatsInput): Promise<Result<DashboardStatsResult, GetDashboardStatsApplicationError>> {
    try {
      // Get actor (current user)
      const actor = await this.adminUserRepo.findById(UserId.fromString(input.actorId));
      
      if (!actor) {
        return Result.err({
          code: 'AUTHORIZATION_ERROR',
          details: { message: 'Actor not found' },
        });
      }

      // Check authorization
      if (!AuthorizationService.canListUsers(actor)) {
        return Result.err({
          code: 'AUTHORIZATION_ERROR',
          details: { message: 'User is not authorized to view dashboard' },
        });
      }

      // Get all users
      const allUsersResult = await this.adminUserRepo.list();
      const allUsers = allUsersResult.users;

      // Calculate basic stats
      const totalUsers = allUsers.length;
      const activeUsers = allUsers.filter((u: AdminUser) => u.status.value === 'active').length;
      const suspendedUsers = allUsers.filter((u: AdminUser) => u.status.value === 'suspended').length;
      const deletedUsers = allUsers.filter((u: AdminUser) => u.status.value === 'deleted').length;
      const systemAdmins = allUsers.filter((u: AdminUser) => u.isSystemAdmin()).length;
      
      // Recent logins (last 24 hours)
      const oneDayAgo = new Date();
      oneDayAgo.setDate(oneDayAgo.getDate() - 1);
      const recentLogins = allUsers.filter((u: AdminUser) => u.lastLoginAt && u.lastLoginAt > oneDayAgo).length;
      
      // New users today
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      const newUsersToday = allUsers.filter((u: AdminUser) => u.createdAt > today).length;

      // Role distribution
      const roleCounts: Record<string, number> = {};
      allUsers.forEach((user: AdminUser) => {
        user.roles.forEach((role: UserRole) => {
          const roleValue = role.value;
          roleCounts[roleValue] = (roleCounts[roleValue] || 0) + 1;
        });
      });

      const roleDistribution = Object.entries(roleCounts).map(([role, count]) => ({
        label: role.charAt(0).toUpperCase() + role.slice(1),
        value: count,
        color: role === 'owner' ? 'text-purple-500' : role === 'admin' ? 'text-blue-500' : 'text-gray-500',
      }));

      // User growth (last 7 days)
      const userGrowth: DashboardStatsResult['userGrowth'] = [];
      for (let i = 6; i >= 0; i--) {
        const date = new Date();
        date.setDate(date.getDate() - i);
        const dateStr = date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
        
        const count = allUsers.filter((u: AdminUser) => {
          const userDate = new Date(u.createdAt);
          return userDate.toDateString() === date.toDateString();
        }).length;

        userGrowth.push({
          label: dateStr,
          value: count,
          color: 'text-primary-blue',
        });
      }

      // Activity timeline (last 7 days)
      const activityTimeline: DashboardStatsResult['activityTimeline'] = [];
      for (let i = 6; i >= 0; i--) {
        const date = new Date();
        date.setDate(date.getDate() - i);
        const dateStr = date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
        
        const newUsers = allUsers.filter((u: AdminUser) => {
          const userDate = new Date(u.createdAt);
          return userDate.toDateString() === date.toDateString();
        }).length;

        const logins = allUsers.filter((u: AdminUser) => {
          const loginDate = u.lastLoginAt;
          return loginDate && loginDate.toDateString() === date.toDateString();
        }).length;

        activityTimeline.push({
          date: dateStr,
          newUsers,
          logins,
        });
      }

      const result: DashboardStatsResult = {
        totalUsers,
        activeUsers,
        suspendedUsers,
        deletedUsers,
        systemAdmins,
        recentLogins,
        newUsersToday,
        userGrowth,
        roleDistribution,
        statusDistribution: {
          active: activeUsers,
          suspended: suspendedUsers,
          deleted: deletedUsers,
        },
        activityTimeline,
      };

      return Result.ok(result);
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Failed to get dashboard stats';

      return Result.err({
        code: 'REPOSITORY_ERROR',
        details: { message },
      });
    }
  }
}
