/**
 * Tests unitaires pour la synchronisation Jira
 */

import { describe, it, expect } from 'vitest';
import { buildSyncUpdateData } from '@/services/task-management/readonly-fields';
import { detectSyncChanges } from '@/services/integrations/jira/jira';

describe('Synchronisation Jira - Logique de préservation des champs', () => {
  describe('buildSyncUpdateData pour Jira', () => {
    it('devrait préserver title si modifié localement', () => {
      const existingTask = {
        title: 'Titre modifié localement',
        description: 'Description locale',
        status: 'todo',
        priority: 'high',
        dueDate: new Date('2024-01-01'),
      };

      const syncData = {
        title: 'Titre original Jira',
        description: 'Description Jira',
        status: 'in_progress',
        priority: 'medium',
        dueDate: new Date('2024-01-02'),
      };

      const result = buildSyncUpdateData('jira', existingTask, syncData);

      expect(result.title).toBe('Titre modifié localement');
      expect(result.description).toBe('Description Jira'); // Écrasé
      expect(result.status).toBe('in_progress'); // Écrasé
      expect(result.priority).toBe('high'); // Préservé
      expect(result.dueDate).toEqual(new Date('2024-01-02')); // Écrasé
    });

    it('devrait préserver priority si modifié localement', () => {
      const existingTask = {
        title: 'Même titre',
        description: 'Description locale',
        status: 'todo',
        priority: 'low', // Modifié localement
        dueDate: new Date('2024-01-01'),
      };

      const syncData = {
        title: 'Même titre',
        description: 'Description Jira',
        status: 'done',
        priority: 'high', // Valeur Jira
        dueDate: null,
      };

      const result = buildSyncUpdateData('jira', existingTask, syncData);

      expect(result.priority).toBe('low'); // Préservé car modifié localement
    });

    it('devrait préserver status archived même si Jira dit done', () => {
      const existingTask = {
        title: 'Tâche archivée',
        description: 'Description',
        status: 'archived', // Archivé localement
        priority: 'medium',
        dueDate: null,
      };

      const syncData = {
        title: 'Tâche archivée',
        description: 'Description Jira',
        status: 'done', // Jira dit done
        priority: 'medium',
        dueDate: null,
      };

      const result = buildSyncUpdateData('jira', existingTask, syncData);

      expect(result.status).toBe('archived'); // Préservé car archived
    });

    it('devrait écraser status si pas archived', () => {
      const existingTask = {
        title: 'Tâche',
        description: 'Description',
        status: 'todo',
        priority: 'medium',
        dueDate: null,
      };

      const syncData = {
        title: 'Tâche',
        description: 'Description Jira',
        status: 'in_progress', // Jira dit in_progress
        priority: 'medium',
        dueDate: null,
      };

      const result = buildSyncUpdateData('jira', existingTask, syncData);

      expect(result.status).toBe('in_progress'); // Écrasé
    });

    it('devrait toujours écraser description', () => {
      const existingTask = {
        title: 'Tâche',
        description: 'Description locale modifiée',
        status: 'todo',
        priority: 'medium',
        dueDate: null,
      };

      const syncData = {
        title: 'Tâche',
        description: 'Description Jira',
        status: 'todo',
        priority: 'medium',
        dueDate: null,
      };

      const result = buildSyncUpdateData('jira', existingTask, syncData);

      expect(result.description).toBe('Description Jira'); // Toujours écrasé
    });

    it('devrait toujours écraser dueDate', () => {
      const existingTask = {
        title: 'Tâche',
        description: 'Description',
        status: 'todo',
        priority: 'medium',
        dueDate: new Date('2024-01-01'), // Date locale
      };

      const syncData = {
        title: 'Tâche',
        description: 'Description',
        status: 'todo',
        priority: 'medium',
        dueDate: new Date('2024-12-31'), // Date Jira
      };

      const result = buildSyncUpdateData('jira', existingTask, syncData);

      expect(result.dueDate).toEqual(new Date('2024-12-31')); // Toujours écrasé
    });

    it('devrait préserver priority même si title identique', () => {
      const existingTask = {
        title: 'Titre identique',
        description: 'Description locale',
        status: 'todo',
        priority: 'medium', // Modifié localement
        dueDate: null,
      };

      const syncData = {
        title: 'Titre identique', // Même titre
        description: 'Description Jira',
        status: 'done',
        priority: 'high', // Valeur Jira différente
        dueDate: new Date('2024-01-01'),
      };

      const result = buildSyncUpdateData('jira', existingTask, syncData);

      // Title identique → utilise syncData
      expect(result.title).toBe('Titre identique');
      // Priority différente → préservée même si title identique
      expect(result.priority).toBe('medium'); // Préservé car modifié localement
    });
  });

  describe('detectSyncChanges - Détection des changements et préservations', () => {
    it('devrait détecter une priorité préservée localement', () => {
      const existingTask = {
        title: 'Tâche test',
        description: 'Description locale',
        status: 'todo',
        priority: 'high', // Modifié localement
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const taskData = {
        title: 'Tâche test',
        description: 'Description locale',
        status: 'todo',
        priority: 'medium', // Valeur Jira différente
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const finalData = buildSyncUpdateData('jira', existingTask, taskData);

      const { realChanges, preservedFields } = detectSyncChanges(
        existingTask,
        taskData,
        finalData
      );

      expect(realChanges).toHaveLength(0);
      expect(preservedFields).toHaveLength(1);
      expect(preservedFields[0]).toBe(
        'Priorité: préservée localement (high) vs Jira (medium)'
      );
    });

    it('devrait détecter un titre préservé localement', () => {
      const existingTask = {
        title: 'Titre modifié localement',
        description: 'Description',
        status: 'todo',
        priority: 'medium',
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const taskData = {
        title: 'Titre original Jira',
        description: 'Description',
        status: 'todo',
        priority: 'medium',
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const finalData = buildSyncUpdateData('jira', existingTask, taskData);

      const { realChanges, preservedFields } = detectSyncChanges(
        existingTask,
        taskData,
        finalData
      );

      expect(realChanges).toHaveLength(0);
      expect(preservedFields).toHaveLength(1);
      expect(preservedFields[0]).toContain('Titre: préservé localement');
      expect(preservedFields[0]).toContain('vs Jira');
    });

    it('devrait détecter plusieurs champs préservés', () => {
      const existingTask = {
        title: 'Titre modifié',
        description: 'Description',
        status: 'todo',
        priority: 'high', // Modifié localement
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const taskData = {
        title: 'Titre original', // Différent
        description: 'Description',
        status: 'todo',
        priority: 'medium', // Différent
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const finalData = buildSyncUpdateData('jira', existingTask, taskData);

      const { realChanges, preservedFields } = detectSyncChanges(
        existingTask,
        taskData,
        finalData
      );

      expect(realChanges).toHaveLength(0);
      expect(preservedFields.length).toBeGreaterThanOrEqual(2);
      expect(preservedFields.some((f) => f.includes('Titre'))).toBe(true);
      expect(preservedFields.some((f) => f.includes('Priorité'))).toBe(true);
    });

    it('devrait détecter un changement réel de statut', () => {
      const existingTask = {
        title: 'Tâche',
        description: 'Description',
        status: 'todo',
        priority: 'medium',
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const taskData = {
        title: 'Tâche',
        description: 'Description',
        status: 'in_progress', // Changé dans Jira
        priority: 'medium',
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const finalData = buildSyncUpdateData('jira', existingTask, taskData);

      const { realChanges, preservedFields } = detectSyncChanges(
        existingTask,
        taskData,
        finalData
      );

      expect(realChanges.length).toBeGreaterThan(0);
      expect(realChanges.some((c) => c.includes('Statut'))).toBe(true);
      expect(preservedFields).toHaveLength(0);
    });

    it('devrait détecter changement réel + préservation simultanés', () => {
      const existingTask = {
        title: 'Titre modifié localement',
        description: 'Description locale',
        status: 'todo',
        priority: 'high', // Modifié localement
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const taskData = {
        title: 'Titre original', // Différent
        description: 'Description Jira', // Différent
        status: 'in_progress', // Changé dans Jira
        priority: 'medium', // Différent
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const finalData = buildSyncUpdateData('jira', existingTask, taskData);

      const { realChanges, preservedFields } = detectSyncChanges(
        existingTask,
        taskData,
        finalData
      );

      // Description et statut devraient être dans realChanges (écrasés)
      expect(realChanges.length).toBeGreaterThan(0);
      // Titre et priorité devraient être préservés
      expect(preservedFields.length).toBeGreaterThan(0);
      expect(preservedFields.some((f) => f.includes('Titre'))).toBe(true);
      expect(preservedFields.some((f) => f.includes('Priorité'))).toBe(true);
    });

    it('devrait détecter aucun changement quand tout est identique', () => {
      const existingTask = {
        title: 'Tâche',
        description: 'Description',
        status: 'todo',
        priority: 'medium',
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const taskData = {
        title: 'Tâche',
        description: 'Description',
        status: 'todo',
        priority: 'medium',
        dueDate: null,
        jiraProject: 'TEST',
        jiraType: 'Task',
        assignee: 'User',
      };

      const finalData = buildSyncUpdateData('jira', existingTask, taskData);

      const { realChanges, preservedFields } = detectSyncChanges(
        existingTask,
        taskData,
        finalData
      );

      expect(realChanges).toHaveLength(0);
      expect(preservedFields).toHaveLength(0);
    });

    it('devrait détecter un changement de projet Jira', () => {
      const existingTask = {
        title: 'Tâche',
        description: 'Description',
        status: 'todo',
        priority: 'medium',
        dueDate: null,
        jiraProject: 'OLD',
        jiraType: 'Task',
        assignee: 'User',
      };

      const taskData = {
        title: 'Tâche',
        description: 'Description',
        status: 'todo',
        priority: 'medium',
        dueDate: null,
        jiraProject: 'NEW', // Changé
        jiraType: 'Task',
        assignee: 'User',
      };

      const finalData = buildSyncUpdateData('jira', existingTask, taskData);

      const { realChanges, preservedFields } = detectSyncChanges(
        existingTask,
        taskData,
        finalData
      );

      expect(realChanges.length).toBeGreaterThan(0);
      expect(realChanges.some((c) => c.includes('Projet'))).toBe(true);
      expect(preservedFields).toHaveLength(0); // Pas de préservation pour un changement de projet
    });
  });
});
