/**
 * Marketplace Store
 * Zustand store for marketplace module state management
 */

import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import type {
  MarketplaceProductListItem,
  SignalPack,
  AdvisoryService,
  CourseProduct,
  ProductReview,
  UserSubscription,
  ConsultationBooking,
  MarketplaceFilters,
  ProductCategory,
} from '../types/marketplace.types';
import { marketplaceService } from '../services/marketplace.service';

// ============================================================================
// State Interface
// ============================================================================

interface MarketplaceState {
  // Products (all categories)
  products: MarketplaceProductListItem[];
  featuredProducts: MarketplaceProductListItem[];
  popularProducts: MarketplaceProductListItem[];
  relatedProducts: MarketplaceProductListItem[];
  totalProducts: number;
  currentPage: number;
  pageSize: number;
  loadingProducts: boolean;
  filters: MarketplaceFilters;

  // Current Product Detail
  currentSignalPack: SignalPack | null;
  currentAdvisory: AdvisoryService | null;
  currentCourseProduct: CourseProduct | null;
  loadingDetail: boolean;

  // Reviews
  reviews: ProductReview[];
  totalReviews: number;
  loadingReviews: boolean;
  submittingReview: boolean;

  // User subscriptions and bookings
  mySubscriptions: UserSubscription[];
  myBookings: ConsultationBooking[];
  loadingSubscriptions: boolean;
  loadingBookings: boolean;

  // Availability (for advisory)
  availableSlots: string[];
  availabilityTimezone: string;
  loadingAvailability: boolean;

  // General
  error: string | null;

  // Actions - Products
  fetchProducts: (filters?: MarketplaceFilters) => Promise<void>;
  fetchFeaturedProducts: () => Promise<void>;
  fetchPopularProducts: () => Promise<void>;
  fetchRelatedProducts: (productId: string) => Promise<void>;

  // Actions - Signal Packs
  fetchSignalPackById: (id: string) => Promise<void>;
  fetchSignalPackBySlug: (slug: string) => Promise<void>;
  subscribeToSignalPack: (packId: string, pricingId: string) => Promise<void>;

  // Actions - Advisory
  fetchAdvisoryById: (id: string) => Promise<void>;
  fetchAdvisoryBySlug: (slug: string) => Promise<void>;
  fetchAdvisorAvailability: (advisoryId: string, date: string) => Promise<void>;
  bookConsultation: (
    advisoryId: string,
    data: { serviceTypeId: string; scheduledAt: string; notes?: string }
  ) => Promise<void>;

  // Actions - Course Products
  fetchCourseProductById: (id: string) => Promise<void>;
  fetchCourseProductBySlug: (slug: string) => Promise<void>;

  // Actions - Reviews
  fetchReviews: (
    productId: string,
    productType: ProductCategory,
    params?: { page?: number; pageSize?: number; sortBy?: 'newest' | 'helpful' | 'rating' }
  ) => Promise<void>;
  createReview: (
    productId: string,
    productType: ProductCategory,
    data: { rating: number; title?: string; comment: string }
  ) => Promise<void>;
  markReviewHelpful: (reviewId: string) => Promise<void>;

  // Actions - Subscriptions
  fetchMySubscriptions: () => Promise<void>;
  cancelSubscription: (id: string) => Promise<void>;

  // Actions - Bookings
  fetchMyBookings: () => Promise<void>;
  cancelBooking: (id: string) => Promise<void>;

  // Utility
  setFilters: (filters: MarketplaceFilters) => void;
  clearError: () => void;
  resetCurrentProduct: () => void;
}

// ============================================================================
// Initial State
// ============================================================================

const initialState = {
  // Products
  products: [],
  featuredProducts: [],
  popularProducts: [],
  relatedProducts: [],
  totalProducts: 0,
  currentPage: 1,
  pageSize: 12,
  loadingProducts: false,
  filters: {},

  // Current Product
  currentSignalPack: null,
  currentAdvisory: null,
  currentCourseProduct: null,
  loadingDetail: false,

  // Reviews
  reviews: [],
  totalReviews: 0,
  loadingReviews: false,
  submittingReview: false,

  // User data
  mySubscriptions: [],
  myBookings: [],
  loadingSubscriptions: false,
  loadingBookings: false,

  // Availability
  availableSlots: [],
  availabilityTimezone: 'UTC',
  loadingAvailability: false,

  // General
  error: null,
};

// ============================================================================
// Store
// ============================================================================

