import { createContext, useContext, useState, useCallback, type ReactNode } from 'react';
import type { Segment, SegmentMetrics } from './types';

export type { Segment, SegmentCondition, SegmentMetrics } from './types';

/**
 * Segment context state
 */
interface SegmentContextState {
  /** Currently selected segment (null = all traffic) */
  selectedSegment: Segment | null;
  /** All available segments */
  availableSegments: Segment[];
  /** Comparison segment (for A/B comparison) */
  comparisonSegment: Segment | null;
  /** Whether segment data is loading */
  loading: boolean;
  /** Any error from segment operations */
  error: string | null;
}

/**
 * Segment context actions
 */
interface SegmentContextActions {
  /** Select a segment to apply globally */
  selectSegment: (segment: Segment | null) => void;
  /** Set comparison segment for A/B analysis */
  setComparisonSegment: (segment: Segment | null) => void;
  /** Load available segments from API */
  loadSegments: () => Promise<void>;
  /** Create a new segment */
  createSegment: (
    segment: Omit<Segment, 'id' | 'isBuiltIn' | 'createdAt' | 'updatedAt'>
  ) => Promise<Segment>;
  /** Delete a segment */
  deleteSegment: (segmentId: string) => Promise<void>;
  /** Clear all segment selections */
  clearSelection: () => void;
}

type SegmentContextValue = SegmentContextState & SegmentContextActions;

const SegmentContext = createContext<SegmentContextValue | null>(null);

export interface SegmentProviderProps {
  children: ReactNode;
  /** Base URL for segments API (default: /api/segments) */
  apiBaseUrl?: string;
  /** Initial segment to select */
  initialSegment?: Segment | null;
}

/**
 * Provider for global segment state
 */
export function SegmentProvider({
  children,
  apiBaseUrl = '/api/segments',
  initialSegment = null,
}: SegmentProviderProps) {
  const [selectedSegment, setSelectedSegment] = useState<Segment | null>(initialSegment);
  const [comparisonSegment, setComparisonSegment] = useState<Segment | null>(null);
  const [availableSegments, setAvailableSegments] = useState<Segment[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const loadSegments = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const response = await fetch(apiBaseUrl);
      if (!response.ok) {
        throw new Error(`Failed to load segments: ${response.statusText}`);
      }
      const segments = await response.json();
      setAvailableSegments(segments);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load segments');
    } finally {
      setLoading(false);
    }
  }, [apiBaseUrl]);

  const selectSegment = useCallback((segment: Segment | null) => {
    setSelectedSegment(segment);
  }, []);

  const createSegment = useCallback(
    async (
      segmentData: Omit<Segment, 'id' | 'isBuiltIn' | 'createdAt' | 'updatedAt'>
    ): Promise<Segment> => {
      setLoading(true);
      setError(null);
      try {
        const response = await fetch(apiBaseUrl, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(segmentData),
        });
        if (!response.ok) {
          const errorData = await response.json().catch(() => ({}));
          throw new Error(
            errorData.message || `Failed to create segment: ${response.statusText}`
          );
        }
        const newSegment = await response.json();
        setAvailableSegments((prev) => [...prev, newSegment]);
        return newSegment;
      } catch (err) {
        const message = err instanceof Error ? err.message : 'Failed to create segment';
        setError(message);
        throw err;
      } finally {
        setLoading(false);
      }
    },
    [apiBaseUrl]
  );

  const deleteSegment = useCallback(
    async (segmentId: string) => {
      setLoading(true);
      setError(null);
      try {
        const response = await fetch(`${apiBaseUrl}/${segmentId}`, {
          method: 'DELETE',
        });
        if (!response.ok) {
          const errorData = await response.json().catch(() => ({}));
          throw new Error(
            errorData.message || `Failed to delete segment: ${response.statusText}`
          );
        }
        setAvailableSegments((prev) => prev.filter((s) => s.id !== segmentId));
        if (selectedSegment?.id === segmentId) {
          setSelectedSegment(null);
        }
        if (comparisonSegment?.id === segmentId) {
          setComparisonSegment(null);
        }
      } catch (err) {
        const message = err instanceof Error ? err.message : 'Failed to delete segment';
        setError(message);
        throw err;
      } finally {
        setLoading(false);
      }
    },
    [apiBaseUrl, selectedSegment, comparisonSegment]
  );

  const clearSelection = useCallback(() => {
    setSelectedSegment(null);
    setComparisonSegment(null);
  }, []);

  const value: SegmentContextValue = {
    selectedSegment,
    comparisonSegment,
    availableSegments,
    loading,
    error,
    selectSegment,
    setComparisonSegment,
    loadSegments,
    createSegment,
    deleteSegment,
    clearSelection,
  };

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

/**
 * Hook to access segment context
 */
export function useSegment(): SegmentContextValue {
  const context = useContext(SegmentContext);
  if (!context) {
    throw new Error('useSegment must be used within a SegmentProvider');
  }
  return context;
}

/**
 * Hook to get current segment filter params for API calls
 */
export function useSegmentFilter(): { segmentId?: string } {
  const context = useContext(SegmentContext);
  if (!context?.selectedSegment) {
    return {};
  }
  return { segmentId: context.selectedSegment.id };
}
