import { defineStore } from "pinia";
import { ref, computed } from "vue";
import { useAuthStore } from "./auth";
import { useSyncStore } from "./sync";

// Types
export interface Transaction {
  _id?: string;
  amount: number;
  type: "income" | "expense";
  categoryId: string;
  description: string;
  date: string;
  createdAt?: string;
  updatedAt?: string;
  synced?: boolean;
}

export interface Category {
  _id?: string;
  name: string;
  icon?: string;
  color?: string;
}

// Store for transactions
export const useTransactionsStore = defineStore("transactions", () => {
  // State
  const transactions = ref<Transaction[]>([]);
  const loading = ref(false);
  const error = ref("");

  // API URL
  const apiBaseUrl = "http://localhost:3000/api";

  // Auth store for token
  const authStore = useAuthStore();

  // Getters
  const incomes = computed(() =>
    transactions.value.filter((t) => t.type === "income"),
  );

  const expenses = computed(() =>
    transactions.value.filter((t) => t.type === "expense"),
  );

  const totalIncome = computed(() =>
    incomes.value.reduce((sum, t) => sum + t.amount, 0),
  );

  const totalExpenses = computed(() =>
    expenses.value.reduce((sum, t) => sum + t.amount, 0),
  );

  const balance = computed(() => totalIncome.value - totalExpenses.value);

  // Load and save from local storage
  function loadFromLocalStorage() {
    const savedData = localStorage.getItem("transactions");
    if (savedData) {
      transactions.value = JSON.parse(savedData);
    }
  }

  function saveToLocalStorage() {
    localStorage.setItem("transactions", JSON.stringify(transactions.value));
  }

  // API Actions
  async function fetchTransactions() {
    if (!authStore.token) return;

    loading.value = true;
    error.value = "";

    try {
      const response = await fetch(`${apiBaseUrl}/transactions`, {
        headers: {
          Authorization: `Bearer ${authStore.token}`,
        },
      });

      if (!response.ok) {
        throw new Error("Failed to fetch transactions");
      }

      const data = await response.json();
      transactions.value = data.data;

      // Save to localStorage for offline access
      saveToLocalStorage();
    } catch (err: any) {
      error.value = err.message;
      // If API call fails, try to load from localStorage
      loadFromLocalStorage();
    } finally {
      loading.value = false;
    }
  }

  async function addTransaction(
    transaction: Omit<Transaction, "_id" | "createdAt" | "updatedAt">,
  ) {
    loading.value = true;
    error.value = "";

    // Get sync store for handling offline/online sync
    const syncStore = useSyncStore();

    // Create transaction object with temp ID
    const newTransaction = {
      ...transaction,
      _id: "temp_" + Date.now(),
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
      synced: false,
    };

    // Check if we're online and authenticated
    if (syncStore.isOnline && authStore.token) {
      try {
        console.log("Sending transaction to server:", transaction);
        const response = await fetch(`${apiBaseUrl}/transactions`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${authStore.token}`,
          },
          body: JSON.stringify(transaction),
        });

        const responseData = await response.json();

        if (!response.ok) {
          throw new Error(responseData.message || "Failed to save transaction");
        }

        // Add to local state with server ID
        const serverTransaction = {
          ...transaction,
          _id: responseData.transactionId,
          createdAt: newTransaction.createdAt,
          updatedAt: newTransaction.updatedAt,
          synced: true,
        };

        transactions.value.push(serverTransaction);
        saveToLocalStorage();

        return serverTransaction;
      } catch (err: any) {
        console.error("Transaction error:", err);
        error.value = err.message;

        // Add to local state as unsynced
        transactions.value.push(newTransaction);
        saveToLocalStorage();

        // Add to pending actions for later sync
        syncStore.addPendingAction("transaction", "create", newTransaction);
      }
    } else {
      // We're offline or not authenticated, add to local state
      transactions.value.push(newTransaction);
      saveToLocalStorage();

      // Add to pending actions for later sync
      syncStore.addPendingAction("transaction", "create", newTransaction);
    }

    loading.value = false;
    return newTransaction;
  }

  // Update an existing transaction
  async function updateTransaction(transaction: Transaction) {
    if (!transaction._id) {
      error.value = "Transaction ID is required for update";
      return false;
    }

    loading.value = true;
    error.value = "";

    // Get sync store
    const syncStore = useSyncStore();

    // Update in local state first
    const index = transactions.value.findIndex(
      (t) => t._id === transaction._id,
    );
    if (index !== -1) {
      transactions.value[index] = {
        ...transaction,
        updatedAt: new Date().toISOString(),
        synced: false,
      };
      saveToLocalStorage();
    } else {
      error.value = "Transaction not found";
      loading.value = false;
      return false;
    }

    // Try to sync with server if online
    if (syncStore.isOnline && authStore.token) {
      try {
        const response = await fetch(
          `${apiBaseUrl}/transactions/${transaction._id}`,
          {
            method: "PUT",
            headers: {
              "Content-Type": "application/json",
              Authorization: `Bearer ${authStore.token}`,
            },
            body: JSON.stringify(transaction),
          },
        );

        if (!response.ok) {
          throw new Error("Failed to update transaction");
        }

        // Mark as synced
        transactions.value[index].synced = true;
        saveToLocalStorage();
      } catch (err: any) {
        error.value = err.message;
        // Add to pending actions for later sync
        syncStore.addPendingAction("transaction", "update", transaction);
      }
    } else {
      // We're offline, add to pending actions
      syncStore.addPendingAction("transaction", "update", transaction);
    }

    loading.value = false;
    return true;
  }

  // Delete a transaction
  async function deleteTransaction(id: string) {
    loading.value = true;
    error.value = "";

    // Get sync store
    const syncStore = useSyncStore();

    // Find the transaction to delete
    const transaction = transactions.value.find((t) => t._id === id);
    if (!transaction) {
      error.value = "Transaction not found";
      loading.value = false;
      return false;
    }

    // Remove from local state first
    transactions.value = transactions.value.filter((t) => t._id !== id);
    saveToLocalStorage();

    // Try to sync with server if online
    if (syncStore.isOnline && authStore.token) {
      try {
        const response = await fetch(`${apiBaseUrl}/transactions/${id}`, {
          method: "DELETE",
          headers: {
            Authorization: `Bearer ${authStore.token}`,
          },
        });

        if (!response.ok) {
          throw new Error("Failed to delete transaction");
        }
      } catch (err: any) {
        error.value = err.message;
        // Add to pending actions for later sync
        syncStore.addPendingAction("transaction", "delete", { _id: id });
      }
    } else {
      // We're offline, add to pending actions
      syncStore.addPendingAction("transaction", "delete", { _id: id });
    }

    loading.value = false;
    return true;
  }

  // Initialize
  loadFromLocalStorage();

  return {
    // State
    transactions,
    loading,
    error,

    // Getters
    incomes,
    expenses,
    totalIncome,
    totalExpenses,
    balance,

    // Actions
    fetchTransactions,
    addTransaction,
    updateTransaction,
    deleteTransaction,
    loadFromLocalStorage,
    saveToLocalStorage,
  };
});
