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

type TaskType = {
  id: string;
  title: string;
  description?: string | null;
  priority: string; // high, medium, low
  completedAt?: Date | null;
  createdAt: Date;
  updatedAt: Date;
  taskTags?: {
    tag: {
      name: string;
    };
  }[];
};

type CheckboxType = {
  id: string;
  text: string;
  isChecked: boolean;
  type: string; // task, meeting
  date: Date;
  createdAt: Date;
  task?: {
    id: string;
    title: string;
    priority: string;
    taskTags?: {
      tag: {
        name: string;
      };
    }[];
  } | null;
};

export interface KeyAccomplishment {
  id: string;
  title: string;
  description?: string;
  tags: string[];
  impact: 'high' | 'medium' | 'low';
  completedAt: Date;
  updatedAt: Date;
  relatedItems: string[]; // IDs des tâches/checkboxes liées
  todosCount: number; // Nombre de todos associés
}

export interface UpcomingChallenge {
  id: string;
  title: string;
  description?: string;
  tags: string[];
  priority: 'high' | 'medium' | 'low';
  estimatedEffort: 'days' | 'weeks' | 'hours';
  blockers: string[];
  deadline?: Date;
  relatedItems: string[]; // IDs des tâches/checkboxes liées
  todosCount: number; // Nombre de todos associés
}

export interface ManagerSummary {
  period: {
    start: Date;
    end: Date;
  };
  keyAccomplishments: KeyAccomplishment[];
  upcomingChallenges: UpcomingChallenge[];
  metrics: {
    totalTasksCompleted: number;
    totalCheckboxesCompleted: number;
    highPriorityTasksCompleted: number;
    meetingCheckboxesCompleted: number;
    completionRate: number;
    focusAreas: { [category: string]: number };
  };
  narrative: {
    weekHighlight: string;
    mainChallenges: string;
    nextWeekFocus: string;
  };
}

export class ManagerSummaryService {
  /**
   * Génère un résumé orienté manager pour les 7 derniers jours
   */
  static async getManagerSummary(
    userId: string,
    date: Date = getToday()
  ): Promise<ManagerSummary> {
    // Fenêtre glissante de 7 jours au lieu de semaine calendaire
    const weekEnd = new Date(date);
    const weekStart = new Date(date);
    weekStart.setDate(weekStart.getDate() - 6); // 7 jours en arrière (incluant aujourd'hui)

    // Récupérer les données de base
    const [tasks, checkboxes] = await Promise.all([
      this.getCompletedTasks(userId, weekStart, weekEnd),
      this.getCompletedCheckboxes(userId, weekStart, weekEnd),
    ]);

    // Analyser et extraire les accomplissements clés
    const keyAccomplishments = await this.extractKeyAccomplishments(
      tasks,
      checkboxes
    );

    // Identifier les défis à venir
    const upcomingChallenges = await this.identifyUpcomingChallenges(userId);

    // Calculer les métriques
    const metrics = this.calculateMetrics(tasks, checkboxes);

    // Générer le narratif
    const narrative = this.generateNarrative(
      keyAccomplishments,
      upcomingChallenges
    );

    return {
      period: { start: weekStart, end: weekEnd },
      keyAccomplishments,
      upcomingChallenges,
      metrics,
      narrative,
    };
  }

  /**
   * Récupère les tâches complétées de la semaine
   */
  private static async getCompletedTasks(
    userId: string,
    startDate: Date,
    endDate: Date
  ) {
    const tasks = await prisma.task.findMany({
      where: {
        ownerId: userId,
        OR: [
          // Tâches avec completedAt dans la période (priorité)
          {
            completedAt: {
              gte: startDate,
              lte: endDate,
            },
          },
        ],
      },
      orderBy: {
        completedAt: 'desc',
      },
      select: {
        id: true,
        title: true,
        description: true,
        priority: true,
        completedAt: true,
        createdAt: true,
        updatedAt: true,
        taskTags: {
          select: {
            tag: {
              select: {
                name: true,
              },
            },
          },
        },
      },
    });

    return tasks;
  }