export const useMarketplaceStore = create<MarketplaceState>()(
  devtools(
    (set, get) => ({
      ...initialState,

      // ========================================================================
      // Product Actions
      // ========================================================================

      fetchProducts: async (filters?: MarketplaceFilters) => {
        const state = get();
        const mergedFilters = { ...state.filters, ...filters };

        set({ loadingProducts: true, error: null, filters: mergedFilters });

        try {
          const result = await marketplaceService.getProducts(mergedFilters);
          set({
            products: result.data,
            totalProducts: result.total,
            currentPage: result.page,
            pageSize: result.pageSize,
            loadingProducts: false,
          });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to fetch products';
          set({ error: errorMessage, loadingProducts: false, products: [] });
          console.error('Error fetching products:', error);
        }
      },

      fetchFeaturedProducts: async () => {
        try {
          const products = await marketplaceService.getFeaturedProducts(6);
          set({ featuredProducts: products });
        } catch (error) {
          console.error('Error fetching featured products:', error);
        }
      },

      fetchPopularProducts: async () => {
        try {
          const products = await marketplaceService.getPopularProducts(6);
          set({ popularProducts: products });
        } catch (error) {
          console.error('Error fetching popular products:', error);
        }
      },

      fetchRelatedProducts: async (productId: string) => {
        try {
          const products = await marketplaceService.getRelatedProducts(productId, 4);
          set({ relatedProducts: products });
        } catch (error) {
          console.error('Error fetching related products:', error);
        }
      },

      // ========================================================================
      // Signal Pack Actions
      // ========================================================================

      fetchSignalPackById: async (id: string) => {
        set({ loadingDetail: true, error: null, currentSignalPack: null });

        try {
          const signalPack = await marketplaceService.getSignalPackById(id);
          set({ currentSignalPack: signalPack, loadingDetail: false });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to fetch signal pack';
          set({ error: errorMessage, loadingDetail: false });
          console.error('Error fetching signal pack:', error);
        }
      },

      fetchSignalPackBySlug: async (slug: string) => {
        set({ loadingDetail: true, error: null, currentSignalPack: null });

        try {
          const signalPack = await marketplaceService.getSignalPackBySlug(slug);
          set({ currentSignalPack: signalPack, loadingDetail: false });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to fetch signal pack';
          set({ error: errorMessage, loadingDetail: false });
          console.error('Error fetching signal pack:', error);
        }
      },

      subscribeToSignalPack: async (packId: string, pricingId: string) => {
        set({ error: null });

        try {
          const subscription = await marketplaceService.subscribeToSignalPack(packId, pricingId);
          // Add to subscriptions list
          const state = get();
          set({ mySubscriptions: [...state.mySubscriptions, subscription] });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to subscribe';
          set({ error: errorMessage });
          console.error('Error subscribing to signal pack:', error);
          throw error;
        }
      },

      // ========================================================================
      // Advisory Actions
      // ========================================================================

      fetchAdvisoryById: async (id: string) => {
        set({ loadingDetail: true, error: null, currentAdvisory: null });

        try {
          const advisory = await marketplaceService.getAdvisoryServiceById(id);
          set({ currentAdvisory: advisory, loadingDetail: false });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to fetch advisory';
          set({ error: errorMessage, loadingDetail: false });
          console.error('Error fetching advisory:', error);
        }
      },

      fetchAdvisoryBySlug: async (slug: string) => {
        set({ loadingDetail: true, error: null, currentAdvisory: null });

        try {
          const advisory = await marketplaceService.getAdvisoryServiceBySlug(slug);
          set({ currentAdvisory: advisory, loadingDetail: false });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to fetch advisory';
          set({ error: errorMessage, loadingDetail: false });
          console.error('Error fetching advisory:', error);
        }
      },

      fetchAdvisorAvailability: async (advisoryId: string, date: string) => {
        set({ loadingAvailability: true });

        try {
          const result = await marketplaceService.getAdvisorAvailability(advisoryId, date);
          set({
            availableSlots: result.slots,
            availabilityTimezone: result.timezone,
            loadingAvailability: false,
          });
        } catch (error) {
          console.error('Error fetching availability:', error);
          set({ loadingAvailability: false, availableSlots: [] });
        }
      },

      bookConsultation: async (advisoryId, data) => {
        set({ error: null });

        try {
          const booking = await marketplaceService.bookConsultation(advisoryId, data);
          const state = get();
          set({ myBookings: [...state.myBookings, booking] });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to book consultation';
          set({ error: errorMessage });
          console.error('Error booking consultation:', error);
          throw error;
        }
      },

      // ========================================================================
      // Course Product Actions
      // ========================================================================

      fetchCourseProductById: async (id: string) => {
        set({ loadingDetail: true, error: null, currentCourseProduct: null });

        try {
          const course = await marketplaceService.getCourseProductById(id);
          set({ currentCourseProduct: course, loadingDetail: false });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to fetch course';
          set({ error: errorMessage, loadingDetail: false });
          console.error('Error fetching course:', error);
        }
      },

      fetchCourseProductBySlug: async (slug: string) => {
        set({ loadingDetail: true, error: null, currentCourseProduct: null });

        try {
          const course = await marketplaceService.getCourseProductBySlug(slug);
          set({ currentCourseProduct: course, loadingDetail: false });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to fetch course';
          set({ error: errorMessage, loadingDetail: false });
          console.error('Error fetching course:', error);
        }
      },

      // ========================================================================
      // Review Actions
      // ========================================================================

      fetchReviews: async (productId, productType, params) => {
        set({ loadingReviews: true });

        try {
          const result = await marketplaceService.getProductReviews(productId, productType, params);
          set({
            reviews: result.data,
            totalReviews: result.total,
            loadingReviews: false,
          });
        } catch (error) {
          console.error('Error fetching reviews:', error);
          set({ loadingReviews: false, reviews: [] });
        }
      },

      createReview: async (productId, productType, data) => {
        set({ submittingReview: true, error: null });

        try {
          const review = await marketplaceService.createReview(productId, productType, data);
          const state = get();
          set({
            reviews: [review, ...state.reviews],
            totalReviews: state.totalReviews + 1,
            submittingReview: false,
          });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to create review';
          set({ error: errorMessage, submittingReview: false });
          console.error('Error creating review:', error);
          throw error;
        }
      },

      markReviewHelpful: async (reviewId: string) => {
        try {
          await marketplaceService.markReviewHelpful(reviewId);
          // Update local state
          const state = get();
          set({
            reviews: state.reviews.map((r) =>
              r.id === reviewId ? { ...r, helpful: r.helpful + 1 } : r
            ),
          });
        } catch (error) {
          console.error('Error marking review helpful:', error);
        }
      },

      // ========================================================================
      // Subscription Actions
      // ========================================================================

      fetchMySubscriptions: async () => {
        set({ loadingSubscriptions: true });

        try {
          const subscriptions = await marketplaceService.getMySubscriptions();
          set({ mySubscriptions: subscriptions, loadingSubscriptions: false });
        } catch (error) {
          console.error('Error fetching subscriptions:', error);
          set({ loadingSubscriptions: false, mySubscriptions: [] });
        }
      },

      cancelSubscription: async (id: string) => {
        set({ error: null });

        try {
          const updated = await marketplaceService.cancelSubscription(id);
          const state = get();
          set({
            mySubscriptions: state.mySubscriptions.map((s) => (s.id === id ? updated : s)),
          });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to cancel subscription';
          set({ error: errorMessage });
          console.error('Error cancelling subscription:', error);
          throw error;
        }
      },

      // ========================================================================
      // Booking Actions
      // ========================================================================

      fetchMyBookings: async () => {
        set({ loadingBookings: true });

        try {
          const bookings = await marketplaceService.getMyBookings();
          set({ myBookings: bookings, loadingBookings: false });
        } catch (error) {
          console.error('Error fetching bookings:', error);
          set({ loadingBookings: false, myBookings: [] });
        }
      },

      cancelBooking: async (id: string) => {
        set({ error: null });

        try {
          const updated = await marketplaceService.cancelBooking(id);
          const state = get();
          set({
            myBookings: state.myBookings.map((b) => (b.id === id ? updated : b)),
          });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to cancel booking';
          set({ error: errorMessage });
          console.error('Error cancelling booking:', error);
          throw error;
        }
      },

      // ========================================================================
      // Utility Actions
      // ========================================================================

      setFilters: (filters: MarketplaceFilters) => {
        set({ filters });
      },

      clearError: () => {
        set({ error: null });
      },

      resetCurrentProduct: () => {
        set({
          currentSignalPack: null,
          currentAdvisory: null,
          currentCourseProduct: null,
          loadingDetail: false,
          reviews: [],
          totalReviews: 0,
          relatedProducts: [],
        });
      },
    }),
    {
      name: 'marketplace-store',
    }
  )
);

