/**
 * Query Parameter Types
 * FE-TYPE-009: Add type definitions for all query parameters
 *
 * Comprehensive type definitions for all query parameters used throughout
 * the application, ensuring type safety for URL query string handling.
 */

/**
 * Base query parameter types
 */
export type SortOrder = 'asc' | 'desc';
export type SortDirection = 'asc' | 'desc';

/**
 * Pagination Query Parameters
 * Common query params: ?page=1&limit=20
 */
export interface PaginationQueryParams {
  page?: string; // Page number (as string from URL)
  limit?: string; // Items per page (as string from URL)
  cursor?: string; // Cursor for cursor-based pagination
  offset?: string; // Offset for offset-based pagination
}

/**
 * Sort Query Parameters
 * Common query params: ?sort_by=name&sort_order=asc
 */
export interface SortQueryParams {
  sort_by?: string; // Field to sort by
  sort_order?: SortOrder; // Sort direction
  sort?: string; // Alternative sort field name
  order?: SortOrder; // Alternative order field name
}

/**
 * Search Query Parameters
 * Route: /search?q=query&type=tracks
 */
export interface SearchQueryParams {
  q?: string; // Search query
  query?: string; // Alternative query parameter name
  type?:
    | 'all'
    | 'track'
    | 'tracks'
    | 'playlist'
    | 'playlists'
    | 'user'
    | 'users';
  page?: string;
  limit?: string;
}

/**
 * Track Search Query Parameters
 * Advanced search with filters
 */
export interface TrackSearchQueryParams {
  q?: string; // Search query
  tags?: string; // Comma-separated tags
  tag_mode?: 'all' | 'any'; // Tag matching mode
  min_duration?: string; // Minimum duration in seconds
  max_duration?: string; // Maximum duration in seconds
  min_bpm?: string; // Minimum BPM
  max_bpm?: string; // Maximum BPM
  genre?: string; // Genre filter
  format?: string; // Audio format (mp3, flac, etc.)
  min_date?: string; // Minimum date (ISO8601)
  max_date?: string; // Maximum date (ISO8601)
  page?: string;
  limit?: string;
  sort_by?: string;
  sort_order?: SortOrder;
}

/**
 * Playlist Search Query Parameters
 */
export interface PlaylistSearchQueryParams {
  q?: string; // Search query
  owner?: string; // Owner username or ID
  is_public?: 'true' | 'false'; // Public/private filter
  min_tracks?: string; // Minimum number of tracks
  max_tracks?: string; // Maximum number of tracks
  page?: string;
  limit?: string;
  sort_by?:
    | 'name'
    | 'created_at'
    | 'updated_at'
    | 'track_count'
    | 'follower_count';
  sort_order?: SortOrder;
}

/**
 * User Search Query Parameters
 */
export interface UserSearchQueryParams {
  q?: string; // Search query
  role?: string; // User role filter
  is_verified?: 'true' | 'false'; // Verified users only
  is_active?: 'true' | 'false'; // Active users only
  page?: string;
  limit?: string;
  sort_by?: 'username' | 'created_at' | 'last_login';
  sort_order?: SortOrder;
}

/**
 * Library Query Parameters
 * Route: /library?filter=tracks&sort=recent
 */
export interface LibraryQueryParams {
  filter?: 'all' | 'tracks' | 'playlists' | 'favorites' | 'recent';
  sort?: 'recent' | 'name' | 'artist' | 'date' | 'title';
  order?: SortOrder;
  page?: string;
  limit?: string;
}

/**
 * Marketplace Query Parameters
 * Route: /marketplace?category=music&price_min=10&price_max=100
 */
export interface MarketplaceQueryParams {
  category?: string; // Product category
  price_min?: string; // Minimum price
  price_max?: string; // Maximum price
  currency?: string; // Currency code
  sort?: 'price' | 'date' | 'popularity' | 'rating';
  order?: SortOrder;
  page?: string;
  limit?: string;
}

/**
 * Track List Query Parameters
 */
export interface TrackListQueryParams {
  artist?: string; // Filter by artist
  genre?: string; // Filter by genre
  year?: string; // Filter by year
  is_public?: 'true' | 'false'; // Public/private filter
  status?: 'uploading' | 'processing' | 'completed' | 'failed';
  page?: string;
  limit?: string;
  sort_by?: 'title' | 'artist' | 'created_at' | 'play_count' | 'like_count';
  sort_order?: SortOrder;
}

/**
 * Playlist List Query Parameters
 */
export interface PlaylistListQueryParams {
  user_id?: string; // Filter by user
  is_public?: 'true' | 'false'; // Public/private filter
  min_tracks?: string; // Minimum number of tracks
  max_tracks?: string; // Maximum number of tracks
  page?: string;
  limit?: string;
  sort_by?: 'name' | 'created_at' | 'updated_at' | 'track_count';
  sort_order?: SortOrder;
}

/**
 * Conversation List Query Parameters
 */
export interface ConversationListQueryParams {
  type?: 'direct' | 'group'; // Conversation type
  unread_only?: 'true' | 'false'; // Show only unread
  page?: string;
  limit?: string;
  sort_by?: 'name' | 'updated_at' | 'created_at';
  sort_order?: SortOrder;
}

/**
 * Message List Query Parameters
 */
export interface MessageListQueryParams {
  conversation_id?: string; // Filter by conversation
  sender_id?: string; // Filter by sender
  message_type?: 'text' | 'image' | 'audio' | 'file';
  page?: string;
  limit?: string;
  sort_by?: 'created_at' | 'updated_at';
  sort_order?: SortOrder;
}

