package com.aiosman.ravenow.data.api

import com.aiosman.ravenow.data.AccountFavourite
import com.aiosman.ravenow.data.AccountFollow
import com.aiosman.ravenow.data.AccountLike
import com.aiosman.ravenow.data.AccountNotice
import com.aiosman.ravenow.data.AccountProfile
import com.aiosman.ravenow.data.Agent
import com.aiosman.ravenow.data.Comment
import com.aiosman.ravenow.data.DataContainer
import com.aiosman.ravenow.data.ListContainer
import com.aiosman.ravenow.data.Moment
import com.aiosman.ravenow.data.Room
import com.aiosman.ravenow.entity.ChatNotification
import com.aiosman.ravenow.data.membership.MembershipConfigData
import com.aiosman.ravenow.data.membership.ValidateData
import com.aiosman.ravenow.data.membership.ValidateProductRequestBody
import com.google.gson.annotations.SerializedName
import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
import retrofit2.http.Multipart
import retrofit2.http.PATCH
import retrofit2.http.POST
import retrofit2.http.Part
import retrofit2.http.Path
import retrofit2.http.Query

data class RegisterRequestBody(
    @SerializedName("username")
    val username: String,
    @SerializedName("password")
    val password: String
)
data class AgentMomentRequestBody(
    @SerializedName("generateText")
    val generateText: String,
    @SerializedName("sessionId")
    val sessionId: String
)

data class SingleChatRequestBody(
    @SerializedName("agentOpenId")
    val agentOpenId: String? = null,
    @SerializedName("agentTrtcId")
    val agentTrtcId: String? = null,
)

data class GroupChatRequestBody(
    @SerializedName("trtcGroupId")
    val trtcGroupId: String,
)


data class SendChatAiRequestBody(
    @SerializedName("trtcGroupId")
    val trtcGroupId: String? = null,
    @SerializedName("fromTrtcUserId")
    val fromTrtcUserId: String? = null,
    @SerializedName("toTrtcUserId")
    val toTrtcUserId: String? = null,
    @SerializedName("message")
    val message: String,
    @SerializedName("skipTrtc")
    val skipTrtc: Boolean? = true,

)


data class CreateGroupChatRequestBody(
    @SerializedName("name")
    val name: String,
    @SerializedName("userIds")
    val userIds: List<String>,
    @SerializedName("promptIds")
    val promptIds: List<String>,
    )

data class JoinGroupChatRequestBody(
    @SerializedName("trtcId")
    val trtcId: String,
)

data class LoginUserRequestBody(
    @SerializedName("username")
    val username: String? = null,
    @SerializedName("password")
    val password: String? = null,
    @SerializedName("googleId")
    val googleId: String? = null,
    @SerializedName("captcha")
    val captcha: CaptchaInfo? = null,
)

data class GuestLoginRequestBody(
    @SerializedName("deviceID")
    val deviceId: String,
    @SerializedName("platform")
    val platform: String = "android",
    @SerializedName("deviceInfo")
    val deviceInfo: String? = null,
    @SerializedName("userAgent")
    val userAgent: String? = null,
    @SerializedName("ipAddress")
    val ipAddress: String? = null
)

data class GoogleRegisterRequestBody(
    @SerializedName("idToken")
    val idToken: String
)

data class AuthResult(
    @SerializedName("code")
    val code: Int,
    @SerializedName("expire")
    val expire: String,
    @SerializedName("token")
    val token: String
)

data class ValidateTokenResult(
    @SerializedName("id")
    val id: Int,
)

data class CommentRequestBody(
    @SerializedName("content")
    val content: String,
    @SerializedName("parentCommentId")
    val parentCommentId: Int? = null,
    @SerializedName("replyUserId")
    val replyUserId: Int? = null,
    @SerializedName("replyCommentId")
    val replyCommentId: Int? = null,
)

data class ChangePasswordRequestBody(
    @SerializedName("currentPassword")
    val oldPassword: String = "",
    @SerializedName("newPassword")
    val newPassword: String = ""
)

data class UpdateNoticeRequestBody(
    @SerializedName("lastLookLikeTime")
    val lastLookLikeTime: String? = null,
    @SerializedName("lastLookFollowTime")
    val lastLookFollowTime: String? = null,
    @SerializedName("lastLookFavoriteTime")
    val lastLookFavouriteTime: String? = null
)