// ============================================================================
// Selectors
// ============================================================================

export const useProducts = () => useMarketplaceStore((state) => state.products);
export const useFeaturedProducts = () => useMarketplaceStore((state) => state.featuredProducts);
export const usePopularProducts = () => useMarketplaceStore((state) => state.popularProducts);
export const useRelatedProducts = () => useMarketplaceStore((state) => state.relatedProducts);
export const useCurrentSignalPack = () => useMarketplaceStore((state) => state.currentSignalPack);
export const useCurrentAdvisory = () => useMarketplaceStore((state) => state.currentAdvisory);
export const useCurrentCourseProduct = () => useMarketplaceStore((state) => state.currentCourseProduct);
export const useProductReviews = () => useMarketplaceStore((state) => state.reviews);
export const useMySubscriptions = () => useMarketplaceStore((state) => state.mySubscriptions);
export const useMyBookings = () => useMarketplaceStore((state) => state.myBookings);
export const useMarketplaceFilters = () => useMarketplaceStore((state) => state.filters);
export const useMarketplaceError = () => useMarketplaceStore((state) => state.error);
export const useLoadingProducts = () => useMarketplaceStore((state) => state.loadingProducts);
export const useLoadingDetail = () => useMarketplaceStore((state) => state.loadingDetail);

export default useMarketplaceStore;
