import React, { createContext, useContext, useState, useCallback, useEffect } from 'react';
import { useAuth } from './AuthContext';
import {
  Subscription,
  SubscriptionPlan,
  SubscriptionStatus,
  SubscriptionFeatureFlag,
  planHasFeature,
  isSubscriptionActive,
  SUBSCRIPTION_PLANS,
} from '@/types/subscription';

interface SubscriptionContextType {
  subscription: Subscription | null;
  isLoading: boolean;
  refreshSubscription: () => Promise<void>;
  // Convenience methods
  hasFeature: (feature: SubscriptionFeatureFlag) => boolean;
  hasActiveSubscription: boolean;
  canAccessFeature: (feature: SubscriptionFeatureFlag) => boolean;
  isWithinLimits: (
    limitType: 'organizations' | 'users' | 'storage' | 'apiCalls',
    current: number
  ) => boolean;
  getRemainingLimit: (
    limitType: 'organizations' | 'users' | 'storage' | 'apiCalls',
    current: number
  ) => number;
}

const SubscriptionContext = createContext<SubscriptionContextType | undefined>(undefined);

export const useSubscription = () => {
  const context = useContext(SubscriptionContext);
  if (context === undefined) {
    throw new Error('useSubscription must be used within a SubscriptionProvider');
  }
  return context;
};

interface SubscriptionProviderProps {
  children: React.ReactNode;
}

/**
 * Subscription context provider for managing subscription state
 */
export const SubscriptionProvider = ({ children }: SubscriptionProviderProps) => {
  const { user, isAuthenticated } = useAuth();
  const [subscription, setSubscription] = useState<Subscription | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  const fetchSubscription = useCallback(async (): Promise<Subscription | null> => {
    if (!isAuthenticated || !user) {
      return null;
    }

    try {
      const token = localStorage.getItem('auth_token');
      const isProduction = import.meta.env.PROD;
      const baseUrl =
        import.meta.env.VITE_API_BASE_URL || (isProduction ? 'https://api.bugulma.city' : '');

      const response = await fetch(`${baseUrl}/api/v1/subscription`, {
        method: 'GET',
        headers: {
          Authorization: `Bearer ${token}`,
          'Content-Type': 'application/json',
        },
        signal: AbortSignal.timeout(5000),
      });

      if (response.ok) {
        const data = await response.json();
        return {
          ...data,
          currentPeriodStart: new Date(data.currentPeriodStart),
          currentPeriodEnd: new Date(data.currentPeriodEnd),
          trialEnd: data.trialEnd ? new Date(data.trialEnd) : undefined,
        };
      }

      // If no subscription, return default free plan
      return {
        id: 'free',
        userId: user.id,
        plan: 'free' as SubscriptionPlan,
        status: 'none' as SubscriptionStatus,
        billingPeriod: 'monthly',
        currentPeriodStart: new Date(),
        currentPeriodEnd: new Date(),
        cancelAtPeriodEnd: false,
        features: SUBSCRIPTION_PLANS.free.features,
        limits: SUBSCRIPTION_PLANS.free.limits,
      };
    } catch (error) {
      console.error('Failed to fetch subscription:', error);
      // Return free plan on error
      return {
        id: 'free',
        userId: user.id,
        plan: 'free' as SubscriptionPlan,
        status: 'none' as SubscriptionStatus,
        billingPeriod: 'monthly',
        currentPeriodStart: new Date(),
        currentPeriodEnd: new Date(),
        cancelAtPeriodEnd: false,
        features: SUBSCRIPTION_PLANS.free.features,
        limits: SUBSCRIPTION_PLANS.free.limits,
      };
    }
  }, [isAuthenticated, user]);

  const refreshSubscription = useCallback(async () => {
    setIsLoading(true);
    try {
      const sub = await fetchSubscription();
      setSubscription(sub);
    } catch (error) {
      console.error('Failed to refresh subscription:', error);
    } finally {
      setIsLoading(false);
    }
  }, [fetchSubscription]);

  useEffect(() => {
    if (isAuthenticated) {
      refreshSubscription();
    } else {
      setSubscription(null);
      setIsLoading(false);
    }
  }, [isAuthenticated, refreshSubscription]);

  const hasFeature = useCallback(
    (feature: SubscriptionFeatureFlag): boolean => {
      if (!subscription) return false;
      return planHasFeature(subscription.plan, feature);
    },
    [subscription]
  );

  const hasActiveSubscription = subscription ? isSubscriptionActive(subscription.status) : false;

  const canAccessFeature = useCallback(
    (feature: SubscriptionFeatureFlag): boolean => {
      if (!subscription) return false;
      return hasActiveSubscription && hasFeature(feature);
    },
    [subscription, hasActiveSubscription, hasFeature]
  );

  const isWithinLimits = useCallback(
    (limitType: 'organizations' | 'users' | 'storage' | 'apiCalls', current: number): boolean => {
      if (!subscription) return true; // No subscription = free plan limits
      const limit = subscription.limits[limitType];
      if (limit === undefined || limit === -1) return true; // Unlimited
      return current < limit;
    },
    [subscription]
  );

  const getRemainingLimit = useCallback(
    (limitType: 'organizations' | 'users' | 'storage' | 'apiCalls', current: number): number => {
      if (!subscription) {
        const freeLimit = SUBSCRIPTION_PLANS.free.limits[limitType] || 0;
        return Math.max(0, freeLimit - current);
      }
      const limit = subscription.limits[limitType];
      if (limit === undefined || limit === -1) return Infinity;
      return Math.max(0, limit - current);
    },
    [subscription]
  );

  const value: SubscriptionContextType = {
    subscription,
    isLoading,
    refreshSubscription,
    hasFeature,
    hasActiveSubscription,
    canAccessFeature,
    isWithinLimits,
    getRemainingLimit,
  };

  return <SubscriptionContext.Provider value={value}>{children}</SubscriptionContext.Provider>;
};