data class RegisterMessageChannelRequestBody(
    @SerializedName("client")
    val client: String,
    @SerializedName("identifier")
    val identifier: String,
)

data class UnRegisterMessageChannelRequestBody(
    @SerializedName("client")
    val client: String,
    @SerializedName("identifier")
    val identifier: String,
)
data class ResetPasswordRequestBody(
    @SerializedName("username")
    val username: String,
)

data class UpdateUserLangRequestBody(
    @SerializedName("language")
    val lang: String,
    @SerializedName("timeOffset")
    val timeOffset: Int,
    @SerializedName("timezone")
    val timezone: String,
)

data class TrtcSignResponseBody(
    @SerializedName("sig")
    val sig: String,
    @SerializedName("userId")
    val userId: String,
)

data class AppConfig(
    @SerializedName("trtcAppId")
    val trtcAppId: Int,
)

data class DictItem(
    @SerializedName("key")
    val key: String,
    @SerializedName("value")
    val value: Any,
    @SerializedName("desc")
    val desc: String,
)

data class CaptchaRequestBody(
    @SerializedName("source")
    val source: String,
)

data class CaptchaResponseBody(
    @SerializedName("id")
    val id: Int,
    @SerializedName("thumb_base64")
    val thumbBase64: String,
    @SerializedName("master_base64")
    val masterBase64: String,
    @SerializedName("count")
    val count: Int,
)

data class CheckLoginCaptchaRequestBody(
    @SerializedName("username")
    val username: String,
)

data class GenerateLoginCaptchaRequestBody(
    @SerializedName("username")
    val username: String,
)

data class DotPosition(
    @SerializedName("index")
    val index: Int,
    @SerializedName("x")
    val x: Int,
    @SerializedName("y")
    val y: Int,
)

data class CaptchaInfo(
    @SerializedName("id")
    val id: Int,
    @SerializedName("dot")
    val dot: List<DotPosition>
)


data class UpdateChatNotificationRequestBody(
    @SerializedName("targetUserId")
    val targetUserId: Int,
    @SerializedName("strategy")
    val strategy: String,
)


data class CreateReportRequestBody(
    @SerializedName("reportType")
    val reportType: String,
    @SerializedName("reportId")
    val reportId: Int,
    @SerializedName("reason")
    val reason: Int,
    @SerializedName("extra")
    val extra: String,
    @SerializedName("base64Images")
    val base64Images: List<String>,
)

data class RemoveAccountRequestBody(
    @SerializedName("password")
    val password: String,
)

data class CategoryTemplate(
    @SerializedName("id")
    val id: Int,
    @SerializedName("name")
    val name: String,
    @SerializedName("description")
    val description: String,
    @SerializedName("avatar")
    val avatar: String,
    @SerializedName("parentId")
    val parentId: Int?,
    @SerializedName("parent")
    val parent: CategoryTemplate?,
    @SerializedName("children")
    val children: List<CategoryTemplate>?,
    @SerializedName("sort")
    val sort: Int,
    @SerializedName("isActive")
    val isActive: Boolean,
    @SerializedName("promptCount")
    val promptCount: Int?,
    @SerializedName("createdAt")
    val createdAt: String,
    @SerializedName("updatedAt")
    val updatedAt: String
)

data class CategoryListResponse(
    @SerializedName("page")
    val page: Int,
    @SerializedName("pageSize")
    val pageSize: Int,
    @SerializedName("total")
    val total: Int,
    @SerializedName("list")
    val list: List<CategoryTemplate>
)

interface RaveNowAPI {
    @GET("membership/config")
    @retrofit2.http.Headers("X-Requires-Auth: true")
    suspend fun getMembershipConfig(): Response<DataContainer<MembershipConfigData>>

    @POST("membership/android/product/validate")
    @retrofit2.http.Headers("X-Requires-Auth: true")
    suspend fun validateAndroidProduct(
        @Body body: ValidateProductRequestBody
    ): Response<DataContainer<ValidateData>>
    @POST("register")
    suspend fun register(@Body body: RegisterRequestBody): Response<Unit>

