'use server';

import {
  JiraAnalyticsService,
  JiraAnalyticsConfig,
} from '@/services/integrations/jira/analytics';
import { userPreferencesService } from '@/services/core/user-preferences';
import { SprintDetails } from '@/components/jira/SprintDetailModal';
import {
  JiraTask,
  AssigneeDistribution,
  StatusDistribution,
  SprintVelocity,
} from '@/lib/types';
import { parseDate } from '@/lib/date-utils';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';

export interface SprintDetailsResult {
  success: boolean;
  data?: SprintDetails;
  error?: string;
}

/**
 * Récupère les détails d'un sprint spécifique
 */
export async function getSprintDetails(
  sprintName: string
): Promise<SprintDetailsResult> {
  try {
    const session = await getServerSession(authOptions);
    if (!session?.user?.id) {
      return { success: false, error: 'Non authentifié' };
    }

    // Récupérer la config Jira
    const jiraConfig = await userPreferencesService.getJiraConfig(
      session.user.id
    );

    if (
      !jiraConfig?.baseUrl ||
      !jiraConfig?.email ||
      !jiraConfig?.apiToken ||
      !jiraConfig?.projectKey
    ) {
      return {
        success: false,
        error: 'Configuration Jira incomplète',
      };
    }

    // Récupérer les analytics générales pour trouver le sprint
    if (!jiraConfig.baseUrl || !jiraConfig.projectKey) {
      return { success: false, error: 'Configuration Jira incomplète' };
    }

    const analyticsService = new JiraAnalyticsService(
      jiraConfig as JiraAnalyticsConfig
    );
    const analytics = await analyticsService.getProjectAnalytics();

    const sprint = analytics.velocityMetrics.sprintHistory.find(
      (s) => s.sprintName === sprintName
    );
    if (!sprint) {
      return {
        success: false,
        error: `Sprint "${sprintName}" introuvable`,
      };
    }

    // Récupérer toutes les issues du projet pour filtrer par sprint
    const allIssues = await analyticsService.getAllProjectIssues();

    // Filtrer les issues pour ce sprint spécifique
    // Note: En réalité, il faudrait une requête JQL plus précise pour récupérer les issues d'un sprint
    // Pour simplifier, on prend les issues dans la période du sprint
    const sprintStart = parseDate(sprint.startDate);
    const sprintEnd = parseDate(sprint.endDate);

    const sprintIssues = allIssues.filter((issue) => {
      const issueDate = parseDate(issue.created);
      return issueDate >= sprintStart && issueDate <= sprintEnd;
    });

    // Calculer les métriques du sprint
    const sprintMetrics = calculateSprintMetrics(sprintIssues, sprint);

    // Calculer la distribution par assigné pour ce sprint
    const assigneeDistribution = calculateAssigneeDistribution(sprintIssues);

    // Calculer la distribution par statut pour ce sprint
    const statusDistribution = calculateStatusDistribution(sprintIssues);

    const sprintDetails: SprintDetails = {
      sprint,
      issues: sprintIssues,
      assigneeDistribution,
      statusDistribution,
      metrics: sprintMetrics,
    };

    return {
      success: true,
      data: sprintDetails,
    };
  } catch (error) {
    console.error(
      '❌ Erreur lors de la récupération des détails du sprint:',
      error
    );
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Erreur inconnue',
    };
  }
}

/**
 * Calcule les métriques spécifiques au sprint
 */
function calculateSprintMetrics(issues: JiraTask[], sprint: SprintVelocity) {
  const totalIssues = issues.length;
  const completedIssues = issues.filter(
    (issue) =>
      issue.status.category === 'Done' ||
      issue.status.name.toLowerCase().includes('done') ||
      issue.status.name.toLowerCase().includes('closed')
  ).length;

  const inProgressIssues = issues.filter(
    (issue) =>
      issue.status.category === 'In Progress' ||
      issue.status.name.toLowerCase().includes('progress') ||
      issue.status.name.toLowerCase().includes('review')
  ).length;

  const blockedIssues = issues.filter(
    (issue) =>
      issue.status.name.toLowerCase().includes('blocked') ||
      issue.status.name.toLowerCase().includes('waiting')
  ).length;

  // Calcul du cycle time moyen pour ce sprint
  const completedIssuesWithDates = issues.filter(
    (issue) =>
      issue.status.category === 'Done' && issue.created && issue.updated
  );

  let averageCycleTime = 0;
  if (completedIssuesWithDates.length > 0) {
    const totalCycleTime = completedIssuesWithDates.reduce((total, issue) => {
      const created = parseDate(issue.created);
      const updated = parseDate(issue.updated);
      const cycleTime =
        (updated.getTime() - created.getTime()) / (1000 * 60 * 60 * 24); // en jours
      return total + cycleTime;
    }, 0);
    averageCycleTime = totalCycleTime / completedIssuesWithDates.length;
  }

  // Déterminer la tendance de vélocité (simplifié)
  let velocityTrend: 'up' | 'down' | 'stable' = 'stable';
  if (sprint.completedPoints > sprint.plannedPoints * 0.9) {
    velocityTrend = 'up';
  } else if (sprint.completedPoints < sprint.plannedPoints * 0.7) {
    velocityTrend = 'down';
  }

  return {
    totalIssues,
    completedIssues,
    inProgressIssues,
    blockedIssues,
    averageCycleTime,
    velocityTrend,
  };
}

/**
 * Calcule la distribution par assigné pour le sprint
 */
function calculateAssigneeDistribution(
  issues: JiraTask[]
): AssigneeDistribution[] {
  const assigneeMap = new Map<
    string,
    { total: number; completed: number; inProgress: number }
  >();

  issues.forEach((issue) => {
    const assigneeName = issue.assignee?.displayName || 'Non assigné';
    const current = assigneeMap.get(assigneeName) || {
      total: 0,
      completed: 0,
      inProgress: 0,
    };

    current.total++;

    if (issue.status.category === 'Done') {
      current.completed++;
    } else if (issue.status.category === 'In Progress') {
      current.inProgress++;
    }

    assigneeMap.set(assigneeName, current);
  });

  return Array.from(assigneeMap.entries())
    .map(([displayName, stats]) => ({
      assignee: displayName === 'Non assigné' ? '' : displayName,
      displayName,
      totalIssues: stats.total,
      completedIssues: stats.completed,
      inProgressIssues: stats.inProgress,
      percentage: issues.length > 0 ? (stats.total / issues.length) * 100 : 0,
      count: stats.total, // Ajout pour compatibilité
    }))
    .sort((a, b) => b.totalIssues - a.totalIssues);
}

/**
 * Calcule la distribution par statut pour le sprint
 */
function calculateStatusDistribution(issues: JiraTask[]): StatusDistribution[] {
  const statusMap = new Map<string, number>();

  issues.forEach((issue) => {
    statusMap.set(
      issue.status.name,
      (statusMap.get(issue.status.name) || 0) + 1
    );
  });

  return Array.from(statusMap.entries())
    .map(([status, count]) => ({
      status,
      count,
      percentage: issues.length > 0 ? (count / issues.length) * 100 : 0,
    }))
    .sort((a, b) => b.count - a.count);
}
