"use client";

import { clientFetch } from '@/lib/api/api-client';
import { formatGBP } from '@/lib/utils/format';

// Analytics Types
export interface AnalyticsOverview {
  orders: {
    total: number;
    completed: number;
    pending: number;
    completionRate: string;
  };
  revenue: {
    total: number;
    monthly: number;
    weekly: number;
    averageOrderValue: number;
  };
  products: {
    total: number;
  };
  customers: {
    unique: number;
  };
  userType?: "vendor" | "staff";
}

export interface RevenueData {
  _id: {
    year: number;
    month: number;
    day: number;
  };
  revenue: number;
  orders: number;
}

export interface ProductPerformance {
  productId: string;
  name: string;
  image: string;
  unitType: string;
  currentStock: number;
  stockStatus: string;
  totalSold: number;
  totalRevenue: number;
  orderCount: number;
  averagePrice: number;
}

export interface CustomerInsights {
  totalCustomers: number;
  segments: {
    new: number;
    returning: number;
    loyal: number;
    vip: number;
  };
  topCustomers: Array<{
    _id: string;
    orderCount: number;
    totalSpent: number;
    averageOrderValue: number;
    firstOrder: string;
    lastOrder: string;
    displayName?: string;
    username?: string;
  }>;
  averageOrdersPerCustomer: string;
  pagination?: {
    currentPage: number;
    totalPages: number;
    totalCustomers: number;
    limit: number;
    hasNextPage: boolean;
    hasPrevPage: boolean;
    startIndex: number;
    endIndex: number;
  };
}

export interface OrderAnalytics {
  statusDistribution: Array<{
    _id: string;
    count: number;
  }>;
}

export interface GrowthAnalytics {
  launchDate: string;
  generatedAt: string;
  daily: Array<{
    date: string;
    orders: number;
    revenue: number;
    customers: number;
    avgOrderValue: number;
  }>;
  monthly: Array<{
    month: string;
    orders: number;
    revenue: number;
    customers: number;
    avgOrderValue: number;
    newCustomers: number;
  }>;
  customers: {
    total: number;
    segments: {
      new: number;
      returning: number;
      loyal: number;
      vip: number;
    };
    segmentDetails: {
      [key: string]: {
        count: number;
        totalRevenue: number;
        avgOrderCount: number;
        avgSpent: number;
      };
    };
    segmentPercentages: {
      new: number;
      returning: number;
      loyal: number;
      vip: number;
    };
  };
  cumulative: {
    orders: number;
    revenue: number;
    customers: number;
    products: number;
    avgOrderValue: number;
  };
}

// Analytics Service Functions

/**
 * Get analytics overview data
 * @param storeId Optional storeId for staff users
 */
export const getAnalyticsOverview = async (
  storeId?: string,
): Promise<AnalyticsOverview> => {
  const url = storeId
    ? `/analytics/overview?storeId=${storeId}`
    : "/analytics/overview";
  return clientFetch<AnalyticsOverview>(url);
};

/**
 * Get revenue trends data
 * @param period Time period in days (7, 30, 90)
 * @param storeId Optional storeId for staff users
 */
export const getRevenueTrends = async (
  period: string = "30",
  storeId?: string,
): Promise<RevenueData[]> => {
  const params = new URLSearchParams({ period });
  if (storeId) params.append("storeId", storeId);

  const url = `/analytics/revenue-trends?${params.toString()}`;
  return clientFetch<RevenueData[]>(url);
};

/**
 * Get product performance data
 * @param storeId Optional storeId for staff users
 */
export const getProductPerformance = async (
  storeId?: string,
): Promise<ProductPerformance[]> => {
  const url = storeId
    ? `/analytics/product-performance?storeId=${storeId}`
    : "/analytics/product-performance";
  return clientFetch<ProductPerformance[]>(url);
};

/**
 * Get customer insights data
 * @param storeId Optional storeId for staff users
 * @param page Page number (default: 1)
 * @param limit Number of customers per page (default: 10)
 */
export const getCustomerInsights = async (
  storeId?: string,
  page: number = 1,
  limit: number = 10,
  sortBy: string = "spent",
): Promise<CustomerInsights> => {
  const params = new URLSearchParams({
    page: page.toString(),
    limit: limit.toString(),
    sort: sortBy,
  });
  if (storeId) params.append("storeId", storeId);

  const url = `/analytics/customer-insights?${params.toString()}`;
  return clientFetch<CustomerInsights>(url);
};

/**
 * Get order analytics data
 * @param period Time period in days (7, 30, 90)
 * @param storeId Optional storeId for staff users
 */
export const getOrderAnalytics = async (
  period: string = "30",
  storeId?: string,
): Promise<OrderAnalytics> => {
  const params = new URLSearchParams({ period });
  if (storeId) params.append("storeId", storeId);

  const url = `/analytics/order-analytics?${params.toString()}`;
  return clientFetch<OrderAnalytics>(url);
};

/**
 * Get growth analytics data (since first order)
 * @param storeId Optional storeId for staff users
 */
