'use client';

import {
  ReactNode,
  createContext,
  useCallback,
  useContext,
  useEffect,
  useState,
} from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import { useApiClient } from '@/lib/apiClient';
import type { components } from '@/lib/gen';

type MarketplaceProject = components['schemas']['ProjectResponse'];

type ViewMode = 'browse' | 'my-projects';
type SortField = 'created_at' | 'credit_bounty' | 'applicant_count' | 'title';
type SortOrder = 'asc' | 'desc';
type ClientSortBy = 'created_at' | 'credit_bounty' | 'creator_rating';

interface MarketplaceLandingContextType {
  // Projects state
  projects: MarketplaceProject[];
  isLoading: boolean;
  error: string | null;

  // Filters and search
  searchQuery: string;
  setSearchQuery: (query: string) => void;
  statusFilter: string;
  setStatusFilter: (filter: string) => void;
  viewMode: ViewMode;
  setViewMode: (mode: ViewMode) => void;
  sortField: SortField;
  setSortField: (field: SortField) => void;
  sortOrder: SortOrder;
  setSortOrder: (order: SortOrder) => void;
  sortBy: ClientSortBy;
  setSortBy: (sort: ClientSortBy) => void;

  // Filtered projects
  filteredProjects: MarketplaceProject[];

  // Actions
  fetchProjects: () => Promise<void>;
  refreshProjects: () => Promise<void>;
}

const MarketplaceLandingContext = createContext<
  MarketplaceLandingContextType | undefined
>(undefined);

export const useMarketplaceLanding = () => {
  const context = useContext(MarketplaceLandingContext);
  if (!context) {
    throw new Error(
      'useMarketplaceLanding must be used within a MarketplaceLandingProvider'
    );
  }
  return context;
};

interface MarketplaceLandingProviderProps {
  children: ReactNode;
}