    @POST("login")
    suspend fun login(@Body body: LoginUserRequestBody): Response<AuthResult>

    @POST("guest/login")
    suspend fun guestLogin(@Body body: GuestLoginRequestBody): Response<AuthResult>

    @GET("auth/token")
    suspend fun checkToken(): Response<ValidateTokenResult>

    @GET("auth/refresh_token")
    suspend fun refreshToken(
        @Query("token") token: String
    ): Response<AuthResult>

    @GET("posts")
    suspend fun getPosts(
        @Query("page") page: Int = 1,
        @Query("pageSize") pageSize: Int = 20,
        @Query("timelineId") timelineId: Int? = null,
        @Query("authorId") authorId: Int? = null,
        @Query("contentSearch") contentSearch: String? = null,
        @Query("postUser") postUser: Int? = null,
        @Query("trend") trend: String? = null,
        @Query("favouriteUserId") favouriteUserId: Int? = null,
        @Query("explore") explore: String? = null,
    ): Response<ListContainer<Moment>>

    @Multipart
    @POST("posts")
    suspend fun createPost(
        @Part image: List<MultipartBody.Part>,
        @Part("textContent") textContent: RequestBody,
    ): Response<DataContainer<Moment>>

    @GET("post/{id}")
    suspend fun getPost(
        @Path("id") id: Int
    ): Response<DataContainer<Moment>>

    @POST("post/{id}/like")
    suspend fun likePost(
        @Path("id") id: Int
    ): Response<Unit>

    @POST("post/{id}/dislike")
    suspend fun dislikePost(
        @Path("id") id: Int
    ): Response<Unit>

    @POST("post/{id}/favorite")
    suspend fun favoritePost(
        @Path("id") id: Int
    ): Response<Unit>

    @POST("post/{id}/unfavorite")
    suspend fun unfavoritePost(
        @Path("id") id: Int
    ): Response<Unit>

    @POST("post/{id}/comment")
    suspend fun createComment(
        @Path("id") id: Int,
        @Body body: CommentRequestBody
    ): Response<DataContainer<Comment>>

    @POST("comment/{id}/like")
    suspend fun likeComment(
        @Path("id") id: Int
    ): Response<Unit>

    @POST("comment/{id}/dislike")
    suspend fun dislikeComment(
        @Path("id") id: Int
    ): Response<Unit>

    @POST("comment/{id}/read")
    suspend fun updateReadStatus(
        @Path("id") id: Int
    ): Response<Unit>


    @GET("comments")
    suspend fun getComments(
        @Query("page") page: Int = 1,
        @Query("postId") postId: Int? = null,
        @Query("pageSize") pageSize: Int = 20,
        @Query("postUser") postUser: Int? = null,
        @Query("selfNotice") selfNotice: Int? = 0,
        @Query("order") order: String? = null,
        @Query("parentCommentId") parentCommentId: Int? = null,
    ): Response<ListContainer<Comment>>

    @GET("account/my")
    suspend fun getMyAccount(): Response<DataContainer<AccountProfile>>

    @Multipart
    @PATCH("account/my/profile")
    suspend fun updateProfile(
        @Part avatar: MultipartBody.Part?,
        @Part banner: MultipartBody.Part?,
        @Part("nickname") nickname: RequestBody?,
        @Part("bio") bio: RequestBody?,
    ): Response<Unit>

    @POST("account/my/password")
    suspend fun changePassword(
        @Body body: ChangePasswordRequestBody
    ): Response<Unit>

    @GET("account/my/notice/like")
    suspend fun getMyLikeNotices(
        @Query("page") page: Int = 1,
        @Query("pageSize") pageSize: Int = 20,
    ): Response<ListContainer<AccountLike>>

    @GET("account/my/notice/follow")
    suspend fun getMyFollowNotices(
        @Query("page") page: Int = 1,
        @Query("pageSize") pageSize: Int = 20,
    ): Response<ListContainer<AccountFollow>>

    @GET("account/my/notice/favourite")
    suspend fun getMyFavouriteNotices(
        @Query("page") page: Int = 1,
        @Query("pageSize") pageSize: Int = 20,
    ): Response<ListContainer<AccountFavourite>>

    @GET("account/my/notice")
    suspend fun getMyNoticeInfo(): Response<DataContainer<AccountNotice>>

