import axios from 'axios';
import { AuthResponse, Story, Author, Tag, TagAlias, Series, SearchResult, PagedResult, Collection, CollectionSearchResult, StoryWithCollectionContext, CollectionStatistics } from '../types/api';

const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || '/api';

// Create axios instance with default config
const api = axios.create({
  baseURL: API_BASE_URL,
  withCredentials: true, // Include cookies for JWT
  headers: {
    'Content-Type': 'application/json',
  },
});

// Request interceptor to add JWT token
api.interceptors.request.use((config) => {
  const token = localStorage.getItem('auth-token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// Global auth failure handler - can be set by AuthContext
let globalAuthFailureHandler: (() => void) | null = null;

export const setGlobalAuthFailureHandler = (handler: () => void) => {
  globalAuthFailureHandler = handler;
};

// Flag to prevent multiple simultaneous refresh attempts
let isRefreshing = false;
let failedQueue: Array<{ resolve: (value?: any) => void; reject: (reason?: any) => void }> = [];

const processQueue = (error: any = null) => {
  failedQueue.forEach(prom => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve();
    }
  });

  failedQueue = [];
};

// Response interceptor to handle auth errors and token refresh
api.interceptors.response.use(
  (response) => response,
  async (error) => {
    const originalRequest = error.config;

    // Handle authentication failures
    if (error.response?.status === 401 || error.response?.status === 403) {
      // Don't attempt refresh for login or refresh endpoints
      if (originalRequest.url?.includes('/auth/login') || originalRequest.url?.includes('/auth/refresh')) {
        console.warn('Authentication failed on login/refresh endpoint');
        localStorage.removeItem('auth-token');

        if (globalAuthFailureHandler) {
          globalAuthFailureHandler();
        } else {
          window.location.href = '/login';
        }

        return Promise.reject(new Error('Authentication required'));
      }

      // If already retried, don't try again
      if (originalRequest._retry) {
        console.warn('Token refresh failed, logging out');
        localStorage.removeItem('auth-token');

        if (globalAuthFailureHandler) {
          globalAuthFailureHandler();
        } else {
          window.location.href = '/login';
        }

        return Promise.reject(new Error('Authentication required'));
      }

      // If already refreshing, queue this request
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject });
        }).then(() => {
          return api(originalRequest);
        }).catch((err) => {
          return Promise.reject(err);
        });
      }

      originalRequest._retry = true;
      isRefreshing = true;

      try {
        // Attempt to refresh the token
        const response = await api.post('/auth/refresh');

        if (response.data.token) {
          // Update stored token
          localStorage.setItem('auth-token', response.data.token);

          // Process queued requests
          processQueue();

          // Retry original request
          return api(originalRequest);
        }
      } catch (refreshError) {
        // Refresh failed, log out user
        processQueue(refreshError);
        localStorage.removeItem('auth-token');

        if (globalAuthFailureHandler) {
          globalAuthFailureHandler();
        } else {
          window.location.href = '/login';
        }

        return Promise.reject(new Error('Authentication required'));
      } finally {
        isRefreshing = false;
      }
    }

    return Promise.reject(error);
  }
);

// Auth endpoints
export const authApi = {
  login: async (password: string): Promise<AuthResponse> => {
    const response = await api.post('/auth/login', { password });
    // Store token in localStorage (httpOnly cookie is preferred but this is for backup)
    if (response.data.token) {
      localStorage.setItem('auth-token', response.data.token);
    }
    return response.data;
  },
  
  logout: async (): Promise<void> => {
    localStorage.removeItem('auth-token');
    // Could call backend logout endpoint if implemented
  },
  
  isAuthenticated: (): boolean => {
    return !!localStorage.getItem('auth-token');
  },
};

