import { TaskStatus } from '@/lib/types';
import { prisma } from '@/services/core/database';
import { getToday } from '@/lib/date-utils';

export interface DeadlineTask {
  id: string;
  title: string;
  status: TaskStatus;
  priority: string;
  dueDate: Date;
  daysRemaining: number;
  urgencyLevel: 'overdue' | 'critical' | 'warning' | 'normal';
  source: string;
  tags: string[];
  jiraKey?: string;
}

export interface DeadlineMetrics {
  overdue: DeadlineTask[];
  critical: DeadlineTask[]; // 0-2 jours
  warning: DeadlineTask[]; // 3-7 jours
  upcoming: DeadlineTask[]; // 8-14 jours
  summary: {
    overdueCount: number;
    criticalCount: number;
    warningCount: number;
    upcomingCount: number;
    totalWithDeadlines: number;
  };
}

export class DeadlineAnalyticsService {
  /**
   * Analyse les tâches selon leurs échéances
   */
  static async getDeadlineMetrics(
    userId: string,
    sources?: string[]
  ): Promise<DeadlineMetrics> {
    try {
      const now = getToday();

      // Récupérer toutes les tâches non terminées avec échéance
      const dbTasks = await prisma.task.findMany({
        where: {
          ownerId: userId,
          dueDate: {
            not: null,
          },
          status: {
            notIn: ['done', 'cancelled', 'archived'],
          },
        },
        include: {
          taskTags: {
            include: {
              tag: true,
            },
          },
        },
        orderBy: {
          dueDate: 'asc',
        },
      });

      // Convertir et analyser les tâches
      let deadlineTasks: DeadlineTask[] = dbTasks.map((task) => {
        const dueDate = task.dueDate!;
        const daysRemaining = Math.ceil(
          (dueDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)
        );

        let urgencyLevel: DeadlineTask['urgencyLevel'];
        if (daysRemaining < 0) {
          urgencyLevel = 'overdue';
        } else if (daysRemaining <= 2) {
          urgencyLevel = 'critical';
        } else if (daysRemaining <= 7) {
          urgencyLevel = 'warning';
        } else {
          urgencyLevel = 'normal';
        }

        return {
          id: task.id,
          title: task.title,
          status: task.status as TaskStatus,
          priority: task.priority,
          dueDate,
          daysRemaining,
          urgencyLevel,
          source: task.source,
          tags: task.taskTags.map((tt) => tt.tag.name),
          jiraKey: task.jiraKey || undefined,
        };
      });

      // Filtrer par sources si spécifié
      if (sources && sources.length > 0) {
        deadlineTasks = deadlineTasks.filter((task) =>
          sources.includes(task.source)
        );
      }

      // Filtrer les tâches dans les 2 prochaines semaines
      const relevantTasks = deadlineTasks.filter(
        (task) => task.daysRemaining <= 14 || task.urgencyLevel === 'overdue'
      );

      const overdue = relevantTasks.filter((t) => t.urgencyLevel === 'overdue');
      const critical = relevantTasks.filter(
        (t) => t.urgencyLevel === 'critical'
      );
      const warning = relevantTasks.filter((t) => t.urgencyLevel === 'warning');
      const upcoming = relevantTasks.filter(
        (t) => t.urgencyLevel === 'normal' && t.daysRemaining <= 14
      );

      return {
        overdue,
        critical,
        warning,
        upcoming,
        summary: {
          overdueCount: overdue.length,
          criticalCount: critical.length,
          warningCount: warning.length,
          upcomingCount: upcoming.length,
          totalWithDeadlines: deadlineTasks.length,
        },
      };
    } catch (error) {
      console.error("Erreur lors de l'analyse des échéances:", error);
      throw new Error("Impossible d'analyser les échéances");
    }
  }

  /**
   * Retourne les tâches les plus critiques (en retard + échéance dans 48h)
   */
  static async getCriticalDeadlines(
    userId: string,
    sources?: string[]
  ): Promise<DeadlineTask[]> {
    const metrics = await this.getDeadlineMetrics(userId, sources);
    return [...metrics.overdue, ...metrics.critical].slice(0, 10); // Limite à 10 tâches les plus critiques
  }

  /**
   * Analyse l'impact des échéances par priorité
   */
  static analyzeImpactByPriority(tasks: DeadlineTask[]): Array<{
    priority: string;
    count: number;
    overdueCount: number;
    criticalCount: number;
  }> {
    const priorityGroups = new Map<string, DeadlineTask[]>();

    tasks.forEach((task) => {
      const priority = task.priority || 'medium';
      if (!priorityGroups.has(priority)) {
        priorityGroups.set(priority, []);
      }
      priorityGroups.get(priority)!.push(task);
    });

    return Array.from(priorityGroups.entries())
      .map(([priority, tasks]) => ({
        priority,
        count: tasks.length,
        overdueCount: tasks.filter((t) => t.urgencyLevel === 'overdue').length,
        criticalCount: tasks.filter((t) => t.urgencyLevel === 'critical')
          .length,
      }))
      .sort((a, b) => {
        // Trier par impact (retard + critique) puis par priorité
        const aImpact = a.overdueCount + a.criticalCount;
        const bImpact = b.overdueCount + b.criticalCount;
        if (aImpact !== bImpact) return bImpact - aImpact;

        const priorityOrder: Record<string, number> = {
          urgent: 4,
          high: 3,
          medium: 2,
          low: 1,
        };
        return (
          (priorityOrder[b.priority] || 2) - (priorityOrder[a.priority] || 2)
        );
      });
  }

  /**
   * Calcule les métriques de risque
   */
  static calculateRiskMetrics(metrics: DeadlineMetrics): {
    riskScore: number; // 0-100
    riskLevel: 'low' | 'medium' | 'high' | 'critical';
    recommendation: string;
  } {
    const { summary } = metrics;

    // Calcul du score de risque basé sur les échéances
    let riskScore = 0;
    riskScore += summary.overdueCount * 25; // Retard = très grave
    riskScore += summary.criticalCount * 15; // Critique = grave
    riskScore += summary.warningCount * 5; // Avertissement = attention
    riskScore += summary.upcomingCount * 1; // À venir = surveillance

    // Limiter à 100
    riskScore = Math.min(riskScore, 100);

    let riskLevel: 'low' | 'medium' | 'high' | 'critical';
    let recommendation: string;

    if (riskScore >= 75) {
      riskLevel = 'critical';
      recommendation =
        'Action immédiate requise ! Plusieurs tâches en retard ou critiques.';
    } else if (riskScore >= 50) {
      riskLevel = 'high';
      recommendation =
        'Attention : échéances critiques approchent, planifier les priorités.';
    } else if (riskScore >= 25) {
      riskLevel = 'medium';
      recommendation =
        'Surveillance nécessaire, quelques échéances à surveiller.';
    } else {
      riskLevel = 'low';
      recommendation = 'Situation stable, échéances sous contrôle.';
    }

    return { riskScore, riskLevel, recommendation };
  }
}