    @POST("account/my/notice")
    suspend fun updateNoticeInfo(
        @Body body: UpdateNoticeRequestBody
    ): Response<Unit>

    @POST("account/my/messaging")
    suspend fun registerMessageChannel(
        @Body body: RegisterMessageChannelRequestBody
    ): Response<Unit>

    @POST("account/my/messaging/unregister")
    suspend fun unRegisterMessageChannel(
        @Body body: UnRegisterMessageChannelRequestBody
    ): Response<Unit>

    @GET("profile/{id}")
    suspend fun getAccountProfileById(
        @Path("id") id: Int
    ): Response<DataContainer<AccountProfile>>

    @GET("profile/trtc/{id}")
    suspend fun getAccountProfileByTrtcUserId(
        @Path("id") id: String,
        @Query("includeAI") includeAI: Int
    ): Response<DataContainer<AccountProfile>>


    @GET("profile/aichat/profile/{id}")
    suspend fun getAccountProfileByOpenId(
        @Path("id") id: String
    ): Response<DataContainer<AccountProfile>>

    @POST("user/{id}/follow")
    suspend fun followUser(
        @Path("id") id: Int
    ): Response<Unit>

    @POST("user/{id}/unfollow")
    suspend fun unfollowUser(
        @Path("id") id: Int
    ): Response<Unit>

    @GET("users")
    suspend fun getUsers(
        @Query("page") page: Int = 1,
        @Query("pageSize") pageSize: Int = 20,
        @Query("nickname") search: String? = null,
        @Query("followerId") followerId: Int? = null,
        @Query("followingId") followingId: Int? = null,
        @Query("includeAI") includeAI: Boolean? = false,
        @Query("chatSessionIdNotNull") chatSessionIdNotNull: Boolean? = true,
    ): Response<ListContainer<AccountProfile>>

    @POST("register/google")
    suspend fun registerWithGoogle(@Body body: GoogleRegisterRequestBody): Response<AuthResult>

    @DELETE("post/{id}")
    suspend fun deletePost(
        @Path("id") id: Int
    ): Response<Unit>

    @DELETE("comment/{id}")
    suspend fun deleteComment(
        @Path("id") id: Int
    ): Response<Unit>

    @POST("account/my/password/reset")
    suspend fun resetPassword(
        @Body body: ResetPasswordRequestBody
    ): Response<Unit>

    @GET("comment/{id}")
    suspend fun getComment(
        @Path("id") id: Int
    ): Response<DataContainer<Comment>>

    @PATCH("account/my/extra")
    suspend fun updateUserExtra(
        @Body body: UpdateUserLangRequestBody
    ): Response<Unit>

    @GET("account/my/chat/sign")
    suspend fun getChatSign(): Response<DataContainer<TrtcSignResponseBody>>

    @GET("app/info")
    suspend fun getAppConfig(): Response<DataContainer<AppConfig>>

    @GET("dict")
    suspend fun getDict(
        @Query("key") key: String
    ): Response<DataContainer<DictItem>>

    @GET("dicts")
    suspend fun getDicts(
        @Query("keys") keys: String
    ): Response<ListContainer<DictItem>>

    @POST("captcha/generate")
    suspend fun generateCaptcha(
        @Body body: CaptchaRequestBody
    ): Response<DataContainer<CaptchaResponseBody>>

    @POST("login/needCaptcha")
    suspend fun checkLoginCaptcha(
        @Body body: CheckLoginCaptchaRequestBody
    ): Response<DataContainer<Boolean>>

    @POST("captcha/login/generate")
    suspend fun generateLoginCaptcha(
        @Body body: GenerateLoginCaptchaRequestBody
    ): Response<DataContainer<CaptchaResponseBody>>

    @GET("chat/notification")
    suspend fun getChatNotification(
        @Query("targetTrtcId") targetTrtcId: String
    ): Response<DataContainer<ChatNotification>>

    @POST("chat/notification")
    suspend fun updateChatNotification(
        @Body body: UpdateChatNotificationRequestBody
    ): Response<DataContainer<ChatNotification>>

    @POST("reports")
    suspend fun createReport(
        @Body body: CreateReportRequestBody
    ): Response<Unit>