/**
 * Notification Query Parameters
 */
export interface NotificationQueryParams {
  type?: string; // Notification type filter
  read?: 'true' | 'false'; // Read/unread filter
  page?: string;
  limit?: string;
  sort_by?: 'created_at';
  sort_order?: SortOrder;
}

/**
 * Audit Log Query Parameters
 */
export interface AuditLogQueryParams {
  user_id?: string; // Filter by user
  action?: string; // Filter by action
  resource?: string; // Filter by resource type
  start_date?: string; // Start date (ISO8601)
  end_date?: string; // End date (ISO8601)
  page?: string;
  limit?: string;
  sort_by?: 'timestamp' | 'action' | 'resource';
  sort_order?: SortOrder;
}

/**
 * Analytics Query Parameters
 */
export interface AnalyticsQueryParams {
  start_date?: string; // Start date (ISO8601)
  end_date?: string; // End date (ISO8601)
  metric?: string; // Metric to analyze
  group_by?: string; // Grouping field
  interval?: 'hour' | 'day' | 'week' | 'month'; // Time interval
}

/**
 * Filter Query Parameters (generic)
 */
export interface FilterQueryParams {
  filter?: string; // Filter value
  filters?: string; // Multiple filters (comma-separated)
  exclude?: string; // Exclude filter
  include?: string; // Include filter
}

/**
 * Date Range Query Parameters
 */
export interface DateRangeQueryParams {
  start_date?: string; // Start date (ISO8601)
  end_date?: string; // End date (ISO8601)
  date_from?: string; // Alternative start date
  date_to?: string; // Alternative end date
}

/**
 * Reset Password Query Parameters
 * Route: /reset-password?token=...
 */
export interface ResetPasswordQueryParams {
  token?: string; // Reset token
}

/**
 * Verify Email Query Parameters
 * Route: /verify-email?token=...
 */
export interface VerifyEmailQueryParams {
  token?: string; // Verification token
}

/**
 * OAuth Callback Query Parameters
 * Route: /auth/callback?code=...&state=...
 */
export interface OAuthCallbackQueryParams {
  code?: string; // OAuth authorization code
  state?: string; // OAuth state parameter
  error?: string; // OAuth error code
  error_description?: string; // OAuth error description
}

/**
 * Share Query Parameters
 * Route: /share?token=...&type=...
 */
export interface ShareQueryParams {
  token?: string; // Share token
  type?: 'track' | 'playlist' | 'user';
  id?: string; // Resource ID
}

/**
 * Embed Query Parameters
 * Route: /embed?track_id=...&autoplay=true
 */
export interface EmbedQueryParams {
  track_id?: string; // Track ID
  playlist_id?: string; // Playlist ID
  autoplay?: 'true' | 'false'; // Autoplay option
  controls?: 'true' | 'false'; // Show controls
  theme?: 'light' | 'dark'; // Theme
}

/**
 * Admin Query Parameters
 */
export interface AdminQueryParams {
  section?: string; // Admin section
  action?: string; // Admin action
  user_id?: string; // User ID filter
  role_id?: string; // Role ID filter
  page?: string;
  limit?: string;
}

/**
 * Settings Query Parameters
 */
export interface SettingsQueryParams {
  tab?:
    | 'profile'
    | 'security'
    | 'notifications'
    | 'privacy'
    | 'sessions'
    | 'api';
  section?: string; // Settings section
}

/**
 * Helper function to parse query params from URLSearchParams
 */
export function parseQueryParams<T extends Record<string, string | undefined>>(
  searchParams: URLSearchParams,
): Partial<T> {
  const params: Partial<T> = {};

  for (const [key, value] of searchParams.entries()) {
    params[key as keyof T] = value as T[keyof T];
  }

  return params;
}

/**
 * Helper function to build query string from params
 */
export function buildQueryString<
  T extends Record<string, string | number | boolean | undefined>,
>(params: T): string {
  const searchParams = new URLSearchParams();

  for (const [key, value] of Object.entries(params)) {
    if (value !== null && value !== undefined && value !== '') {
      searchParams.set(key, String(value));
    }
  }

  return searchParams.toString();
}

/**
 * Helper function to convert string query params to typed values
 */
export function convertQueryParams<
  T extends Record<string, string | undefined>,
>(
  params: Partial<T>,
  converters: {
    [K in keyof T]?: (value: string) => T[K];
  },
): Partial<T> {
  const converted: Partial<T> = {};

  for (const [key, value] of Object.entries(params)) {
    if (value !== undefined) {
      const converter = converters[key as keyof T];
      if (converter) {
        converted[key as keyof T] = converter(value);
      } else {
        converted[key as keyof T] = value as T[keyof T];
      }
    }
  }

  return converted;
}

/**
 * Helper to parse pagination params
 */
export function parsePaginationParams(params: PaginationQueryParams): {
  page: number;
  limit: number;
} {
  return {
    page: params.page ? parseInt(params.page, 10) : 1,
    limit: params.limit ? parseInt(params.limit, 10) : 20,
  };
}

/**
 * Helper to parse boolean query params
 */
export function parseBooleanParam(
  value: string | undefined,
): boolean | undefined {
  if (value === undefined) return undefined;
  return value === 'true' || value === '1';
}

/**
 * Helper to parse number query params
 */
export function parseNumberParam(
  value: string | undefined,
): number | undefined {
  if (value === undefined) return undefined;
  const parsed = parseInt(value, 10);
  return isNaN(parsed) ? undefined : parsed;
}
