import { 
  ApiResponse,
  SendMessageRequest,
  SendMessageResponse,
  GetMessagesRequest,
  GetMessagesResponse,
  CreateConversationRequest,
  CreateConversationResponse,
  GetConversationsResponse,
  GetNotificationsRequest,
  GetNotificationsResponse,
  NotificationStatistics,
  SearchMessagesRequest,
  SearchMessagesResponse,
  UpdateMessageRequest,
  MarkMessagesReadRequest,
  TypingIndicatorRequest,
  Message,
  Conversation,
  Notification
} from '../types';

// API service for handling HTTP requests
const API_BASE_URL = (() => {
  const dev = typeof import.meta !== 'undefined' && (import.meta as any).env && (import.meta as any).env.DEV;
  if (dev) return '/api';
  const envUrl = typeof import.meta !== 'undefined' && (import.meta as any).env && (import.meta as any).env.VITE_API_BASE_URL ? (import.meta as any).env.VITE_API_BASE_URL as string : '';
  const origin = typeof window !== 'undefined' && window.location && window.location.origin ? window.location.origin : '';
  const base = envUrl || origin || '';
  if (!base) return '/api';
  return base.endsWith('/api') ? base : `${base}/api`;
})();

// Generic API request function
async function apiRequest<T>(
  endpoint: string,
  options: RequestInit = {}
): Promise<ApiResponse<T>> {
  const url = `${API_BASE_URL}${endpoint}`;
  
  const defaultHeaders: Record<string, string> = {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Cache-Control': 'no-cache',
    'Pragma': 'no-cache',
  };

  // Add authorization header if token exists
  const token = localStorage.getItem('authToken');
  if (token) {
    defaultHeaders['Authorization'] = `Bearer ${token}`;
  }

  const config: RequestInit = {
    ...options,
    headers: {
      ...defaultHeaders,
      ...options.headers,
    },
    mode: 'cors',
    credentials: 'omit',
  };

  try {
    const response = await fetch(url, config);

    if (!response.ok) {
      let errorMessage = `HTTP error! status: ${response.status}`;
      
      if (response.status === 401) {
        errorMessage = 'Authentication required. Please log in again.';
      } else if (response.status === 403) {
        errorMessage = 'Access denied. You do not have permission to access this resource.';
      } else if (response.status === 404) {
        errorMessage = 'Resource not found.';
      } else if (response.status >= 500) {
        errorMessage = 'Server error. Please try again later.';
      }
      
      try {
        const errorData = await response.json();
        errorMessage = errorData.message || errorMessage;
      } catch {
        errorMessage = response.statusText || errorMessage;
      }
      throw new Error(errorMessage);
    }

    const contentType = response.headers.get('content-type');
    if (!contentType || !contentType.includes('application/json')) {
      throw new Error('Response is not JSON');
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error('API request failed:', error);
    throw error;
  }
}

// Messages API functions
export const messagesApi = {
  // Send a message
  async sendMessage(data: SendMessageRequest): Promise<ApiResponse<SendMessageResponse>> {
    return apiRequest<SendMessageResponse>('/messages/send', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  },

  // Get messages for a conversation
  async getMessages(params: GetMessagesRequest): Promise<ApiResponse<GetMessagesResponse>> {
    const queryParams = new URLSearchParams();
    queryParams.append('conversation_id', params.conversation_id.toString());
    if (params.page) queryParams.append('page', params.page.toString());
    if (params.limit) queryParams.append('limit', params.limit.toString());
    if (params.before_id) queryParams.append('before_id', params.before_id.toString());
    if (params.after_id) queryParams.append('after_id', params.after_id.toString());

    return apiRequest<GetMessagesResponse>(`/messages/conversation/${params.conversation_id}?${queryParams.toString()}`);
  },

  // Mark messages as read
  async markMessagesAsRead(data: MarkMessagesReadRequest): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/messages/conversation/${data.conversation_id}/read`, {
      method: 'PUT',
      body: JSON.stringify({ message_ids: data.message_ids }),
    });
  },

  // Get unread message count
  async getUnreadCount(): Promise<ApiResponse<{ count: number }>> {
    return apiRequest<{ count: number }>('/messages/unread/count');
  },

  // Search messages
  async searchMessages(params: SearchMessagesRequest): Promise<ApiResponse<SearchMessagesResponse>> {
    const queryParams = new URLSearchParams();
    queryParams.append('q', params.q);
    if (params.conversation_id) queryParams.append('conversation_id', params.conversation_id.toString());
    if (params.page) queryParams.append('page', params.page.toString());
    if (params.limit) queryParams.append('limit', params.limit.toString());

    return apiRequest<SearchMessagesResponse>(`/messages/search?${queryParams.toString()}`);
  },

  // Update a message
  async updateMessage(messageId: number, data: UpdateMessageRequest): Promise<ApiResponse<{ message: Message }>> {
    return apiRequest<{ message: Message }>(`/messages/${messageId}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  },

  // Delete a message
  async deleteMessage(messageId: number): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/messages/${messageId}`, {
      method: 'DELETE',
    });
  },

  // Set typing indicator
  async setTypingIndicator(data: TypingIndicatorRequest): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/messages/conversation/${data.conversation_id}/typing`, {
      method: 'POST',
      body: JSON.stringify({ isTyping: data.isTyping }),
    });
  },
};