export const getGrowthAnalytics = async (
  storeId?: string,
): Promise<GrowthAnalytics> => {
  const params = new URLSearchParams();
  if (storeId) params.append("storeId", storeId);

  const url = params.toString()
    ? `/analytics/growth?${params.toString()}`
    : "/analytics/growth";
  return clientFetch<GrowthAnalytics>(url);
};

// Helper function to determine if user is staff and get storeId
export const getStoreIdForUser = (): string | undefined => {
  if (typeof window === "undefined") return undefined;

  // Check if user is staff (you might need to adjust this based on your auth system)
  const userType = localStorage.getItem("userType");
  const storeId = localStorage.getItem("storeId");

  if (userType === "staff" && storeId) {
    return storeId;
  }

  return undefined;
};

// Enhanced analytics functions that automatically handle storeId for staff users
export const getAnalyticsOverviewWithStore =
  async (): Promise<AnalyticsOverview> => {
    const storeId = getStoreIdForUser();
    return getAnalyticsOverview(storeId);
  };

export const getRevenueTrendsWithStore = async (
  period: string = "30",
): Promise<RevenueData[]> => {
  const storeId = getStoreIdForUser();
  return getRevenueTrends(period, storeId);
};

export const getProductPerformanceWithStore = async (): Promise<
  ProductPerformance[]
> => {
  const storeId = getStoreIdForUser();
  return getProductPerformance(storeId);
};

export const getCustomerInsightsWithStore = async (
  page: number = 1,
  limit: number = 10,
  sortBy: string = "spent",
): Promise<CustomerInsights> => {
  const storeId = getStoreIdForUser();
  return getCustomerInsights(storeId, page, limit, sortBy);
};

export const getOrderAnalyticsWithStore = async (
  period: string = "30",
): Promise<OrderAnalytics> => {
  const storeId = getStoreIdForUser();
  return getOrderAnalytics(period, storeId);
};

export const getGrowthAnalyticsWithStore =
  async (): Promise<GrowthAnalytics> => {
    const storeId = getStoreIdForUser();
    return getGrowthAnalytics(storeId);
  };

// Prediction Types
export interface SalesPrediction {
  predicted: number | null;
  predictedOrders: number | null;
  dailyPredictions?: Array<{
    day: number;
    predicted: number;
    date: string;
  }>;
  confidence: "very_high" | "high" | "medium" | "low";
  method: string;
  methods?: {
    aiNeuralNetwork?: number | null;
    weightedMovingAverage?: number | null;
    exponentialSmoothing?: number | null;
    holtWinters?: number | null;
    weightedLinearRegression?: number | null;
    trendAdjusted?: number | null;
  };
  aiModel?: {
    used: boolean;
    available?: boolean;
    confidence?: string;
    modelAccuracy?: number;
    error?: string | null;
  };
  trend?: {
    direction: "up" | "down" | "neutral";
    strength: number;
    acceleration: number;
    slope?: number;
  };
  variance?: number;
  minPrediction?: number;
  maxPrediction?: number;
  confidenceScore?: number;
  confidenceIntervals?: {
    lower: number;
    upper: number;
    confidenceScore?: number;
    modelAgreement?: number;
    avgModelAccuracy?: number;
    dataConsistency?: number;
  };
  modelPerformance?: {
    [key: string]: {
      mae?: number;
      mape?: number;
      rmse?: number;
      accuracy?: number;
      confidence?: string;
    };
  };
  seasonality?: {
    dayOfWeek: Record<string, number>;
    month: Record<string, number>;
    confidence: string;
  };
  historicalPeriod: number;
  predictionPeriod: number;
  message?: string;
}

export interface DemandPrediction {
  predictedDaily: number | null;
  predictedWeekly: number | null;
  predictedMonthly: number | null;
  confidence: "very_high" | "high" | "medium" | "low";
  averageDaily?: number;
  trendFactor?: number;
  stdDev?: number;
  confidenceIntervals?: {
    lower: number;
    upper: number;
    confidenceScore?: number;
    modelAgreement?: number;
    avgModelAccuracy?: number;
    dataConsistency?: number;
  };
  historicalPeriod: number;
  predictionPeriod: number;
  productId?: string | null;
  message?: string;
}

export interface StockPrediction {
  productId: string;
  productName: string;
  currentStock: number;
  lowStockThreshold: number;
  unitType: string;
  prediction: {
    daysUntilOutOfStock: number | null;
    estimatedDate: string | null;
    confidence: "very_high" | "high" | "medium" | "low";
    averageDailySales?: number;
    stdDev?: number;
    optimisticDays?: number | null;
    pessimisticDays?: number | null;
    optimisticDate?: string | null;
    pessimisticDate?: string | null;
    message?: string;
  };
  needsRestock: boolean;
}

export interface StockPredictionsResponse {
  predictions: StockPrediction[];
  historicalPeriod: number;
  totalProducts: number;
  productsNeedingRestock: number;
}

export interface PredictionsOverview {
  sales: SalesPrediction;
  demand: DemandPrediction;
  stock: {
    totalProducts: number;
    message?: string;
  };
  historicalPeriod: number;
  predictionPeriod: number;
  message?: string;
}