// Story endpoints
export const storyApi = {
  getStories: async (params?: {
    page?: number;
    size?: number;
    sortBy?: string;
    sortDir?: string;
  }): Promise<PagedResult<Story>> => {
    const response = await api.get('/stories', { params });
    return response.data;
  },
  
  getStoriesByAuthor: async (authorId: string, params?: { page?: number; size?: number }): Promise<PagedResult<Story>> => {
    const response = await api.get(`/stories/author/${authorId}`, { params });
    return response.data;
  },

  getStory: async (id: string): Promise<Story> => {
    const response = await api.get(`/stories/${id}`);
    return response.data;
  },
  
  createStory: async (storyData: {
    title: string;
    summary?: string;
    description?: string;
    contentHtml: string;
    sourceUrl?: string;
    volume?: number;
    authorId?: string;
    authorName?: string;
    seriesId?: string;
    seriesName?: string;
    tagNames?: string[];
  }): Promise<Story> => {
    const response = await api.post('/stories', storyData);
    return response.data;
  },
  
  updateStory: async (id: string, storyData: {
    title: string;
    summary?: string;
    description?: string;
    contentHtml: string;
    sourceUrl?: string;
    volume?: number;
    authorId?: string;
    seriesId?: string;
    seriesName?: string;
    tagNames?: string[];
  }): Promise<Story> => {
    const response = await api.put(`/stories/${id}`, storyData);
    return response.data;
  },
  
  deleteStory: async (id: string): Promise<void> => {
    await api.delete(`/stories/${id}`);
  },
  
  updateRating: async (id: string, rating: number): Promise<void> => {
    await api.post(`/stories/${id}/rating`, { rating });
  },

  updateReadingProgress: async (id: string, position: number): Promise<Story> => {
    const response = await api.post(`/stories/${id}/reading-progress`, { position });
    return response.data;
  },
  
  uploadCover: async (id: string, coverImage: File): Promise<{ imagePath: string }> => {
    const formData = new FormData();
    formData.append('file', coverImage);
    const response = await api.post(`/stories/${id}/cover`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return response.data;
  },
  
  removeCover: async (id: string): Promise<void> => {
    await api.delete(`/stories/${id}/cover`);
  },

  processContentImages: async (id: string, htmlContent: string): Promise<{
    processedContent: string;
    warnings?: string[];
    downloadedImages: string[];
    hasWarnings: boolean;
  }> => {
    const response = await api.post(`/stories/${id}/process-content-images`, {
      htmlContent
    });
    return response.data;
  },

  addTag: async (storyId: string, tagId: string): Promise<Story> => {
    const response = await api.post(`/stories/${storyId}/tags/${tagId}`);
    return response.data;
  },

  removeTag: async (storyId: string, tagId: string): Promise<Story> => {
    const response = await api.delete(`/stories/${storyId}/tags/${tagId}`);
    return response.data;
  },
  
  getStoryCollections: async (storyId: string): Promise<Collection[]> => {
    const response = await api.get(`/stories/${storyId}/collections`);
    return response.data;
  },
  
  
  checkDuplicate: async (title: string, authorName: string): Promise<{
    hasDuplicates: boolean;
    count: number;
    duplicates: Array<{
      id: string;
      title: string;
      authorName: string;
      createdAt: string;
    }>;
  }> => {
    const response = await api.get('/stories/check-duplicate', {
      params: { title, authorName }
    });
    return response.data;
  },
  
  getRandomStory: async (filters?: {
    searchQuery?: string;
    tags?: string[];
    minWordCount?: number;
    maxWordCount?: number;
    createdAfter?: string;
    createdBefore?: string;
    lastReadAfter?: string;
    lastReadBefore?: string;
    minRating?: number;
    maxRating?: number;
    unratedOnly?: boolean;
    readingStatus?: string;
    hasReadingProgress?: boolean;
    hasCoverImage?: boolean;
    sourceDomain?: string;
    seriesFilter?: string;
    minTagCount?: number;
    popularOnly?: boolean;
    hiddenGemsOnly?: boolean;
  }): Promise<Story | null> => {
    try {
      // Use proper Solr RandomSortField with dynamic field random_* for true randomness
      // Each call generates a different random seed to ensure different random results
      const randomSeed = Math.floor(Math.random() * 1000000);
      const searchResult = await searchApi.search({
        query: filters?.searchQuery || '*:*',
        page: 0,
        size: 1, // Only get one result - Solr RandomSortField considers entire dataset
        authors: [],
        tags: filters?.tags || [],
        minRating: filters?.minRating,
        maxRating: filters?.maxRating,
        sortBy: `random_${randomSeed}`, // Use proper dynamic field with random seed
        sortDir: 'desc',

        // Advanced filters - pass through all filter options
        minWordCount: filters?.minWordCount,
        maxWordCount: filters?.maxWordCount,
        createdAfter: filters?.createdAfter,
        createdBefore: filters?.createdBefore,
        lastReadAfter: filters?.lastReadAfter,
        lastReadBefore: filters?.lastReadBefore,
        unratedOnly: filters?.unratedOnly,
        readingStatus: filters?.readingStatus,
        hasReadingProgress: filters?.hasReadingProgress,
        hasCoverImage: filters?.hasCoverImage,
        sourceDomain: filters?.sourceDomain,
        seriesFilter: filters?.seriesFilter,
        minTagCount: filters?.minTagCount,
        popularOnly: filters?.popularOnly,
        hiddenGemsOnly: filters?.hiddenGemsOnly,
      });

      return searchResult.results && searchResult.results.length > 0
        ? searchResult.results[0]
        : null;

    } catch (error: any) {
      if (error.response?.status === 404 || error.response?.status === 204) {
        // No content - no stories match filters
        return null;
      }

      // If random sorting fails, fallback to client-side approach
      console.warn('Solr random sorting failed, falling back to client-side selection:', error.message);

      try {
        // Fallback: get larger sample and pick randomly client-side
        const fallbackResult = await searchApi.search({
          query: filters?.searchQuery || '*:*',
          page: 0,
          size: 200, // Large enough sample for good randomness
          authors: [],
          tags: filters?.tags || [],
          minRating: filters?.minRating,
          maxRating: filters?.maxRating,
          sortBy: 'createdAt',
          sortDir: 'desc',

          // Same advanced filters
          minWordCount: filters?.minWordCount,
          maxWordCount: filters?.maxWordCount,
          createdAfter: filters?.createdAfter,
          createdBefore: filters?.createdBefore,
          lastReadAfter: filters?.lastReadAfter,
          lastReadBefore: filters?.lastReadBefore,
          unratedOnly: filters?.unratedOnly,
          readingStatus: filters?.readingStatus,
          hasReadingProgress: filters?.hasReadingProgress,
          hasCoverImage: filters?.hasCoverImage,
          sourceDomain: filters?.sourceDomain,
          seriesFilter: filters?.seriesFilter,
          minTagCount: filters?.minTagCount,
          popularOnly: filters?.popularOnly,
          hiddenGemsOnly: filters?.hiddenGemsOnly,
        });

        if (fallbackResult.results && fallbackResult.results.length > 0) {
          const randomIndex = Math.floor(Math.random() * fallbackResult.results.length);
          return fallbackResult.results[randomIndex];
        }

        return null;
      } catch (fallbackError: any) {
        throw fallbackError;
      }
    }
  },
};

// Author endpoints
export const authorApi = {
  getAuthors: async (params?: {
    page?: number;
    size?: number;
    sortBy?: string;
    sortDir?: string;
  }): Promise<PagedResult<Author>> => {
    const response = await api.get('/authors', { params });
    return response.data;
  },
  
  getAuthor: async (id: string): Promise<Author> => {
    const response = await api.get(`/authors/${id}`);
    return response.data;
  },
  
  updateAuthor: async (id: string, formData: FormData): Promise<Author> => {
    const response = await api.put(`/authors/${id}`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return response.data;
  },
  
  uploadAvatar: async (id: string, avatarImage: File): Promise<{ imagePath: string }> => {
    const formData = new FormData();
    formData.append('file', avatarImage);
    const response = await api.post(`/authors/${id}/avatar`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return response.data;
  },
  
  removeAvatar: async (id: string): Promise<void> => {
    await api.delete(`/authors/${id}/avatar`);
  },

  searchAuthors: async (params: {
    query?: string;
    page?: number;
    size?: number;
    sortBy?: string;
    sortDir?: string;
  }): Promise<{
    results: Author[];
    totalHits: number;
    page: number;
    perPage: number;
    query: string;
    searchTimeMs: number;
  }> => {
    const searchParams = new URLSearchParams();

    // Add query parameter
    searchParams.append('q', params.query || '*');
    if (params.page !== undefined) searchParams.append('page', params.page.toString());
    if (params.size !== undefined) searchParams.append('size', params.size.toString());
    if (params.sortBy) searchParams.append('sortBy', params.sortBy);
    if (params.sortDir) searchParams.append('sortOrder', params.sortDir);

    const response = await api.get(`/authors/search-typesense?${searchParams.toString()}`);
    return response.data;
  },

  // Simple name-based search (faster for autocomplete)
  searchAuthorsByName: async (query: string, params?: {
    page?: number;
    size?: number;
  }): Promise<PagedResult<Author>> => {
    const response = await api.get('/authors/search', {
      params: {
        query,
        page: params?.page ?? 0,
        size: params?.size ?? 20,
      },
    });
    return response.data;
  },

};

// Tag endpoints
export const tagApi = {
  getTags: async (params?: {
    page?: number;
    size?: number;
    sortBy?: string;
    sortDir?: string;
  }): Promise<PagedResult<Tag>> => {
    const response = await api.get('/tags', { params });
    return response.data;
  },
  
  getTag: async (id: string): Promise<Tag> => {
    const response = await api.get(`/tags/${id}`);
    return response.data;
  },
  
  createTag: async (tagData: {
    name: string;
    color?: string;
    description?: string;
  }): Promise<Tag> => {
    const response = await api.post('/tags', tagData);
    return response.data;
  },
  
  updateTag: async (id: string, tagData: {
    name?: string;
    color?: string;
    description?: string;
  }): Promise<Tag> => {
    const response = await api.put(`/tags/${id}`, tagData);
    return response.data;
  },
  
  deleteTag: async (id: string): Promise<void> => {
    await api.delete(`/tags/${id}`);
  },
  
  getTagAutocomplete: async (query: string): Promise<string[]> => {
    const response = await api.get('/tags/autocomplete', { params: { query } });
    // Backend returns TagDto[], extract just the names
    return response.data.map((tag: Tag) => tag.name);
  },
  
  getCollectionTags: async (): Promise<Tag[]> => {
    const response = await api.get('/tags/collections');
    return response.data;
  },
  
  // Alias operations
  addAlias: async (tagId: string, aliasName: string): Promise<TagAlias> => {
    const response = await api.post(`/tags/${tagId}/aliases`, { aliasName });
    return response.data;
  },
  
  removeAlias: async (tagId: string, aliasId: string): Promise<void> => {
    await api.delete(`/tags/${tagId}/aliases/${aliasId}`);
  },
  
  resolveTag: async (name: string): Promise<Tag | null> => {
    try {
      const response = await api.get(`/tags/resolve/${encodeURIComponent(name)}`);
      return response.data;
    } catch (error: any) {
      if (error.response?.status === 404) {
        return null;
      }
      throw error;
    }
  },
  
  // Batch resolve multiple tag names to their canonical forms
  resolveTags: async (names: string[]): Promise<string[]> => {
    const resolved = await Promise.all(
      names.map(async (name) => {
        const tag = await tagApi.resolveTag(name);
        return tag ? tag.name : name; // Return canonical name or original if not found
      })
    );
    return resolved;
  },
  
  // Merge operations
  previewMerge: async (sourceTagIds: string[], targetTagId: string): Promise<{
    targetTagName: string;
    targetStoryCount: number;
    totalResultStoryCount: number;
    aliasesToCreate: string[];
  }> => {
    const response = await api.post('/tags/merge/preview', {
      sourceTagIds,
      targetTagId
    });
    return response.data;
  },
  
  mergeTags: async (sourceTagIds: string[], targetTagId: string): Promise<Tag> => {
    const response = await api.post('/tags/merge', {
      sourceTagIds,
      targetTagId
    });
    return response.data;
  },
  
  // Tag suggestions
  suggestTags: async (title: string, content?: string, summary?: string, limit?: number): Promise<{
    tagName: string;
    confidence: number;
    reason: string;
  }[]> => {
    const response = await api.post('/tags/suggest', {
      title,
      content,
      summary,
      limit: limit || 10
    });
    return response.data;
  },
};

// Series endpoints
export const seriesApi = {
  getSeries: async (params?: {
    page?: number;
    size?: number;
    sortBy?: string;
    sortDir?: string;
  }): Promise<PagedResult<Series>> => {
    const response = await api.get('/series', { params });
    return response.data;
  },

  // Simple name-based search (faster for autocomplete)
  searchSeriesByName: async (query: string, params?: {
    page?: number;
    size?: number;
  }): Promise<PagedResult<Series>> => {
    const response = await api.get('/series/search', {
      params: {
        query,
        page: params?.page ?? 0,
        size: params?.size ?? 20,
      },
    });
    return response.data;
  },

  getSeriesStories: async (id: string): Promise<Story[]> => {
    const response = await api.get(`/stories/series/${id}`);
    return response.data;
  },

  createCollectionFromSeries: async (seriesId: string): Promise<{ collectionId: string; name: string }> => {
    const response = await api.post(`/series/${seriesId}/create-collection`);
    return response.data;
  },
};

// Search endpoints
export const searchApi = {
  search: async (params: {
    query: string;
    page?: number;
    size?: number;
    authors?: string[];
    tags?: string[];
    minRating?: number;
    maxRating?: number;
    sortBy?: string;
    sortDir?: string;
    facetBy?: string[];
    // Advanced filters
    minWordCount?: number;
    maxWordCount?: number;
    createdAfter?: string;
    createdBefore?: string;
    lastReadAfter?: string;
    lastReadBefore?: string;
    unratedOnly?: boolean;
    readingStatus?: string;
    hasReadingProgress?: boolean;
    hasCoverImage?: boolean;
    sourceDomain?: string;
    seriesFilter?: string;
    minTagCount?: number;
    popularOnly?: boolean;
    hiddenGemsOnly?: boolean;
  }): Promise<SearchResult> => {
    // Resolve tag aliases to canonical names for expanded search
    let resolvedTags = params.tags;
    if (params.tags && params.tags.length > 0) {
      try {
        resolvedTags = await tagApi.resolveTags(params.tags);
      } catch (error) {
        console.warn('Failed to resolve tag aliases during search:', error);
        // Fall back to original tags if resolution fails
        resolvedTags = params.tags;
      }
    }
    
    // Create URLSearchParams to properly handle array parameters
    const searchParams = new URLSearchParams();
    
    // Add basic parameters
    searchParams.append('query', params.query);
    if (params.page !== undefined) searchParams.append('page', params.page.toString());
    if (params.size !== undefined) searchParams.append('size', params.size.toString());
    if (params.minRating !== undefined) searchParams.append('minRating', params.minRating.toString());
    if (params.maxRating !== undefined) searchParams.append('maxRating', params.maxRating.toString());
    if (params.sortBy) searchParams.append('sortBy', params.sortBy);
    if (params.sortDir) searchParams.append('sortDir', params.sortDir);
    
    // Advanced filters
    if (params.minWordCount !== undefined) searchParams.append('minWordCount', params.minWordCount.toString());
    if (params.maxWordCount !== undefined) searchParams.append('maxWordCount', params.maxWordCount.toString());
    if (params.createdAfter) searchParams.append('createdAfter', params.createdAfter);
    if (params.createdBefore) searchParams.append('createdBefore', params.createdBefore);
    if (params.lastReadAfter) searchParams.append('lastReadAfter', params.lastReadAfter);
    if (params.lastReadBefore) searchParams.append('lastReadBefore', params.lastReadBefore);
    if (params.unratedOnly !== undefined) searchParams.append('unratedOnly', params.unratedOnly.toString());
    if (params.readingStatus) searchParams.append('readingStatus', params.readingStatus);
    if (params.hasReadingProgress !== undefined) searchParams.append('hasReadingProgress', params.hasReadingProgress.toString());
    if (params.hasCoverImage !== undefined) searchParams.append('hasCoverImage', params.hasCoverImage.toString());
    if (params.sourceDomain) searchParams.append('sourceDomain', params.sourceDomain);
    if (params.seriesFilter) searchParams.append('seriesFilter', params.seriesFilter);
    if (params.minTagCount !== undefined) searchParams.append('minTagCount', params.minTagCount.toString());
    if (params.popularOnly !== undefined) searchParams.append('popularOnly', params.popularOnly.toString());
    if (params.hiddenGemsOnly !== undefined) searchParams.append('hiddenGemsOnly', params.hiddenGemsOnly.toString());
    
    // Add array parameters - each element gets its own parameter
    if (params.authors && params.authors.length > 0) {
      params.authors.forEach(author => searchParams.append('authors', author));
    }
    if (resolvedTags && resolvedTags.length > 0) {
      resolvedTags.forEach(tag => searchParams.append('tags', tag));
    }
    if (params.facetBy && params.facetBy.length > 0) {
      params.facetBy.forEach(facet => searchParams.append('facetBy', facet));
    }
    
    const response = await api.get(`/stories/search?${searchParams.toString()}`);
    return response.data;
  },
};

// Configuration endpoints
export const configApi = {
  getHtmlSanitizationConfig: async (): Promise<{
    allowedTags: string[];
    allowedAttributes: Record<string, string[]>;
    allowedCssProperties: string[];
    removedAttributes: Record<string, string[]>;
    description: string;
  }> => {
    const response = await api.get('/config/html-sanitization');
    return response.data;
  },

  previewImageCleanup: async (): Promise<{
    success: boolean;
    orphanedCount: number;
    totalSizeBytes: number;
    formattedSize: string;
    foldersToDelete: number;
    referencedImagesCount: number;
    errors: string[];
    hasErrors: boolean;
    dryRun: boolean;
    error?: string;
    orphanedFiles?: Array<{
      filePath: string;
      fileName: string;
      fileSize: number;
      formattedSize: string;
      storyId: string;
      storyTitle: string | null;
      storyExists: boolean;
      canAccessStory: boolean;
      error?: string;
    }>;
  }> => {
    const response = await api.post('/config/cleanup/images/preview');
    return response.data;
  },

  executeImageCleanup: async (): Promise<{
    success: boolean;
    deletedCount: number;
    totalSizeBytes: number;
    formattedSize: string;
    foldersDeleted: number;
    referencedImagesCount: number;
    errors: string[];
    hasErrors: boolean;
    dryRun: boolean;
    error?: string;
  }> => {
    const response = await api.post('/config/cleanup/images/execute');
    return response.data;
  },

  previewEpubImageMigration: async (): Promise<{
    success: boolean;
    movedCount: number;
    unmatchedCount: number;
    errors: string[];
    hasErrors: boolean;
    dryRun: boolean;
    movedFiles: {
      fileName: string;
      filePath: string;
      targetPath?: string;
      fileSize: number;
      formattedSize: string;
      storyId: string | null;
      storyTitle: string | null;
      action: 'move' | 'copy' | 'unmatched';
    }[];
    error?: string;
  }> => {
    const response = await api.post('/config/migrate/epub-images/preview');
    return response.data;
  },

  executeEpubImageMigration: async (): Promise<{
    success: boolean;
    movedCount: number;
    unmatchedCount: number;
    errors: string[];
    hasErrors: boolean;
    dryRun: boolean;
    movedFiles: {
      fileName: string;
      filePath: string;
      targetPath?: string;
      fileSize: number;
      formattedSize: string;
      storyId: string | null;
      storyTitle: string | null;
      action: 'move' | 'copy' | 'unmatched';
    }[];
    error?: string;
  }> => {
    const response = await api.post('/config/migrate/epub-images/execute');
    return response.data;
  },
};

// Search Engine Management API
export const searchAdminApi = {
  // Get migration status
  getStatus: async (): Promise<{
    primaryEngine: string;
    dualWrite: boolean;
    solrAvailable: boolean;
  }> => {
    const response = await api.get('/admin/search/status');
    return response.data;
  },

  // Configure search engine
  configure: async (config: { engine: string; dualWrite: boolean }): Promise<{ message: string }> => {
    const response = await api.post('/admin/search/configure', config);
    return response.data;
  },

  // Enable/disable dual-write
  enableDualWrite: async (): Promise<{ message: string }> => {
    const response = await api.post('/admin/search/dual-write/enable');
    return response.data;
  },

  disableDualWrite: async (): Promise<{ message: string }> => {
    const response = await api.post('/admin/search/dual-write/disable');
    return response.data;
  },

  // Switch engines
  switchToSolr: async (): Promise<{ message: string }> => {
    const response = await api.post('/admin/search/switch/solr');
    return response.data;
  },


  // Emergency rollback
  emergencyRollback: async (): Promise<{ message: string }> => {
    const response = await api.post('/admin/search/emergency-rollback');
    return response.data;
  },

  // Solr operations
  reindexSolr: async (): Promise<{
    success: boolean;
    message: string;
    storiesCount?: number;
    authorsCount?: number;
    totalCount?: number;
    error?: string;
  }> => {
    const response = await api.post('/admin/search/solr/reindex');
    return response.data;
  },

  recreateSolrIndices: async (): Promise<{
    success: boolean;
    message: string;
    storiesCount?: number;
    authorsCount?: number;
    totalCount?: number;
    error?: string;
  }> => {
    const response = await api.post('/admin/search/solr/recreate');
    return response.data;
  },

  // Add libraryId field to schema
  addLibraryField: async (): Promise<{
    success: boolean;
    message: string;
    error?: string;
    details?: string;
    note?: string;
  }> => {
    const response = await api.post('/admin/search/solr/add-library-field');
    return response.data;
  },

  // Migrate to library-aware schema
  migrateLibrarySchema: async (): Promise<{
    success: boolean;
    message: string;
    storiesCount?: number;
    authorsCount?: number;
    totalCount?: number;
    error?: string;
    details?: string;
    note?: string;
  }> => {
    const response = await api.post('/admin/search/solr/migrate-library-schema');
    return response.data;
  },
};

// Collection endpoints
export const collectionApi = {
  getCollections: async (params?: {
    page?: number;
    limit?: number;
    search?: string;
    tags?: string[];
    archived?: boolean;
  }): Promise<CollectionSearchResult> => {
    // Create URLSearchParams to properly handle array parameters
    const searchParams = new URLSearchParams();
    
    if (params?.page !== undefined) searchParams.append('page', params.page.toString());
    if (params?.limit !== undefined) searchParams.append('limit', params.limit.toString());
    if (params?.search) searchParams.append('search', params.search);
    if (params?.archived !== undefined) searchParams.append('archived', params.archived.toString());
    
    // Add array parameters - each element gets its own parameter
    if (params?.tags && params.tags.length > 0) {
      params.tags.forEach(tag => searchParams.append('tags', tag));
    }
    
    const response = await api.get(`/collections?${searchParams.toString()}`);
    return response.data;
  },
  
  getCollection: async (id: string): Promise<Collection> => {
    const response = await api.get(`/collections/${id}`);
    return response.data;
  },
  
  createCollection: async (collectionData: {
    name: string;
    description?: string;
    tagNames?: string[];
    storyIds?: string[];
  }): Promise<Collection> => {
    const response = await api.post('/collections', collectionData);
    return response.data;
  },
  
  createCollectionWithImage: async (collectionData: {
    name: string;
    description?: string;
    tags?: string[];
    storyIds?: string[];
    coverImage?: File;
  }): Promise<Collection> => {
    const formData = new FormData();
    formData.append('name', collectionData.name);
    if (collectionData.description) formData.append('description', collectionData.description);
    if (collectionData.tags) {
      collectionData.tags.forEach(tag => formData.append('tags', tag));
    }
    if (collectionData.storyIds) {
      collectionData.storyIds.forEach(id => formData.append('storyIds', id));
    }
    if (collectionData.coverImage) {
      formData.append('coverImage', collectionData.coverImage);
    }
    
    const response = await api.post('/collections', formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return response.data;
  },
  
  updateCollection: async (id: string, collectionData: {
    name?: string;
    description?: string;
    tagNames?: string[];
    rating?: number;
  }): Promise<Collection> => {
    const response = await api.put(`/collections/${id}`, collectionData);
    return response.data;
  },
  
  deleteCollection: async (id: string): Promise<void> => {
    await api.delete(`/collections/${id}`);
  },
  
  archiveCollection: async (id: string, archived: boolean): Promise<Collection> => {
    const response = await api.put(`/collections/${id}/archive`, { archived });
    return response.data;
  },
  
  addStoriesToCollection: async (id: string, storyIds: string[], position?: number): Promise<{
    added: number;
    skipped: number;
    totalStories: number;
  }> => {
    const response = await api.post(`/collections/${id}/stories`, {
      storyIds,
      position,
    });
    return response.data;
  },
  
  removeStoryFromCollection: async (collectionId: string, storyId: string): Promise<void> => {
    await api.delete(`/collections/${collectionId}/stories/${storyId}`);
  },
  
  reorderStories: async (collectionId: string, storyOrders: Array<{
    storyId: string;
    position: number;
  }>): Promise<void> => {
    await api.put(`/collections/${collectionId}/stories/order`, {
      storyOrders,
    });
  },
  
  getStoryWithCollectionContext: async (collectionId: string, storyId: string): Promise<StoryWithCollectionContext> => {
    const response = await api.get(`/collections/${collectionId}/read/${storyId}`);
    return response.data;
  },
  
  getCollectionStatistics: async (id: string): Promise<CollectionStatistics> => {
    const response = await api.get(`/collections/${id}/stats`);
    return response.data;
  },
  
  uploadCover: async (id: string, coverImage: File): Promise<{ imagePath: string }> => {
    const formData = new FormData();
    formData.append('file', coverImage);
    const response = await api.post(`/collections/${id}/cover`, formData, {
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    return response.data;
  },
  
  removeCover: async (id: string): Promise<void> => {
    await api.delete(`/collections/${id}/cover`);
  },
};

// Database management endpoints
export const databaseApi = {
  clear: async (): Promise<{ success: boolean; message: string; deletedRecords?: number }> => {
    const response = await api.post('/database/clear');
    return response.data;
  },

  // Async backup creation
  backupComplete: async (): Promise<{ success: boolean; jobId: string; status: string; message: string }> => {
    const response = await api.post('/database/backup-complete');
    return response.data;
  },

  getBackupStatus: async (jobId: string): Promise<{
    success: boolean;
    jobId: string;
    status: string;
    progress: number;
    fileSizeBytes: number;
    createdAt: string;
    completedAt: string;
    errorMessage: string;
  }> => {
    const response = await api.get(`/database/backup-status/${jobId}`);
    return response.data;
  },

  // Filesystem-based backup management
  listBackupFiles: async (): Promise<{
    success: boolean;
    backups: Array<{
      filename: string;
      sizeBytes: number;
      createdAt: string;
      origin: 'MANUAL' | 'AUTO' | 'UNKNOWN';
    }>;
  }> => {
    const response = await api.get('/database/backups');
    return response.data;
  },

  restoreFromFile: async (filename: string): Promise<{ success: boolean; message: string }> => {
    const response = await api.post(`/database/backups/${encodeURIComponent(filename)}/restore`);
    return response.data;
  },

  downloadBackupFile: (filename: string): string => {
    return `/api/database/backups/${encodeURIComponent(filename)}/download`;
  },

  deleteBackupFile: async (filename: string): Promise<{ success: boolean; message: string }> => {
    const response = await api.delete(`/database/backups/${encodeURIComponent(filename)}`);
    return response.data;
  },

  clearComplete: async (): Promise<{ success: boolean; message: string; deletedRecords?: number }> => {
    const response = await api.post('/database/clear-complete');
    return response.data;
  },
};

// Library context for images - will be set by a React context provider
let currentLibraryId: string | null = null;

// Set the current library ID (called by library context or components)
export const setCurrentLibraryId = (libraryId: string | null): void => {
  currentLibraryId = libraryId;
};

// Get current library ID synchronously (fallback to 'default')
export const getCurrentLibraryId = (): string => {
  return currentLibraryId || 'default';
};

// Clear library cache when switching libraries
export const clearLibraryCache = (): void => {
  currentLibraryId = null;
};

// Library statistics endpoints
export const statisticsApi = {
  getOverviewStatistics: async (libraryId: string): Promise<import('../types/api').LibraryOverviewStats> => {
    const response = await api.get(`/libraries/${libraryId}/statistics/overview`);
    return response.data;
  },

  getTopTags: async (libraryId: string, limit: number = 20): Promise<import('../types/api').TopTagsStats> => {
    const response = await api.get(`/libraries/${libraryId}/statistics/top-tags`, {
      params: { limit }
    });
    return response.data;
  },

  getTopAuthors: async (libraryId: string, limit: number = 10): Promise<import('../types/api').TopAuthorsStats> => {
    const response = await api.get(`/libraries/${libraryId}/statistics/top-authors`, {
      params: { limit }
    });
    return response.data;
  },

  getRatingStats: async (libraryId: string): Promise<import('../types/api').RatingStats> => {
    const response = await api.get(`/libraries/${libraryId}/statistics/ratings`);
    return response.data;
  },

  getSourceDomainStats: async (libraryId: string, limit: number = 10): Promise<import('../types/api').SourceDomainStats> => {
    const response = await api.get(`/libraries/${libraryId}/statistics/source-domains`, {
      params: { limit }
    });
    return response.data;
  },

  getReadingProgress: async (libraryId: string): Promise<import('../types/api').ReadingProgressStats> => {
    const response = await api.get(`/libraries/${libraryId}/statistics/reading-progress`);
    return response.data;
  },

  getReadingActivity: async (libraryId: string): Promise<import('../types/api').ReadingActivityStats> => {
    const response = await api.get(`/libraries/${libraryId}/statistics/reading-activity`);
    return response.data;
  },
};

export const audioCoveApi = {
  sendToAudioCove: async (storyId: string): Promise<string> => {
    const response = await api.post(`/stories/${storyId}/send-to-audiocove`);
    return response.data;
  },

  sendCollectionToAudioCove: async (collectionId: string): Promise<string> => {
    const response = await api.post(`/collections/${collectionId}/send-to-audiocove`);
    return response.data;
  },
};

// Image utility - now library-aware
export const getImageUrl = (path: string): string => {
  if (!path) return '';

  // For compatibility during transition, handle both patterns
  if (path.startsWith('http')) {
    return path; // External URL
  }

  // Use library-aware API endpoint
  const libraryId = getCurrentLibraryId();
  return `/api/files/images/${libraryId}/${path}`;
};