// src/client/entities/contractor.ts
// Contractor entity - Pinia store for contractor management with Smart Merge

import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { contractorsRepository, type ContractorPendingEntryResponse } from '../shared/api/repositories/ContractorsRepository';
import type { ContractorEntry, ContractorCreateRequest, ContractorUpdateRequest } from '@shared/contracts/contractors';
import { calculateUnifiedList } from './contractor/model/unifiedList';
// IMPORTING FROM OUR NEW HELPER FILE
import { patchEntries, patchPendingEntries, patchEntry, removeEntry as removeEntryHelper } from './contractor/model/mergeHelpers';
import { EVENTS } from '@shared/contracts/events';
import { socketService } from '../shared/api/SocketService';

export const useContractorStore = defineStore('contractor', () => {
  // State
  const entries = ref<ContractorEntry[]>([]);
  const pendingEntries = ref<ContractorPendingEntryResponse[]>([]);
  const loading = ref(false);
  const error = ref<string | null>(null);
  const searchQuery = ref<string>('');
  const socketBound = ref(false);
  const socketUnsubscribers = ref<(() => void)[]>([]);

  // Computed
  const hasPendingEntries = computed(() => pendingEntries.value.length > 0);
  const items = computed(() => entries.value);

  /**
   * Unified List - Single Source of Truth for the UI
   */
  const unifiedList = computed(() => {
    return calculateUnifiedList(entries.value, pendingEntries.value);
  });

  /**
   * Fetch all approved contractor entries
   * REFACTOR: Direct assignment instead of smart merge to ensure stale data is removed
   */
  async function fetchAll() {
    loading.value = true;
    error.value = null;
    try {
      const data = await contractorsRepository.getAll();
      
      // 🛡️ ФИЛЬТР: Оставляем только реально одобренные записи
      // Это защищает от багов бэкенда, который может прислать черновики в общий список
      const cleanData = data.filter((item: any) => {
        if (typeof item.isApproved === 'boolean') {
          return item.isApproved === true;
        }
        return item.status === 'approved';
      });
      
      // 🛡️ Дополнительная защита: Если запись имеет статус 'approved' в поле status,
      // но isApproved не определен или false, устанавливаем его в true
      const dataWithApproved = cleanData.map((item: any) => ({
        ...item,
        isApproved: item.isApproved === true || item.status === 'approved'
      }));

      console.log(`[ContractorStore] fetchAll: Получено ${data.length}, Оставлено после фильтра ${cleanData.length}`);
      
      // ⚡️ HARD REPLACE: Полная замена массива.
      // Гарантирует, что удаленные/согласованные записи исчезнут из списка entries.
      entries.value = dataWithApproved;
      
    } catch (err: any) {
      error.value = err.message || 'Не удалось загрузить записи контрагентов';
      console.error('Error fetching contractor entries:', err);
    } finally {
      loading.value = false;
    }
  }

  /**
   * Fetch only pending entries
   * REFACTOR: Direct assignment instead of smart merge
   */
  async function fetchPending() {
    loading.value = true;
    error.value = null;
    try {
      const data = await contractorsRepository.getPending();
      
      // ⚡️ HARD REPLACE: Полная замена массива.
      // Если запись была согласована или отклонена, она исчезнет из этого списка моментально.
      pendingEntries.value = data;
      
    } catch (err: any) {
      error.value = err.message || 'Не удалось загрузить записи на согласовании';
      console.error('Error fetching pending entries:', err);
    } finally {
      loading.value = false;
    }
  }

  /**
   * Create new contractor entry
   */
  async function create(data: ContractorCreateRequest) {
    loading.value = true;
    error.value = null;
    try {
      const response = await contractorsRepository.create(data);
      smartMergeEntry(response);
    } catch (err: any) {
      error.value = err.message || 'Не удалось создать запись';
      throw err;
    } finally {
      loading.value = false;
    }
  }

  /**
   * Update existing contractor entry
   */
  async function update(id: string, data: ContractorUpdateRequest) {
    loading.value = true;
    error.value = null;
    try {
      const response = await contractorsRepository.update(id, data);
      smartMergeEntry(response);
    } catch (err: any) {
      error.value = err.message || 'Не удалось обновить запись';
      throw err;
    } finally {
      loading.value = false;
    }
  }

  /**
   * Delete contractor entry
   */
  async function deleteEntry(id: string) {
    loading.value = true;
    error.value = null;
    try {
      await contractorsRepository.archive(id);
      removeEntry(id);
      // Optional: fetchPending if a delete request was created instead of direct delete
      fetchPending();
    } catch (err: any) {
      error.value = err.message || 'Не удалось удалить запись';
      throw err;
    } finally {
      loading.value = false;
    }
  }

  /**
   * Approve single pending entry
   */
  async function approveEntry(id: string) {
    loading.value = true;
    error.value = null;
    try {
      await contractorsRepository.approveEntry(id);
      // Мгновенное обновление списков
      await Promise.all([fetchAll(), fetchPending()]);
    } catch (err: any) {
      error.value = err.message || 'Не удалось согласовать запись';
      throw err;
    } finally {
      loading.value = false;
    }
  }

  /**
   * Reject single pending entry
   */
  async function rejectEntry(id: string) {
    loading.value = true;
    error.value = null;
    try {
      await contractorsRepository.rejectEntry(id);
      // Мгновенное обновление списков
      await Promise.all([fetchAll(), fetchPending()]);
    } catch (err: any) {
      error.value = err.message || 'Не удалось отклонить запись';
      throw err;
    } finally {
      loading.value = false;
    }
  }

  // --- SMART MERGE HELPERS ---

  function smartMergeEntries(newEntries: ContractorEntry[]) {
    entries.value = patchEntries(entries.value, newEntries);
  }

  function smartMergePendingEntries(newEntries: ContractorPendingEntryResponse[]) {
    pendingEntries.value = patchPendingEntries(pendingEntries.value, newEntries);
  }

  function smartMergeEntry(entry: any) {
    const result = patchEntry(entries.value, pendingEntries.value, entry);
    entries.value = result.entries;
    pendingEntries.value = result.pendingEntries;
  }

  function removeEntry(id: string) {
    const result = removeEntryHelper(entries.value, pendingEntries.value, id);
    entries.value = result.entries;
    pendingEntries.value = result.pendingEntries;
  }

  // --- SOCKETS ---

  function handleExternalChange(event: any) {
    console.log('[ContractorStore] External change:', event);
    if (event?.action === 'delete' && event.id) {
      removeEntry(event.id);
    } else if (event?.action === 'fullRefresh') {
      fetchAll();
      fetchPending();
    } else if (event && !event.action) {
      // Create/Update event containing the entry
      smartMergeEntry(event);
    }
  }

  function bindSocketEvents() {
    if (socketBound.value) return;
    const unsubUpdated = socketService.subscribe(EVENTS.CONTRACTOR_UPDATED, handleExternalChange);
    const unsubCreated = socketService.subscribe(EVENTS.CONTRACTOR_CREATED, handleExternalChange);
    const unsubDeleted = socketService.subscribe(EVENTS.CONTRACTOR_DELETED, handleExternalChange);
    socketUnsubscribers.value = [unsubUpdated, unsubCreated, unsubDeleted];
    socketBound.value = true;
    console.log('[ContractorStore] Socket events bound');
  }

  function unbindSocketEvents() {
    if (!socketBound.value) return;
    socketUnsubscribers.value.forEach(unsub => unsub());
    socketUnsubscribers.value = [];
    socketBound.value = false;
  }
/**
   * Set search query for filtering
   */
  function setSearchQuery(query: string) {
    searchQuery.value = query;
  }
  return {
    entries,
    pendingEntries,
    loading,
    error,
    searchQuery,
    hasPendingEntries,
    items,
    unifiedList, // Main export used by Page
    fetchAll,
    fetchPending,
    create,
    update,
    deleteEntry,
    approveEntry,
    rejectEntry,
    getEntryById: (id: string) => entries.value.find(e => e.id === id),
    setSearchQuery,
    smartMergeEntry,
    removeEntry,
    bindSocketEvents,
    unbindSocketEvents,
  };
});
