import { api } from './api';
import type { NextcloudTalkData, NextcloudConnectData, NextcloudPollData, NextcloudMessage, NextcloudRoomListData, NextcloudUser, NextcloudReaction, NextcloudPoll } from '../types/nextcloud.types';

interface ApiResponse<T> {
  success: boolean;
  data: T;
}

export const nextcloudApi = {
  getConversations(): Promise<NextcloudTalkData> {
    return api
      .get<ApiResponse<NextcloudTalkData>>('/api/nextcloud/talk')
      .then((r) => r.data.data);
  },

  connect(): Promise<NextcloudConnectData> {
    return api
      .post<ApiResponse<NextcloudConnectData>>('/api/nextcloud/talk/connect')
      .then((r) => r.data.data);
  },

  poll(pollToken: string, pollEndpoint: string): Promise<NextcloudPollData> {
    return api
      .post<ApiResponse<NextcloudPollData>>('/api/nextcloud/talk/poll', { pollToken, pollEndpoint })
      .then((r) => r.data.data);
  },

  disconnect(): Promise<void> {
    return api
      .delete('/api/nextcloud/talk/connect')
      .then(() => undefined);
  },

  getRooms(): Promise<NextcloudRoomListData> {
    return api
      .get<ApiResponse<NextcloudRoomListData>>('/api/nextcloud/talk/rooms')
      .then((r) => r.data.data);
  },

  getMessages(
    token: string,
    options?: { lookIntoFuture?: boolean; lastKnownMessageId?: number; timeout?: number },
    signal?: AbortSignal,
  ): Promise<NextcloudMessage[]> {
    const params: Record<string, any> = {};
    if (options?.lookIntoFuture) {
      params.lookIntoFuture = '1';
      params.lastKnownMessageId = options.lastKnownMessageId ?? 0;
      params.timeout = options.timeout ?? 25;
    }
    return api
      .get<ApiResponse<NextcloudMessage[]>>(`/api/nextcloud/talk/rooms/${encodeURIComponent(token)}/messages`, {
        params,
        signal,
        ...(options?.lookIntoFuture && { timeout: ((options.timeout ?? 25) + 7) * 1000 }),
      })
      .then((r) => r.data.data);
  },

  sendMessage(token: string, message: string, replyTo?: number): Promise<void> {
    return api
      .post(`/api/nextcloud/talk/rooms/${encodeURIComponent(token)}/messages`, { message, ...(replyTo !== undefined ? { replyTo } : {}) })
      .then(() => undefined);
  },

  markAsRead(token: string): Promise<void> {
    return api
      .post(`/api/nextcloud/talk/rooms/${encodeURIComponent(token)}/read`)
      .then(() => undefined);
  },

  uploadFile(
    token: string,
    file: File,
    onProgress?: (pct: number) => void,
  ): Promise<void> {
    const formData = new FormData();
    formData.append('file', file);
    return api
      .post(`/api/nextcloud/talk/rooms/${encodeURIComponent(token)}/files`, formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
        onUploadProgress: onProgress
          ? (e) => {
              if (e.total) onProgress(Math.round((e.loaded / e.total) * 100));
            }
          : undefined,
      })
      .then(() => undefined);
  },

  getFileDownloadUrl(fileId: number | string, filePath?: string): string {
    const base = `/api/nextcloud/talk/files/${fileId}/download`;
    return filePath ? `${base}?path=${encodeURIComponent(filePath)}` : base;
  },

  getFilePreviewUrl(fileId: number | string, w = 400, h = 400): string {
    return `/api/nextcloud/talk/files/${fileId}/preview?w=${w}&h=${h}`;
  },

  searchUsers(query: string): Promise<NextcloudUser[]> {
    return api
      .get<ApiResponse<NextcloudUser[]>>(`/api/nextcloud/talk/users`, { params: { search: query } })
      .then((r) => r.data.data);
  },

  createRoom(roomType: number, invite: string, roomName?: string): Promise<{ token: string }> {
    return api
      .post<ApiResponse<{ token: string }>>('/api/nextcloud/talk/rooms', { roomType, invite, ...(roomName ? { roomName } : {}) })
      .then((r) => r.data.data);
  },

  addReaction(token: string, messageId: number, reaction: string): Promise<void> {
    return api
      .post(`/api/nextcloud/talk/rooms/${encodeURIComponent(token)}/messages/${messageId}/reactions`, { reaction })
      .then(() => undefined);
  },

  removeReaction(token: string, messageId: number, reaction: string): Promise<void> {
    return api
      .delete(`/api/nextcloud/talk/rooms/${encodeURIComponent(token)}/messages/${messageId}/reactions`, { params: { reaction } })
      .then(() => undefined);
  },

  getReactions(token: string, messageId: number): Promise<Record<string, NextcloudReaction[]>> {
    return api
      .get<ApiResponse<Record<string, NextcloudReaction[]>>>(`/api/nextcloud/talk/rooms/${encodeURIComponent(token)}/messages/${messageId}/reactions`)
      .then((r) => r.data.data);
  },

  getPollDetails(token: string, pollId: number): Promise<NextcloudPoll> {
    return api
      .get<ApiResponse<NextcloudPoll>>(`/api/nextcloud/talk/rooms/${encodeURIComponent(token)}/polls/${pollId}`)
      .then((r) => r.data.data);
  },
};