// Conversations API functions
export const conversationsApi = {
  // Create a new conversation
  async createConversation(data: CreateConversationRequest): Promise<ApiResponse<CreateConversationResponse>> {
    return apiRequest<CreateConversationResponse>('/conversations', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  },

  // Get user conversations
  async getConversations(params: {
    page?: number;
    limit?: number;
    type?: 'direct' | 'group';
    search?: string;
  } = {}): Promise<ApiResponse<GetConversationsResponse>> {
    const queryParams = new URLSearchParams();
    if (params.page) queryParams.append('page', params.page.toString());
    if (params.limit) queryParams.append('limit', params.limit.toString());
    if (params.type) queryParams.append('type', params.type);
    if (params.search) queryParams.append('search', params.search);

    const endpoint = `/conversations${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
    return apiRequest<GetConversationsResponse>(endpoint);
  },

  // Get conversation details
  async getConversation(conversationId: number): Promise<ApiResponse<{ conversation: Conversation }>> {
    return apiRequest<{ conversation: Conversation }>(`/conversations/${conversationId}`);
  },

  // Add participant to conversation
  async addParticipant(conversationId: number, userId: number): Promise<ApiResponse<{ participant: any }>> {
    return apiRequest<{ participant: any }>(`/conversations/${conversationId}/participants`, {
      method: 'POST',
      body: JSON.stringify({ user_id: userId }),
    });
  },

  // Remove participant from conversation
  async removeParticipant(conversationId: number, userId: number): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/conversations/${conversationId}/participants/${userId}`, {
      method: 'DELETE',
    });
  },

  // Update conversation
  async updateConversation(conversationId: number, data: {
    name?: string;
    description?: string;
  }): Promise<ApiResponse<{ conversation: Conversation }>> {
    return apiRequest<{ conversation: Conversation }>(`/conversations/${conversationId}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    });
  },

  // Delete conversation
  async deleteConversation(conversationId: number): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/conversations/${conversationId}`, {
      method: 'DELETE',
    });
  },

  // Archive conversation
  async archiveConversation(conversationId: number): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/conversations/${conversationId}/archive`, {
      method: 'PUT',
    });
  },

  // Unarchive conversation
  async unarchiveConversation(conversationId: number): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/conversations/${conversationId}/unarchive`, {
      method: 'PUT',
    });
  },

  // Mute conversation
  async muteConversation(conversationId: number): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/conversations/${conversationId}/mute`, {
      method: 'PUT',
    });
  },

  // Unmute conversation
  async unmuteConversation(conversationId: number): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/conversations/${conversationId}/unmute`, {
      method: 'PUT',
    });
  },
};

// Notifications API functions
export const notificationsApi = {
  // Get notifications
  async getNotifications(params: GetNotificationsRequest = {}): Promise<ApiResponse<GetNotificationsResponse>> {
    const queryParams = new URLSearchParams();
    if (params.page) queryParams.append('page', params.page.toString());
    if (params.limit) queryParams.append('limit', params.limit.toString());
    if (params.type) queryParams.append('type', params.type);
    if (params.is_read !== undefined) queryParams.append('is_read', params.is_read.toString());

    const endpoint = `/notifications${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
    return apiRequest<GetNotificationsResponse>(endpoint);
  },

  // Mark notification as read
  async markNotificationAsRead(notificationId: number): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/notifications/${notificationId}/read`, {
      method: 'PUT',
    });
  },

  // Mark all notifications as read
  async markAllAsRead(): Promise<ApiResponse<null>> {
    return apiRequest<null>('/notifications/read-all', {
      method: 'PUT',
    });
  },

  // Delete notification
  async deleteNotification(notificationId: number): Promise<ApiResponse<null>> {
    return apiRequest<null>(`/notifications/${notificationId}`, {
      method: 'DELETE',
    });
  },

  // Get notification statistics
  async getStatistics(): Promise<ApiResponse<NotificationStatistics>> {
    return apiRequest<NotificationStatistics>('/notifications/statistics');
  },
};

// Combined messaging API
export const messagingApi = {
  messages: messagesApi,
  conversations: conversationsApi,
  notifications: notificationsApi,
};

export default messagingApi;

