// src/client/entities/blacklist/model/mergeHelpers.ts
// Smart merge helper functions for blacklist entries

import type { BlacklistEntry } from '@shared/contracts/blacklist';
import type { BlacklistPendingEntryResponse } from '../../../shared/api/repositories/BlacklistRepository';

/**
 * Smart Merge: update entries array without resetting
 * Preserves UI state (scroll position, filters, etc.)
 */
export function patchEntries(
  currentEntries: BlacklistEntry[],
  newEntries: BlacklistEntry[]
): BlacklistEntry[] {
  const entryMap = new Map(currentEntries.map((e: BlacklistEntry) => [e.id, e]));
  
  // Update or add new entries
  newEntries.forEach((entry: BlacklistEntry) => {
    entryMap.set(entry.id, entry);
  });
  
  // Remove entries that are no longer in new list
  const newIds = new Set(newEntries.map((e: BlacklistEntry) => e.id));
  for (const [id] of entryMap) {
    if (!newIds.has(id)) {
      entryMap.delete(id);
    }
  }
  
  return Array.from(entryMap.values());
}

/**
 * Smart Merge: update pending entries array
 */
export function patchPendingEntries(
  currentEntries: BlacklistPendingEntryResponse[],
  newEntries: BlacklistPendingEntryResponse[]
): BlacklistPendingEntryResponse[] {
  const entryMap = new Map(currentEntries.map((e: BlacklistPendingEntryResponse) => [e.id, e]));
  
  newEntries.forEach((entry: BlacklistPendingEntryResponse) => {
    entryMap.set(entry.id, entry);
  });
  
  const newIds = new Set(newEntries.map((e: BlacklistPendingEntryResponse) => e.id));
  for (const [id] of entryMap) {
    if (!newIds.has(id)) {
      entryMap.delete(id);
    }
  }
  
  return Array.from(entryMap.values());
}

/**
 * Smart Merge: update single entry
 * Correctly handles pending entries (with targetId or status) vs approved entries
 */
export function patchEntry(
  entries: BlacklistEntry[],
  pendingEntries: BlacklistPendingEntryResponse[],
  entry: BlacklistEntry & { targetId?: string | null; status?: string; creatorName?: string | null }
): { entries: BlacklistEntry[]; pendingEntries: BlacklistPendingEntryResponse[] } {
  // 1. Определение типа записи: если есть targetId или status (pending/to_delete) — это pending запись
  const hasTargetId = 'targetId' in entry && entry.targetId !== undefined;
  const hasStatus = 'status' in entry && entry.status !== undefined;
  const isPendingEntry = hasTargetId || (hasStatus && (entry.status === 'pending' || entry.status === 'to_delete'));

  // 2. Логика Pending: обрабатываем записи для pendingEntries
  if (isPendingEntry) {
    const pendingIndex = pendingEntries.findIndex((e: BlacklistPendingEntryResponse) => e.id === entry.id);
    let newPendingEntries = [...pendingEntries];
    
    if (pendingIndex !== -1) {
      // Обновляем существующую pending запись (patch)
      newPendingEntries[pendingIndex] = {
        ...newPendingEntries[pendingIndex],
        name: entry.name,
        phone: entry.phone,
        bookingEngineCheck: entry.bookingEngineCheck,
        comment: entry.comment,
        status: (entry.status as 'pending' | 'to_delete') || 'pending',
        targetId: entry.targetId || null,
        updatedAt: entry.updatedAt,
        creatorName: entry.creatorName || newPendingEntries[pendingIndex].creatorName,
      };
    } else {
      // Добавляем новую pending запись
      newPendingEntries.push({
        id: entry.id,
        name: entry.name,
        phone: entry.phone,
        bookingEngineCheck: entry.bookingEngineCheck,
        comment: entry.comment,
        status: (entry.status as 'pending' | 'to_delete') || 'pending',
        targetId: entry.targetId || null,
        createdBy: entry.createdBy,
        creatorName: entry.creatorName || null,
        reviewedBy: null,
        reviewedAt: null,
        rejectionReason: null,
        createdAt: entry.createdAt,
        updatedAt: entry.updatedAt,
      });
    }
    
    // Сортируем pendingEntries по createdAt
    newPendingEntries.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
    return { entries, pendingEntries: newPendingEntries };
  }

  // 3. Логика Main (isApproved): обрабатываем одобренные записи
  if (entry.isApproved) {
    // Обновляем или добавляем в основной массив entries
    const mainIndex = entries.findIndex((e: BlacklistEntry) => e.id === entry.id);
    let newEntries = [...entries];
    
    if (mainIndex !== -1) {
      // Обновляем существующую запись (patch)
      newEntries[mainIndex] = entry;
    } else {
      // Добавляем новую запись
      newEntries.push(entry);
    }
    
    // ОБЯЗАТЕЛЬНО удаляем любую запись из pendingEntries, у которой id или targetId совпадает с entry.id
    const newPendingEntries = pendingEntries.filter((e: BlacklistPendingEntryResponse) =>
      e.id !== entry.id && e.targetId !== entry.id
    );
    
    // Сортируем entries по createdAt
    newEntries.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
    return { entries: newEntries, pendingEntries: newPendingEntries };
  }

  return { entries, pendingEntries };
}

/**
 * Cleanup pending entries after approval
 * Removes pending entries from pendingEntries array
 */
export function cleanupPendingAfterApproval(
  pendingEntries: BlacklistPendingEntryResponse[],
  approvedId: string
): BlacklistPendingEntryResponse[] {
  return pendingEntries.filter((e: BlacklistPendingEntryResponse) =>
    e.id !== approvedId && e.targetId !== approvedId
  );
}

/**
 * Remove entry from both arrays
 */
export function removeEntry(
  entries: BlacklistEntry[],
  pendingEntries: BlacklistPendingEntryResponse[],
  id: string
): { entries: BlacklistEntry[]; pendingEntries: BlacklistPendingEntryResponse[] } {
  // Remove from main entries array
  const newEntries = entries.filter((e: BlacklistEntry) => e.id !== id);
  
  // Remove from pendingEntries array (by id OR targetId)
  const newPendingEntries = pendingEntries.filter((e: BlacklistPendingEntryResponse) =>
    e.id !== id && e.targetId !== id
  );
  
  return { entries: newEntries, pendingEntries: newPendingEntries };
}
