// src/client/entities/paymaster.ts
// Paymaster entity - Pinia store and types for cash register management

import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { paymasterRepository } from '../shared/api/repositories';
import { useUserStore } from './user';
import { usePermissionsStore } from './permissions';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import {
  type PaymasterRow,
  type CreatePaymasterRow,
  type UpdatePaymasterRow,
  type PaymasterTotals,
  type PaymasterSuggestions,
  type DateBoundaries,
  type PaymasterPeriodReport,
  PAYMASTER_TYPES,
} from '@shared/contracts/paymaster';
import { AppPermission } from '@shared/contracts/permissions';
import { getOperationalDay } from '@shared/utils/formatters';

// Расширяем dayjs плагинами
dayjs.extend(utc);
dayjs.extend(timezone);

// Хелпер для вычисления операционного дня
const getInitialOpDay = () => {
  const now = dayjs().tz('Europe/Moscow');
  return now.hour() < 9 ? now.subtract(1, 'day').format('YYYY-MM-DD') : now.format('YYYY-MM-DD');
};

// Re-export types for backward compatibility
export type {
  PaymasterRow,
  CreatePaymasterRow,
  UpdatePaymasterRow,
  PaymasterTotals,
  PaymasterPeriodReport,
};

export const usePaymasterStore = defineStore('paymaster', () => {
  // State
  const rows = ref<PaymasterRow[]>([]);
  const totals = ref<PaymasterTotals>({
    cash: 0,
    card: 0,
    advance: 0,
    expense: 0,
    other: 0,
  });
  const loading = ref(false);
  const error = ref<string | null>(null);
  const selectedDate = ref<string>(getInitialOpDay());
  const allTimeSuggestions = ref<PaymasterSuggestions>({
    rooms: [],
    contractors: [],
    types: [],
  });
  const dateBoundaries = ref<DateBoundaries>({
    minDate: getInitialOpDay(),
    maxDate: getInitialOpDay(),
  });

  // Computed properties
  const cashIncome = computed(() => Number(totals.value.cash));
  const cardIncome = computed(() => Number(totals.value.card));
  const advanceTotal = computed(() => Number(totals.value.advance));
  const expenseTotal = computed(() => Number(totals.value.expense));
  const otherTotal = computed(() => Number(totals.value.other));

  // Вычисляемые свойства для совместимости с существующим кодом
  const totalIncome = computed(() => cashIncome.value + cardIncome.value);
  const totalExpense = computed(() => expenseTotal.value + advanceTotal.value);
  const netTotal = computed(() => cashIncome.value - expenseTotal.value - advanceTotal.value);

  // Проверяем, является ли выбранная дата текущим операционным днем
  const currentOperationalDay = computed(() => {
    const now = dayjs().tz('Europe/Moscow');
    const hour = now.hour();
    
    // Если до 10:00 утра, операционный день - вчера
    if (hour < 9) {
      return now.subtract(1, 'day').format('YYYY-MM-DD');
    }
    
    // Иначе - сегодня
    return now.format('YYYY-MM-DD');
  });

  const isHistory = computed(() => selectedDate.value < currentOperationalDay.value);
  
  const canEdit = computed(() => {
    const userStore = useUserStore();
    const permissionsStore = usePermissionsStore();

    const canAnyDate = permissionsStore.hasPermission(AppPermission.PAYMASTER_ANY_DATE);
    if (canAnyDate) {
      return true;
    }

    const canYesterdayToo = permissionsStore.hasPermission(AppPermission.PAYMASTER_YESTERDAY_TOO);
    if (canYesterdayToo) {
      const yesterdayOpDay = dayjs(currentOperationalDay.value).subtract(1, 'day').format('YYYY-MM-DD');
      return selectedDate.value >= yesterdayOpDay && selectedDate.value <= currentOperationalDay.value;
    }

    const canTodayOnly = permissionsStore.hasPermission(AppPermission.PAYMASTER_TODAY_ONLY);
    if (canTodayOnly) {
      return selectedDate.value === currentOperationalDay.value;
    }

    return false;
  });

  const canView = computed(() => {
    const userStore = useUserStore();
    const permissionsStore = usePermissionsStore();

    if (userStore.isGod) return true;

    return permissionsStore.hasPermission(AppPermission.PAYMASTER_READ_ONLY)
      || permissionsStore.hasPermission(AppPermission.PAYMASTER_TODAY_ONLY)
      || permissionsStore.hasPermission(AppPermission.PAYMASTER_YESTERDAY_TOO)
      || permissionsStore.hasPermission(AppPermission.PAYMASTER_ANY_DATE);
  });

  // Actions
  async function fetchRows(date?: string) {
    loading.value = true;
    error.value = null;
    
    try {
      const targetDate = date || selectedDate.value;
      const fetchedRows = date 
        ? await paymasterRepository.fetchRowsByDate(targetDate)
        : await paymasterRepository.fetchRows();
      
      // Smart Merge: обновляем только если данные действительно изменились
      if (JSON.stringify(rows.value) !== JSON.stringify(fetchedRows)) {
        rows.value = fetchedRows;
      }
      
      if (date) {
        selectedDate.value = date;
      }
      
      // Загружаем итоги для выбранной даты
      await fetchTotals(date);
    } catch (err: any) {
      error.value = err.message || 'ERROR_FETCH_ROWS';
      console.error('Error fetching paymaster rows:', err);
    } finally {
      loading.value = false;
    }
  }

  async function fetchTotals(date?: string) {
    try {
      const targetDate = date || selectedDate.value;
      // Всегда вызываем fetchTotalsByDate(targetDate), чтобы не было дефолта бэкенда
      const fetchedTotals = await paymasterRepository.fetchTotalsByDate(targetDate);
      
      totals.value = fetchedTotals;
    } catch (err: any) {
      console.error('Error fetching paymaster totals:', err);
    }
  }

  async function createRow(data: CreatePaymasterRow) {
    loading.value = true;
    error.value = null;

    try {
      // Автоматически определяем операционный день, если не передан явно
      const operationalDay = data.operationalDay || getOperationalDay();

      const row = await paymasterRepository.createRow({
        ...data,
        operationalDay,
      });

      // Smart Merge: добавляем новую запись без перезагрузки всего массива
      rows.value.push(row);

      // Обновляем итоги для выбранной даты (гарантируем обновление для текущей даты)
      await fetchTotals(selectedDate.value);

      return row;
    } catch (err: any) {
      error.value = err.message || 'ERROR_CREATE_ROW';
      console.error('Error creating paymaster row:', err);
      throw err;
    } finally {
      loading.value = false;
    }
  }

  async function updateRow(data: UpdatePaymasterRow & { id: string }) {
    loading.value = true;
    error.value = null;
    
    try {
      const row = await paymasterRepository.updateRow(data);
      
      // Smart Merge: обновляем только измененную строку
      const index = rows.value.findIndex(r => r.id === data.id);
      if (index !== -1) {
        rows.value[index] = row;
      }
      
      // Обновляем итоги для выбранной даты (гарантируем обновление для текущей даты)
      await fetchTotals(selectedDate.value);
      
      return row;
    } catch (err: any) {
      error.value = err.message || 'ERROR_UPDATE_ROW';
      console.error('Error updating paymaster row:', err);
      throw err;
    } finally {
      loading.value = false;
    }
  }

  async function deleteRow(id: string) {
    loading.value = true;
    error.value = null;
    
    try {
      await paymasterRepository.deleteRow(id);
      
      // Smart Merge: удаляем запись без перезагрузки всего массива
      rows.value = rows.value.filter(r => r.id !== id);
      
      // Обновляем итоги для выбранной даты (гарантируем обновление для текущей даты)
      await fetchTotals(selectedDate.value);
    } catch (err: any) {
      error.value = err.message || 'ERROR_DELETE_ROW';
      console.error('Error deleting paymaster row:', err);
      throw err;
    } finally {
      loading.value = false;
    }
  }

  function setSelectedDate(date: string) {
    selectedDate.value = date;
  }

  function clearError() {
    error.value = null;
  }

  async function fetchSuggestions() {
    try {
      const suggestions = await paymasterRepository.fetchSuggestions();
      allTimeSuggestions.value = suggestions;
    } catch (err: any) {
      console.error('Error fetching paymaster suggestions:', err);
    }
  }

  async function fetchDateBoundaries() {
    try {
      const boundaries = await paymasterRepository.fetchDateBoundaries();
      dateBoundaries.value = boundaries;
    } catch (err: any) {
      console.error('Error fetching date boundaries:', err);
    }
  }

  async function fetchPeriodReport(startDate: string, endDate: string): Promise<PaymasterPeriodReport> {
    loading.value = true;
    error.value = null;

    try {
      const report = await paymasterRepository.fetchPeriodReport(startDate, endDate);
      return report;
    } catch (err: any) {
      error.value = err.message || 'ERROR_FETCH_PERIOD_REPORT';
      console.error('Error fetching period report:', err);
      throw err;
    } finally {
      loading.value = false;
    }
  }

  // Геттеры для уникальных значений автокомплита
  const uniqueRoomNumbers = computed(() => {
    const currentRooms = rows.value
      .map(r => r.roomNumber)
      .filter((room): room is string => room !== null && room.trim() !== '');
    const allRooms = [...new Set([...currentRooms, ...allTimeSuggestions.value.rooms])];
    return allRooms;
  });

  const uniqueContractors = computed(() => {
    const currentContractors = rows.value
      .map(r => r.contractor)
      .filter((contractor): contractor is string => contractor !== null && contractor.trim() !== '');
    const allContractors = [...new Set([...currentContractors, ...allTimeSuggestions.value.contractors])];
    return allContractors;
  });

  const uniqueTypes = computed(() => {
    const currentTypes = rows.value.map(r => r.type);
    const allTypes = [...new Set([...currentTypes, ...allTimeSuggestions.value.types])];
    return allTypes;
  });

  return {
    // State
    rows,
    totals,
    loading,
    error,
    selectedDate,
    allTimeSuggestions,
    dateBoundaries,

    // Computed
    cashIncome,
    cardIncome,
    advanceTotal,
    expenseTotal,
    otherTotal,
    totalIncome,
    totalExpense,
    netTotal,
    currentOperationalDay,
    isHistory,
    canEdit,
    canView,
    uniqueRoomNumbers,
    uniqueContractors,
    uniqueTypes,

    // Actions
    fetchRows,
    fetchTotals,
    fetchSuggestions,
    fetchDateBoundaries,
    fetchPeriodReport,
    createRow,
    updateRow,
    deleteRow,
    setSelectedDate,
    clearError,
  };
});