  /**
   * Récupère les checkboxes complétées de la semaine
   */
  private static async getCompletedCheckboxes(
    userId: string,
    startDate: Date,
    endDate: Date
  ) {
    const checkboxes = await prisma.dailyCheckbox.findMany({
      where: {
        userId: userId,
        isChecked: true,
        date: {
          gte: startDate,
          lte: endDate,
        },
        // S'assurer que si le todo est lié à une tâche, cette tâche appartient bien à l'utilisateur
        OR: [
          { task: null }, // Todos standalone (sans tâche associée)
          { task: { ownerId: userId } }, // Todos liés à une tâche de l'utilisateur
        ],
      },
      select: {
        id: true,
        text: true,
        isChecked: true,
        type: true,
        date: true,
        createdAt: true,
        task: {
          select: {
            id: true,
            title: true,
            priority: true,
            taskTags: {
              select: {
                tag: {
                  select: {
                    name: true,
                  },
                },
              },
            },
          },
        },
      },
      orderBy: {
        date: 'desc',
      },
    });

    return checkboxes;
  }

  /**
   * Extrait les accomplissements clés basés sur la priorité
   */
  private static async extractKeyAccomplishments(
    tasks: TaskType[],
    checkboxes: CheckboxType[]
  ): Promise<KeyAccomplishment[]> {
    const accomplishments: KeyAccomplishment[] = [];

    // Tâches: prendre toutes les high/medium priority, et quelques low si significatives
    for (const task of tasks) {
      const priority = task.priority.toLowerCase();

      // Convertir priorité task en impact accomplissement
      let impact: 'high' | 'medium' | 'low';
      if (priority === 'high' || priority === 'urgent') {
        impact = 'high';
      } else if (priority === 'medium') {
        impact = 'medium';
      } else {
        // Pour les low priority, tout prendre
        impact = 'low';
      }

      // Compter TOUS les todos associés à cette tâche (pas seulement ceux de la période)
      // Exclure les todos de type "meeting" (réunion)
      // car l'accomplissement c'est la tâche complétée, pas seulement les todos de la période
      const allRelatedTodos = await prisma.dailyCheckbox.count({
        where: {
          task: {
            id: task.id,
          },
          type: {
            not: 'meeting', // Exclure les réunions
          },
        },
      });

      accomplishments.push({
        id: `task-${task.id}`,
        title: task.title,
        description: task.description || undefined,
        tags: task.taskTags?.map((tt) => tt.tag.name) || [],
        impact,
        completedAt: task.completedAt || task.updatedAt,
        updatedAt: task.updatedAt,
        relatedItems: [task.id],
        todosCount: allRelatedTodos, // Nombre total de todos associés à cette tâche
      });
    }

    // AJOUTER les todos standalone avec la nouvelle règle de priorité
    // Exclure les todos déjà comptés dans les tâches complétées
    // Exclure les todos de type "meeting" (réunion)
    const standaloneTodos = checkboxes.filter(
      (checkbox) => !checkbox.task && checkbox.type !== 'meeting' // Todos non liés à une tâche et pas de type meeting
    );

    standaloneTodos.forEach((todo) => {
      // Appliquer la nouvelle règle de priorité :
      // Si pas de tâche associée, priorité faible
      const impact: 'high' | 'medium' | 'low' = 'low';

      accomplishments.push({
        id: `todo-${todo.id}`,
        title: todo.text,
        tags: [], // Todos standalone n'ont pas de tags par défaut
        impact,
        completedAt: todo.date,
        updatedAt: todo.date, // Pour les todos, updatedAt = completedAt
        relatedItems: [todo.id],
        todosCount: 1, // Un todo = 1 todo
      });
    });

    // Trier par impact puis par date
    return accomplishments.sort((a, b) => {
      const impactOrder = { high: 3, medium: 2, low: 1 };
      if (impactOrder[a.impact] !== impactOrder[b.impact]) {
        return impactOrder[b.impact] - impactOrder[a.impact];
      }
      return b.completedAt.getTime() - a.completedAt.getTime();
    });
    // Pas de limite - afficher tous les accomplissements
  }

