import type {
  ChatRequestOptions,
  ChatSendOptions,
  UnlockPrivateMessageInput,
} from "@/data/repositories/interfaces";
import {
  ChatHistoryResponse,
  ChatPreviewsResponse,
  ChatSendResponse,
  OpeningMessageRequestSchema,
  OpeningMessageResponse,
  SendMessageRequestSchema,
  UnlockHistoryRequestSchema,
  UnlockHistoryResponse,
  UnlockPrivateRequestSchema,
  UnlockPrivateResponse,
} from "@/data/schemas/chat";
import type { ChatApi } from "@/data/services/api";
import { Result } from "@/utils/result";
import { createClientMessageId } from "@/lib/chat/client_message_id";

export class ChatRemoteDataSource {
  constructor(private readonly api: ChatApi) {}

  async sendMessage(
    characterId: string,
    message: string,
    options?: ChatSendOptions,
  ): Promise<Result<ChatSendResponse>> {
    return Result.wrap(async () => {
      const request = SendMessageRequestSchema.parse({
        characterId,
        clientMessageId: options?.clientMessageId ?? createClientMessageId(),
        message,
        ...(options?.imageId ? { imageId: options.imageId } : {}),
        ...(options?.imageThumbUrl
          ? { imageThumbUrl: options.imageThumbUrl }
          : {}),
        ...(options?.imageMediumUrl
          ? { imageMediumUrl: options.imageMediumUrl }
          : {}),
        ...(options?.imageOriginalUrl
          ? { imageOriginalUrl: options.imageOriginalUrl }
          : {}),
        ...(options?.imageWidth !== undefined
          ? { imageWidth: options.imageWidth }
          : {}),
        ...(options?.imageHeight !== undefined
          ? { imageHeight: options.imageHeight }
          : {}),
        useWebSocket: options?.useWebSocket ?? false,
      });
      return await this.api.sendMessage(request, options);
    });
  }

  async saveOpeningMessage(
    characterId: string,
    openingMessage: string,
    options?: ChatRequestOptions,
  ): Promise<Result<OpeningMessageResponse>> {
    return Result.wrap(() =>
      this.api.saveOpeningMessage(
        OpeningMessageRequestSchema.parse({ characterId, openingMessage }),
        options,
      ),
    );
  }

  async getPreviews(
    options?: ChatRequestOptions,
  ): Promise<Result<ChatPreviewsResponse>> {
    return Result.wrap(() => this.api.getPreviews(options));
  }

  async getHistory(
    characterId: string,
    limit = 50,
    offset = 0,
    options?: ChatRequestOptions,
  ): Promise<Result<ChatHistoryResponse>> {
    return Result.wrap(() =>
      this.api.getHistory(characterId, limit, offset, options),
    );
  }

  async unlockPrivateMessage(
    input: UnlockPrivateMessageInput,
    options?: ChatRequestOptions,
  ): Promise<Result<UnlockPrivateResponse>> {
    return Result.wrap(() =>
      this.api.unlockPrivateMessage(
        UnlockPrivateRequestSchema.parse(input),
        options,
      ),
    );
  }

  async unlockHistory(
    characterId: string,
    options?: ChatRequestOptions,
  ): Promise<Result<UnlockHistoryResponse>> {
    return Result.wrap(() =>
      this.api.unlockHistory(
        UnlockHistoryRequestSchema.parse({ characterId }),
        options,
      ),
    );
  }
}
