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

// Types
export interface Category {
  _id?: string;
  name: string;
  icon?: string;
  color?: string;
  synced?: boolean;
}

// Store for categories
export const useCategoriesStore = defineStore("categories", () => {
  // State
  const categories = ref<Category[]>([]);
  const loading = ref(false);
  const error = ref("");
  const lastFetchTime = ref<number>(0);
  const cacheTimeout = 5 * 60 * 1000; // 5 minutes cache timeout

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

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

  // Load and save from local storage
  function loadFromLocalStorage() {
    const savedData = localStorage.getItem("categories");
    const savedTimestamp = localStorage.getItem("categories_timestamp");
    if (savedData && savedTimestamp) {
      categories.value = JSON.parse(savedData);
      lastFetchTime.value = parseInt(savedTimestamp);
    }
  }

  function saveToLocalStorage() {
    localStorage.setItem("categories", JSON.stringify(categories.value));
    localStorage.setItem("categories_timestamp", lastFetchTime.value.toString());
  }

  // Check if cache is valid
  function isCacheValid() {
    const now = Date.now();
    return categories.value.length > 0 && (now - lastFetchTime.value) < cacheTimeout;
  }

  // Default categories if none exist (for offline users only)
  function initializeDefaultCategories() {
    if (categories.value.length === 0 && !authStore.token) {
      categories.value = [
        { _id: "default-food", name: "Food", icon: "🍔", color: "#FF5733" },
        {
          _id: "default-transport",
          name: "Transport",
          icon: "🚗",
          color: "#33A1FF",
        },
        {
          _id: "default-housing",
          name: "Housing",
          icon: "🏠",
          color: "#33FF57",
        },
        {
          _id: "default-entertainment",
          name: "Entertainment",
          icon: "🎬",
          color: "#D733FF",
        },
        { _id: "default-salary", name: "Salary", icon: "💰", color: "#33FFD7" },
        { _id: "default-other", name: "Other", icon: "📦", color: "#FFD733" },
      ];
      saveToLocalStorage();
    }
  }

  // API Actions
  async function fetchCategories(forceRefresh = false) {
    // Load from localStorage first
    if (!forceRefresh) {
      loadFromLocalStorage();
      
      // Check if cache is valid
      if (isCacheValid()) {
        return;
      }
    }

    if (!authStore.token) {
      initializeDefaultCategories();
      return;
    }

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

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

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

      const data = await response.json();

      // Always use what the server returns for authenticated users
      if (data.data) {
        // Clear existing categories to avoid mixing with defaults
        categories.value = [];
        
        // Use server categories even if empty array
        categories.value = data.data;
        lastFetchTime.value = Date.now();
      }

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

      // If still no categories, initialize defaults
      if (categories.value.length === 0) {
        initializeDefaultCategories();
      }
    } finally {
      loading.value = false;
    }
  }

  async function addCategory(category: Omit<Category, "_id">) {
    loading.value = true;
    error.value = "";

    // Client-side validation
    if (!category.name?.trim()) {
      error.value = "Category name cannot be empty";
      loading.value = false;
      return null;
    }

    // Check for duplicates
    const isDuplicate = categories.value.some(
      c => c.name.toLowerCase() === category.name.toLowerCase()
    );
    if (isDuplicate) {
      error.value = "A category with this name already exists";
      loading.value = false;
      return null;
    }

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

    // Prepare the category with defaults if needed
    const preparedCategory = {
      ...category,
      icon: category.icon || "📦",
      color: category.color || "#3b82f6",
    };

    // Add to local state first for immediate UI update
    const newCategory = {
      ...preparedCategory,
      _id: "temp_" + Date.now(),
      synced: false,
    };

    categories.value.push(newCategory);
    saveToLocalStorage();

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

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

        // Update with server response
        const data = await response.json();
        const index = categories.value.findIndex(
          (c) => c._id === newCategory._id,
        );
        if (index !== -1) {
          categories.value[index] = {
            ...category,
            _id: data.categoryId,
            synced: true,
          };
          saveToLocalStorage();
        }
      } catch (err: any) {
        error.value = err.message;
        // Add to pending actions for later sync
        syncStore.addPendingAction("category", "create", newCategory);
      }
    } else {
      // We're offline or not authenticated, add to pending actions
      syncStore.addPendingAction("category", "create", newCategory);
    }

    loading.value = false;
    return newCategory;
  }

  // Admin functions
  async function fetchAllCategories() {
    if (!authStore.token || authStore.user?.role !== "admin") {
      error.value = "Admin access required";
      return;
    }

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

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

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

      const data = await response.json();
      return data.data;
    } catch (err: any) {
      error.value = err.message;
      throw err;
    } finally {
      loading.value = false;
    }
  }

  async function createGlobalCategory(category: Omit<Category, "_id">) {
    if (!authStore.token || authStore.user?.role !== "admin") {
      error.value = "Admin access required";
      return;
    }

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

    try {
      const response = await fetch(`${apiBaseUrl}/admin/categories`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${authStore.token}`,
        },
        body: JSON.stringify(category),
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(
          errorData.message || "Failed to create global category",
        );
      }

      const data = await response.json();
      return data;
    } catch (err: any) {
      error.value = err.message;
      throw err;
    } finally {
      loading.value = false;
    }
  }

  async function updateCategory(
    categoryId: string,
    updates: Partial<Category>,
  ) {
    if (!authStore.token || authStore.user?.role !== "admin") {
      error.value = "Admin access required";
      return;
    }

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

    try {
      const response = await fetch(
        `${apiBaseUrl}/admin/categories/${categoryId}`,
        {
          method: "PUT",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${authStore.token}`,
          },
          body: JSON.stringify(updates),
        },
      );

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.message || "Failed to update category");
      }

      const data = await response.json();
      return data;
    } catch (err: any) {
      error.value = err.message;
      throw err;
    } finally {
      loading.value = false;
    }
  }

  async function deleteCategory(categoryId: string) {
    if (!authStore.token || authStore.user?.role !== "admin") {
      error.value = "Admin access required";
      return;
    }

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

    try {
      const response = await fetch(
        `${apiBaseUrl}/admin/categories/${categoryId}`,
        {
          method: "DELETE",
          headers: {
            Authorization: `Bearer ${authStore.token}`,
          },
        },
      );

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.message || "Failed to delete category");
      }

      const data = await response.json();
      return data;
    } catch (err: any) {
      error.value = err.message;
      throw err;
    } finally {
      loading.value = false;
    }
  }

  // Initialize store
  function initializeStore() {
    // When user is authenticated, always get data from server
    if (authStore.token) {
      // First check if we have a valid cache
      loadFromLocalStorage();
      
      // If cache is invalid or forced refresh, fetch from server
      if (!isCacheValid()) {
        fetchCategories();
      }
    } else {
      // For non-authenticated users, load from local storage or use defaults
      loadFromLocalStorage();
      
      // If still no categories after load, use defaults for offline experience
      if (categories.value.length === 0) {
        initializeDefaultCategories();
      }
    }
  }

  // Initialize
  initializeStore();

  // Method to force refresh categories
  async function refreshCategories() {
    return fetchCategories(true);
  }

  // Method to clear cache
  function clearCache() {
    categories.value = [];
    lastFetchTime.value = 0;
    localStorage.removeItem("categories");
    localStorage.removeItem("categories_timestamp");
  }

  return {
    // State
    categories,
    loading,
    error,

    // Actions
    fetchCategories,
    refreshCategories,
    addCategory,
    clearCache,

    // Admin actions
    fetchAllCategories,
    createGlobalCategory,
    updateCategory,
    deleteCategory,
  };
});