    @POST("account/my/delete")
    suspend fun deleteAccount(
        @Body body: RemoveAccountRequestBody
    ): Response<Unit>

    @GET("outside/prompts")
    suspend fun getAgent(
        @Query("page") page: Int = 1,
        @Query("pageSize") pageSize: Int = 20,
        @Query("withWorkflow") withWorkflow: Int = 1,
        @Query("authorId") authorId: Int? = null,
        @Query("categoryIds") categoryIds: List<Int>? = null,
    ): Response<DataContainer<ListContainer<Agent>>>

    @GET("outside/my/prompts")
    suspend fun getMyAgent(
        @Query("page") page: Int = 1,
        @Query("pageSize") pageSize: Int = 20,
        @Query("withWorkflow") withWorkflow: Int = 1,
    ): Response<ListContainer<Agent>>

    @Multipart
    @POST("outside/prompts")
    suspend fun createAgent(
        @Part avatar: MultipartBody.Part?,
        @Part("title") title: RequestBody?,
        @Part("value") value: RequestBody?,
        @Part("desc") desc: RequestBody?,
        @Part("workflowId") workflowId: RequestBody?,
        @Part("public") isPublic: RequestBody?,
        @Part("breakMode") breakMode: RequestBody?,
        @Part("useWorkflow") useWorkflow: RequestBody?,
        @Part("workflowInputs") workflowInputs: RequestBody?,
    ): Response<DataContainer<Agent>>


    @POST("generate/postText")
    suspend fun agentMoment(@Body body: AgentMomentRequestBody): Response<DataContainer<String>>

    @GET("outside/rooms/open")
    suspend fun createGroupChatAi(@Query("trtcGroupId") trtcGroupId: String): Response<DataContainer<Unit>>

    @POST("outside/rooms/create-single-chat")
    suspend fun createSingleChat(@Body body: SingleChatRequestBody): Response<DataContainer<Unit>>

    @POST("outside/rooms/message")
    suspend fun sendChatAiMessage(@Body body: SendChatAiRequestBody): Response<DataContainer<Unit>>

    @POST("outside/rooms")
    suspend fun createGroupChat(@Body body: CreateGroupChatRequestBody): Response<DataContainer<Unit>>

    @GET("outside/rooms")
    suspend fun getRooms(@Query("page") page: Int = 1,
                         @Query("pageSize") pageSize: Int = 20,
                         @Query("isRecommended") isRecommended: Int = 1,
    ): Response<ListContainer<Room>>

    @GET("outside/rooms/detail")
    suspend fun getRoomDetail(@Query("trtcId") trtcId: String,
    ): Response<DataContainer<Room>>

    @POST("outside/rooms/join")
    suspend fun joinRoom(@Body body: JoinGroupChatRequestBody,
    ): Response<DataContainer<Room>>

    @GET("outside/categories")
    suspend fun getCategories(
        @Query("page") page: Int? = null,
        @Query("pageSize") pageSize: Int? = null,
        @Query("parentId") parentId: Int? = null,
        @Query("isActive") isActive: Boolean? = null,
        @Query("name") name: String? = null,
        @Query("withChildren") withChildren: Boolean? = null,
        @Query("withParent") withParent: Boolean? = null,
        @Query("withCount") withCount: Boolean? = null,
        @Query("hideEmpty") hideEmpty: Boolean? = null
    ): Response<DataContainer<CategoryListResponse>>

    @GET("outside/categories/tree")
    suspend fun getCategoryTree(
        @Query("withCount") withCount: Boolean? = null,
        @Query("hideEmpty") hideEmpty: Boolean? = null
    ): Response<DataContainer<List<CategoryTemplate>>>

    @GET("outside/categories/{id}")
    suspend fun getCategoryById(
        @Path("id") id: Int
    ): Response<DataContainer<CategoryTemplate>>

    @GET("outside/prompts")
    suspend fun getPromptsByCategory(
        @Query("categoryIds") categoryIds: List<Int>? = null,
        @Query("categoryName") categoryName: String? = null,
        @Query("uncategorized") uncategorized: String? = null,
        @Query("page") page: Int? = null,
        @Query("pageSize") pageSize: Int? = null
    ): Response<ListContainer<Agent>>

}