export default function MarketplaceLandingProvider({
  children,
}: MarketplaceLandingProviderProps) {
  const { session } = useStores();
  const apiClient = useApiClient();

  // Projects state
  const [projects, setProjects] = useState<MarketplaceProject[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [accessForbidden, setAccessForbidden] = useState(false);

  // Filters and search
  const [searchQuery, setSearchQuery] = useState('');
  const [statusFilter, setStatusFilter] = useState<string>('all');
  const [viewMode, setViewMode] = useState<ViewMode>('browse');
  const [sortField, setSortField] = useState<SortField>('created_at');
  const [sortOrder, setSortOrder] = useState<SortOrder>('desc');
  const [sortBy, setSortBy] = useState<ClientSortBy>('created_at');

  // Fetch projects
  const fetchProjects = useCallback(async () => {
    try {
      setIsLoading(true);
      setError(null);

      // Build query parameters based on view mode
      const params = new URLSearchParams();

      if (viewMode === 'my-projects') {
        // My Projects: Show all projects by the current user (as creator or fulfiller)
        params.append('my_projects', 'true');
      }

      // Handle status filtering
      if (viewMode === 'browse') {
        // Browse All: Only show OPEN projects by default, or specific status if filtered
        if (statusFilter === 'all') {
          params.append('status', 'OPEN');
        } else {
          params.append('status', statusFilter);
        }
      } else if (viewMode === 'my-projects') {
        // My Projects: Show all statuses by default, or specific status if filtered
        if (statusFilter !== 'all') {
          params.append('status', statusFilter);
        }
      }

      // Add sorting parameters
      params.append('sort_by', sortField);
      params.append('sort_order', sortOrder);

      const url = `/api/marketplace/projects/?${params.toString()}`;

      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const response = await (apiClient.GET as any)(url);

      // Check for 403 Forbidden (user doesn't have marketplace access)
      if (response.response?.status === 403) {
        setAccessForbidden(true);
        setIsLoading(false);
        return;
      }

      if (response.error) {
        throw new Error('Failed to load projects');
      }

      if (!response.response || response.response.status >= 400) {
        throw new Error('Failed to load projects');
      }

      setProjects(response.data.projects || []);
    } catch (err) {
      console.error('Error fetching projects:', err);
      setError(err instanceof Error ? err.message : 'Failed to load projects');
      setProjects([]);
    } finally {
      setIsLoading(false);
    }
  }, [apiClient, viewMode, statusFilter, sortField, sortOrder]);

  // Refresh projects (for polling)
  const refreshProjects = useCallback(async () => {
    // Only refresh if user is logged in and we're not currently loading
    if (!session.userId || isLoading) return;

    try {
      // Build query parameters for polling
      const params = new URLSearchParams();
      if (viewMode === 'my-projects') {
        params.append('my_projects', 'true');
      }

      // Only show OPEN projects for browse mode
      if (viewMode === 'browse') {
        if (statusFilter === 'all') {
          params.append('status', 'OPEN');
        } else {
          params.append('status', statusFilter);
        }
      } else if (viewMode === 'my-projects' && statusFilter !== 'all') {
        params.append('status', statusFilter);
      }

      params.append('sort_by', sortField);
      params.append('sort_order', sortOrder);

      const url = `/api/marketplace/projects/?${params.toString()}`;
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const response = await (apiClient.GET as any)(url);

      if (
        response.error ||
        !response.response ||
        response.response.status >= 400
      ) {
        return; // Silently fail for polling
      }

      const newProjects = response.data.projects || [];

      // Check if there are any changes (new applicants or comments)
      const hasChanges = projects.some((oldProject, index) => {
        const newProject = newProjects[index];
        if (!newProject) return false;

        // Check for applicant count changes (for creators)
        if (oldProject.applicant_count !== newProject.applicant_count) {
          return true;
        }

        // For now, we'll just update all projects to get the latest data
        // In the future, we could add a last_activity timestamp to detect comment changes
        return false;
      });

      // Update projects if there are changes
      if (hasChanges || newProjects.length !== projects.length) {
        setProjects(newProjects);
      }
    } catch (err) {
      // Silently fail for polling to avoid console spam
      console.debug('Polling error (silent):', err);
    }
  }, [
    apiClient,
    viewMode,
    session.userId,
    statusFilter,
    sortField,
    sortOrder,
    projects,
    isLoading,
  ]);

  // Filter and sort projects
  const filteredProjects = projects
    .filter((project) => {
      // Only do client-side search filtering since status filtering is handled server-side
      return (
        project.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
        project.description.toLowerCase().includes(searchQuery.toLowerCase())
      );
    })
    .sort((a, b) => {
      // In "my-projects" view, prioritize IN_PROGRESS projects at the top
      if (viewMode === 'my-projects') {
        const aIsInProgress = a.status === 'IN_PROGRESS';
        const bIsInProgress = b.status === 'IN_PROGRESS';

        if (aIsInProgress && !bIsInProgress) return -1;
        if (!aIsInProgress && bIsInProgress) return 1;

        // For other statuses, sort by created_at (newest first)
        return (
          new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
        );
      }

      // For "browse" view, use client-side sorting based on sortBy
      if (viewMode === 'browse') {
        if (sortBy === 'credit_bounty') {
          return b.credit_bounty - a.credit_bounty;
        } else if (sortBy === 'creator_rating') {
          // Sort by creator rating (highest first), handle null values
          const aRating = a.creator_average_rating ?? 0;
          const bRating = b.creator_average_rating ?? 0;
          return bRating - aRating;
        } else {
          // Default: created_at (newest first)
          return (
            new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
          );
        }
      }

      return 0;
    });

  // Initial data fetch
  useEffect(() => {
    fetchProjects();
  }, [fetchProjects]);

  // Polling for updates
  useEffect(() => {
    // Set up polling interval
    const pollInterval = setInterval(refreshProjects, 10000); // 10 seconds

    // Clean up interval on unmount
    return () => clearInterval(pollInterval);
  }, [refreshProjects]);

  // Show 404 if user doesn't have marketplace access
  if (accessForbidden) {
    return (
      <div className='flex h-screen w-full items-center justify-center'>
        <div className='text-center'>
          <h1 className='text-4xl font-bold'>404</h1>
          <p className='mt-4'>This page could not be found.</p>
        </div>
      </div>
    );
  }

  const value: MarketplaceLandingContextType = {
    // Projects state
    projects,
    isLoading,
    error,

    // Filters and search
    searchQuery,
    setSearchQuery,
    statusFilter,
    setStatusFilter,
    viewMode,
    setViewMode,
    sortField,
    setSortField,
    sortOrder,
    setSortOrder,
    sortBy,
    setSortBy,

    // Filtered projects
    filteredProjects,

    // Actions
    fetchProjects,
    refreshProjects,
  };

  return (
    <MarketplaceLandingContext.Provider value={value}>
      {children}
    </MarketplaceLandingContext.Provider>
  );
}