  /**
   * Identifie les défis et enjeux à venir
   */
  private static async identifyUpcomingChallenges(
    userId: string
  ): Promise<UpcomingChallenge[]> {
    // Récupérer les tâches à venir (priorité high/medium en premier)
    const upcomingTasks = await prisma.task.findMany({
      where: {
        ownerId: userId,
        completedAt: null,
      },
      orderBy: [
        { priority: 'asc' }, // high < medium < low
        { createdAt: 'desc' },
      ],
      select: {
        id: true,
        title: true,
        description: true,
        priority: true,
        createdAt: true,
        taskTags: {
          select: {
            tag: {
              select: {
                name: true,
              },
            },
          },
        },
      },
      take: 30,
    });

    // Récupérer les checkboxes récurrentes non complétées (meetings + tâches prioritaires)
    const upcomingCheckboxes = await prisma.dailyCheckbox.findMany({
      where: {
        userId: userId, // Filtrer par utilisateur
        isChecked: false,
        date: {
          gte: getToday(),
        },
        // S'assurer que si le todo est lié à une tâche, cette tâche appartient bien à l'utilisateur
        AND: [
          {
            OR: [
              { task: null }, // Todos standalone (sans tâche associée)
              { task: { ownerId: userId } }, // Todos liés à une tâche de l'utilisateur
            ],
          },
          {
            OR: [
              { type: 'meeting' },
              {
                task: {
                  priority: {
                    in: ['high', 'medium'],
                  },
                },
              },
            ],
          },
        ],
      },
      select: {
        id: true,
        text: true,
        isChecked: true,
        type: true,
        date: true,
        createdAt: true,
        task: {
          select: {
            id: true,
            title: true,
            priority: true,
            taskTags: {
              select: {
                tag: {
                  select: {
                    name: true,
                  },
                },
              },
            },
          },
        },
      },
      orderBy: [{ date: 'asc' }, { createdAt: 'asc' }],
      take: 20,
    });

    const challenges: UpcomingChallenge[] = [];

    // Analyser les tâches - se baser sur la priorité réelle
    upcomingTasks.forEach((task) => {
      const taskPriority = task.priority.toLowerCase();

      // Convertir priorité task en priorité challenge
      let priority: 'high' | 'medium' | 'low';
      if (taskPriority === 'high' || taskPriority === 'urgent') {
        priority = 'high';
      } else if (taskPriority === 'medium') {
        priority = 'medium';
      } else {
        // Pour les low priority, tout prendre
        priority = 'low';
      }

      const estimatedEffort = this.estimateEffort(
        task.title,
        task.description || undefined
      );

      // Compter les todos associés à cette tâche
      const relatedTodos = upcomingCheckboxes.filter(
        (cb) => cb.task?.id === task.id
      );

      challenges.push({
        id: `task-${task.id}`,
        title: task.title,
        description: task.description || undefined,
        tags: task.taskTags?.map((tt) => tt.tag.name) || [],
        priority,
        estimatedEffort,
        blockers: this.identifyBlockers(
          task.title,
          task.description || undefined
        ),
        relatedItems: [task.id, ...relatedTodos.map((t) => t.id)],
        todosCount: relatedTodos.length, // Nombre réel de todos associés
      });
    });

    // Ajouter les todos importants comme challenges
    upcomingCheckboxes.forEach((checkbox) => {
      // Déterminer la priorité selon la nouvelle règle :
      // Si le todo est associé à une tâche, prendre la priorité de la tâche
      // Sinon, priorité faible par défaut (même pour les meetings)
      let priority: 'high' | 'medium' | 'low';

      if (checkbox.task?.priority) {
        const taskPriority = checkbox.task.priority.toLowerCase();
        if (taskPriority === 'high') {
          priority = 'high';
        } else if (taskPriority === 'medium') {
          priority = 'medium';
        } else {
          priority = 'low';
        }
      } else {
        // Pas de tâche associée = priorité faible (même pour les meetings)
        priority = 'low';
      }

      // Inclure tous les todos (toutes priorités, y compris faible, sont maintenant visibles)
      // La priorité est déterminée par la nouvelle règle et affichée visuellement
      challenges.push({
        id: `checkbox-${checkbox.id}`,
        title: checkbox.text,
        tags: checkbox.task?.taskTags?.map((tt) => tt.tag.name) || [],
        priority,
        estimatedEffort: 'hours',
        blockers: [],
        relatedItems: [checkbox.id],
        todosCount: 1, // Une checkbox = 1 todo
      });
    });

    return challenges.sort((a, b) => {
      const priorityOrder = { high: 3, medium: 2, low: 1 };
      return priorityOrder[b.priority] - priorityOrder[a.priority];
    });
    // Pas de limite - afficher tous les challenges
  }