export interface BatchPredictionsResponse {
  success: boolean;
  storeId?: string;
  historicalPeriod?: number;
  horizons?: number[];
  simulationFactors?: number[];
  predictions?: {
    [horizon: string]: {
      [simulationFactor: string]: PredictionsOverview;
    };
  };
  totalEntries?: number;
  generatedAt?: string;
  message?: string;
}


// Prediction Service Functions

/**
 * Get sales/revenue predictions
 * @param daysAhead Number of days to predict ahead (default: 7)
 * @param period Historical period in days (default: 30)
 * @param storeId Optional storeId for staff users
 */
export const getSalesPredictions = async (
  daysAhead: number = 7,
  period: number = 30,
  storeId?: string,
): Promise<SalesPrediction> => {
  const params = new URLSearchParams({
    daysAhead: daysAhead.toString(),
    period: period.toString(),
  });
  if (storeId) params.append("storeId", storeId);

  const url = `/analytics/predictions/sales?${params.toString()}`;
  return clientFetch<SalesPrediction>(url);
};

/**
 * Get product demand predictions
 * @param productId Optional product ID for specific product prediction
 * @param daysAhead Number of days to predict ahead (default: 7)
 * @param period Historical period in days (default: 30)
 * @param storeId Optional storeId for staff users
 */
export const getDemandPredictions = async (
  productId?: string,
  daysAhead: number = 7,
  period: number = 30,
  storeId?: string,
): Promise<DemandPrediction> => {
  const params = new URLSearchParams({
    daysAhead: daysAhead.toString(),
    period: period.toString(),
  });
  if (productId) params.append("productId", productId);
  if (storeId) params.append("storeId", storeId);

  const url = `/analytics/predictions/demand?${params.toString()}`;
  return clientFetch<DemandPrediction>(url);
};

/**
 * Get stock depletion predictions
 * @param period Historical period in days (default: 30)
 * @param storeId Optional storeId for staff users
 */
export const getStockPredictions = async (
  period: number = 30,
  storeId?: string,
): Promise<StockPredictionsResponse> => {
  const params = new URLSearchParams({
    period: period.toString(),
  });
  if (storeId) params.append("storeId", storeId);

  const url = `/analytics/predictions/stock?${params.toString()}`;
  return clientFetch<StockPredictionsResponse>(url);
};

/**
 * Get comprehensive predictions overview
 * @param daysAhead Number of days to predict ahead (default: 7)
 * @param period Historical period in days (default: 30)
 * @param storeId Optional storeId for staff users
 * @param simulation Simulation factor (e.g. 0.1 for +10%)
 */
export const getPredictionsOverview = async (
  daysAhead: number = 7,
  period: number = 30,
  storeId?: string,
  simulation: number = 0,
): Promise<PredictionsOverview> => {
  const params = new URLSearchParams({
    daysAhead: daysAhead.toString(),
    period: period.toString(),
    simulation: simulation.toString(),
  });
  if (storeId) params.append("storeId", storeId);

  const url = `/analytics/predictions/overview?${params.toString()}`;
  return clientFetch<PredictionsOverview>(url);
};

// Helper functions with automatic storeId handling
export const getSalesPredictionsWithStore = async (
  daysAhead: number = 7,
  period: number = 30,
): Promise<SalesPrediction> => {
  const storeId = getStoreIdForUser();
  return getSalesPredictions(daysAhead, period, storeId);
};

export const getDemandPredictionsWithStore = async (
  productId?: string,
  daysAhead: number = 7,
  period: number = 30,
): Promise<DemandPrediction> => {
  const storeId = getStoreIdForUser();
  return getDemandPredictions(productId, daysAhead, period, storeId);
};

export const getStockPredictionsWithStore = async (
  period: number = 30,
): Promise<StockPredictionsResponse> => {
  const storeId = getStoreIdForUser();
  return getStockPredictions(period, storeId);
};

export const getPredictionsOverviewWithStore = async (
  daysAhead: number = 7,
  period: number = 30,
  simulation: number = 0,
): Promise<PredictionsOverview> => {
  const storeId = getStoreIdForUser();
  return getPredictionsOverview(daysAhead, period, storeId, simulation);
};

/**
 * Get all cached predictions in one request (for client-side switching)
 * @param period Historical period in days (default: 90)
 * @param storeId Optional storeId for staff users
 */
export const getBatchPredictions = async (
  period: number = 90,
  storeId?: string,
): Promise<BatchPredictionsResponse> => {
  const params = new URLSearchParams({
    period: period.toString(),
  });
  if (storeId) params.append("storeId", storeId);

  const url = `/analytics/predictions/batch?${params.toString()}`;
  return clientFetch<BatchPredictionsResponse>(url);
};

export const getBatchPredictionsWithStore = async (
  period: number = 90,
): Promise<BatchPredictionsResponse> => {
  const storeId = getStoreIdForUser();
  return getBatchPredictions(period, storeId);
};