  /**
   * Estime l'effort requis
   */
  private static estimateEffort(
    title: string,
    description?: string
  ): 'days' | 'weeks' | 'hours' {
    const content = `${title} ${description || ''}`.toLowerCase();

    if (
      content.includes('architecture') ||
      content.includes('migration') ||
      content.includes('refactor')
    ) {
      return 'weeks';
    }
    if (
      content.includes('feature') ||
      content.includes('implement') ||
      content.includes('integration')
    ) {
      return 'days';
    }
    return 'hours';
  }

  /**
   * Identifie les blockers potentiels
   */
  private static identifyBlockers(
    title: string,
    description?: string
  ): string[] {
    const content = `${title} ${description || ''}`.toLowerCase();
    const blockers: string[] = [];

    if (content.includes('depends') || content.includes('waiting')) {
      blockers.push('Dépendances externes');
    }
    if (content.includes('approval') || content.includes('review')) {
      blockers.push('Validation requise');
    }
    if (content.includes('design') && !content.includes('implement')) {
      blockers.push('Spécifications incomplètes');
    }

    return blockers;
  }

  /**
   * Calcule les métriques résumées
   */
  private static calculateMetrics(
    tasks: TaskType[],
    checkboxes: CheckboxType[]
  ) {
    const totalTasksCompleted = tasks.length;
    const totalCheckboxesCompleted = checkboxes.length;

    // Calculer les métriques détaillées
    const highPriorityTasksCompleted = tasks.filter(
      (t) => t.priority.toLowerCase() === 'high'
    ).length;
    const meetingCheckboxesCompleted = checkboxes.filter(
      (c) => c.type === 'meeting'
    ).length;

    // Analyser la répartition par catégorie
    const focusAreas: { [category: string]: number } = {};

    return {
      totalTasksCompleted,
      totalCheckboxesCompleted,
      highPriorityTasksCompleted,
      meetingCheckboxesCompleted,
      completionRate: 0, // À calculer par rapport aux objectifs
      focusAreas,
    };
  }

  /**
   * Génère le narratif pour le manager
   */
  private static generateNarrative(
    accomplishments: KeyAccomplishment[],
    challenges: UpcomingChallenge[]
  ) {
    // Points forts des 7 derniers jours
    const topAccomplishments = accomplishments.slice(0, 3);
    const weekHighlight =
      topAccomplishments.length > 0
        ? `Ces 7 derniers jours, j'ai principalement progressé sur ${topAccomplishments.map((a) => a.title).join(', ')}.`
        : "Période focalisée sur l'exécution des tâches quotidiennes.";

    // Défis rencontrés
    const highImpactItems = accomplishments.filter((a) => a.impact === 'high');
    const mainChallenges =
      highImpactItems.length > 0
        ? `Les principaux enjeux traités ont été liés aux ${[...new Set(highImpactItems.flatMap((a) => a.tags))].join(', ')}.`
        : 'Pas de blockers majeurs rencontrés sur cette période.';

    // Focus 7 prochains jours
    const topChallenges = challenges.slice(0, 3);
    const nextWeekFocus =
      topChallenges.length > 0
        ? `Les 7 prochains jours seront concentrés sur ${topChallenges.map((c) => c.title).join(', ')}.`
        : 'Continuation du travail en cours selon les priorités établies.';

    return {
      weekHighlight,
      mainChallenges,
      nextWeekFocus,
    };
  }
}
