package com.aiosman.riderpro.data

import android.util.Log
import com.aiosman.riderpro.AppState
import com.aiosman.riderpro.data.api.ApiClient
import com.aiosman.riderpro.data.api.AppConfig
import com.aiosman.riderpro.data.api.CaptchaInfo
import com.aiosman.riderpro.data.api.ChangePasswordRequestBody
import com.aiosman.riderpro.data.api.GoogleRegisterRequestBody
import com.aiosman.riderpro.data.api.LoginUserRequestBody
import com.aiosman.riderpro.data.api.RegisterMessageChannelRequestBody
import com.aiosman.riderpro.data.api.RegisterRequestBody
import com.aiosman.riderpro.data.api.ResetPasswordRequestBody
import com.aiosman.riderpro.data.api.TrtcSignResponseBody
import com.aiosman.riderpro.data.api.UnRegisterMessageChannelRequestBody
import com.aiosman.riderpro.data.api.UpdateNoticeRequestBody
import com.aiosman.riderpro.data.api.UpdateUserLangRequestBody
import com.aiosman.riderpro.entity.AccountFavouriteEntity
import com.aiosman.riderpro.entity.AccountLikeEntity
import com.aiosman.riderpro.entity.AccountProfileEntity
import com.aiosman.riderpro.entity.NoticeCommentEntity
import com.aiosman.riderpro.entity.NoticePostEntity
import com.aiosman.riderpro.entity.NoticeUserEntity
import com.google.gson.annotations.SerializedName
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File

/**
 * 用户资料
 */
data class AccountProfile(
    // 用户ID
    val id: Int,
    // 用户名
    val username: String,
    // 昵称
    val nickname: String,
    // 头像
    val avatar: String,
    // 关注数
    val followingCount: Int,
    // 粉丝数
    val followerCount: Int,
    // 是否关注
    val isFollowing: Boolean,
    // 个人简介
    val bio: String,
    // 主页背景图
    val banner: String?,
    // trtcUserId
    val trtcUserId: String,
) {
    /**
     * 转换为Entity
     */
    fun toAccountProfileEntity(): AccountProfileEntity {
        return AccountProfileEntity(
            id = id,
            followerCount = followerCount,
            followingCount = followingCount,
            nickName = nickname,
            avatar = "${ApiClient.BASE_SERVER}$avatar",
            bio = bio,
            country = "Worldwide",
            isFollowing = isFollowing,
            banner = banner.let {
                if (!it.isNullOrEmpty()) {
                    return@let "${ApiClient.BASE_SERVER}$it"
                }
                null
            },
            trtcUserId = trtcUserId
        )
    }
}

/**
 * 消息关联资料
 */
data class NoticePost(
    // 动态ID
    @SerializedName("id")
    val id: Int,
    // 动态内容
    @SerializedName("textContent")
    // 动态图片
    val textContent: String,
    // 动态图片
    @SerializedName("images")
    val images: List<Image>,
    // 动态时间
    @SerializedName("time")
    val time: String,
) {
    /**
     * 转换为Entity
     */
    fun toNoticePostEntity(): NoticePostEntity {
        return NoticePostEntity(
            id = id,
            textContent = textContent,
            images = images.map {
                it.copy(
                    url = "${ApiClient.BASE_SERVER}${it.url}",
                    thumbnail = "${ApiClient.BASE_SERVER}${it.thumbnail}",
                    blurHash = it.blurHash,
                    width = it.width,
                    height = it.height
                )
            },
            time = ApiClient.dateFromApiString(time)
        )
    }
}

//"comment": {
//    "id": 103,
//    "content": "ppp",
//    "time": "2024-09-08 15:31:37"
//}
data class NoticeComment(
    @SerializedName("id")
    val id: Int,
    @SerializedName("content")
    val content: String,
    @SerializedName("time")
    val time: String,
    @SerializedName("replyComment")
    val replyComment: NoticeComment?,
    @SerializedName("postId")
    val postId: Int,
    @SerializedName("post")
    val post: NoticePost?,
) {
    fun toNoticeCommentEntity(): NoticeCommentEntity {
        return NoticeCommentEntity(
            id = id,
            content = content,
            postId = postId,
            time = ApiClient.dateFromApiString(time),
            replyComment = replyComment?.toNoticeCommentEntity(),
            post = post?.toNoticePostEntity()
        )
    }
}

/**
 * 消息关联用户
 */
data class NoticeUser(
    // 用户ID
    @SerializedName("id")
    val id: Int,
    // 昵称
    @SerializedName("nickName")
    val nickName: String,
    // 头像
    @SerializedName("avatar")
    val avatar: String,
) {
    /**
     * 转换为Entity
     */
    fun toNoticeUserEntity(): NoticeUserEntity {
        return NoticeUserEntity(
            id = id,
            nickName = nickName,
            avatar = "${ApiClient.BASE_SERVER}$avatar",
        )
    }
}

/**
 * 点赞消息通知
 */
data class AccountLike(
    // 是否未读
    @SerializedName("isUnread")
    val isUnread: Boolean,
    // 动态
    @SerializedName("post")
    val post: NoticePost?,
    @SerializedName("comment")
    val comment: NoticeComment?,
    // 点赞用户
    @SerializedName("user")
    val user: NoticeUser,
    // 点赞时间
    @SerializedName("likeTime")
    val likeTime: String,
    // 动态ID
    @SerializedName("postId")
    val postId: Int,
) {
    fun toAccountLikeEntity(): AccountLikeEntity {
        return AccountLikeEntity(
            post = post?.toNoticePostEntity(),
            comment = comment?.toNoticeCommentEntity(),
            user = user.toNoticeUserEntity(),
            likeTime = ApiClient.dateFromApiString(likeTime),
            postId = postId
        )
    }
}

data class AccountFavourite(
    @SerializedName("isUnread")
    val isUnread: Boolean,
    @SerializedName("post")
    val post: NoticePost,
    @SerializedName("user")
    val user: NoticeUser,
    @SerializedName("favoriteTime")
    val favouriteTime: String,
) {
    fun toAccountFavouriteEntity(): AccountFavouriteEntity {
        return AccountFavouriteEntity(
            post = post.toNoticePostEntity(),
            user = user.toNoticeUserEntity(),
            favoriteTime = ApiClient.dateFromApiString(favouriteTime)
        )
    }
}

data class AccountFollow(
    @SerializedName("id")
    val id: Int,
    @SerializedName("username")
    val username: String,
    @SerializedName("nickname")
    val nickname: String,
    @SerializedName("avatar")
    val avatar: String,
    @SerializedName("isUnread")
    val isUnread: Boolean,
    @SerializedName("userId")
    val userId: Int,
    @SerializedName("isFollowing")
    val isFollowing: Boolean,
)

//{
//    "likeCount": 0,
//    "followCount": 0,
//    "favoriteCount": 0
//}
data class AccountNotice(
    @SerializedName("likeCount")
    val likeCount: Int,
    @SerializedName("followCount")
    val followCount: Int,
    @SerializedName("favoriteCount")
    val favoriteCount: Int,
    @SerializedName("commentCount")
    val commentCount: Int,
)


interface AccountService {
    /**
     *  获取登录当前用户的资料
     */
    suspend fun getMyAccountProfile(): AccountProfileEntity

    /**
     *  获取登录的用户认证信息
     */
    suspend fun getMyAccount(): UserAuth

    /**
     * 使用用户名密码登录
     * @param loginName 用户名
     * @param password 密码
     * @param captchaInfo 验证码信息
     */
    suspend fun loginUserWithPassword(
        loginName: String,
        password: String,
        captchaInfo: CaptchaInfo? = null
    ): UserAuth

    /**
     * 使用google登录
     * @param googleId googleId
     */
    suspend fun loginUserWithGoogle(googleId: String): UserAuth

    /**
     * 退出登录
     */
    suspend fun logout()

    /**
     * 更新用户资料
     * @param avatar 头像
     * @param nickName 昵称
     * @param bio 简介
     * @param banner 主页背景图
     */
    suspend fun updateProfile(
        avatar: UploadImage?,
        banner: UploadImage?,
        nickName: String?,
        bio: String?
    )

    /**
     * 注册用户
     * @param loginName 用户名
     * @param password 密码
     */
    suspend fun registerUserWithPassword(loginName: String, password: String)

    /**
     * 使用google账号注册
     * @param idToken googleIdToken
     */
    suspend fun regiterUserWithGoogleAccount(idToken: String)

    /**
     * 修改密码
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     */
    suspend fun changeAccountPassword(oldPassword: String, newPassword: String)

    /**
     * 获取我的点赞通知
     * @param page 页码
     * @param pageSize 每页数量
     */
    suspend fun getMyLikeNotice(page: Int, pageSize: Int): ListContainer<AccountLike>

    /**
     * 获取我的关注通知
     * @param page 页码
     * @param pageSize 每页数量
     */
    suspend fun getMyFollowNotice(page: Int, pageSize: Int): ListContainer<AccountFollow>

    /**
     * 获取我的收藏通知
     * @param page 页码
     * @param pageSize 每页数量
     */
    suspend fun getMyFavouriteNotice(page: Int, pageSize: Int): ListContainer<AccountFavourite>

    /**
     * 获取我的通知信息
     */
    suspend fun getMyNoticeInfo(): AccountNotice

    /**
     * 更新通知信息,更新最后一次查看时间
     * @param payload 通知信息
     */
    suspend fun updateNotice(payload: UpdateNoticeRequestBody)

    /**
     * 注册消息通道
     */
    suspend fun registerMessageChannel(client: String, identifier: String)

    /**
     * 取消注册消息通道
     */
    suspend fun unregisterMessageChannel(client: String, identifier: String)

    /**
     * 重置密码
     */
    suspend fun resetPassword(email: String)

    /**
     * 更新用户额外信息
     */
    suspend fun updateUserExtra(language: String, timeOffset: Int, timezone: String)

    /**
     * 获取腾讯云TRTC签名
     */
    suspend fun getMyTrtcSign(): TrtcSignResponseBody

    suspend fun getAppConfig(): AppConfig
}

class AccountServiceImpl : AccountService {
    override suspend fun getMyAccountProfile(): AccountProfileEntity {
        val resp = ApiClient.api.getMyAccount()
        val body = resp.body() ?: throw ServiceException("Failed to get account")
        return body.data.toAccountProfileEntity()
    }

    override suspend fun getMyAccount(): UserAuth {
        val resp = ApiClient.api.checkToken()
        val body = resp.body() ?: throw ServiceException("Failed to get account")
        AppState.UserId = body.id
        return UserAuth(body.id)
    }

    override suspend fun loginUserWithPassword(
        loginName: String,
        password: String,
        captchaInfo: CaptchaInfo?
    ): UserAuth {
        val resp = ApiClient.api.login(LoginUserRequestBody(
            username = loginName,
            password = password,
            captcha = captchaInfo,
        ))
        Log.d("login", resp.toString())
        if (!resp.isSuccessful) {
            parseErrorResponse(resp.errorBody())?.let {
                throw it.toServiceException()
            }
            throw ServiceException("Failed to register")
        }
        return UserAuth(0, resp.body()?.token)
    }

    override suspend fun loginUserWithGoogle(googleId: String): UserAuth {
        val resp = ApiClient.api.login(LoginUserRequestBody(googleId = googleId))
        val body = resp.body() ?: throw ServiceException("Failed to login")
        return UserAuth(0, body.token)
    }

    override suspend fun regiterUserWithGoogleAccount(idToken: String) {
        val resp = ApiClient.api.registerWithGoogle(GoogleRegisterRequestBody(idToken))
        if (resp.code() != 200) {
            throw ServiceException("Failed to register")
        }
    }

    override suspend fun logout() {
        // do nothing
    }


    fun createMultipartBody(file: File, filename: String, name: String): MultipartBody.Part {
        val requestFile = file.asRequestBody("image/*".toMediaTypeOrNull())
        return MultipartBody.Part.createFormData(name, filename, requestFile)
    }

    override suspend fun updateProfile(
        avatar: UploadImage?,
        banner: UploadImage?,
        nickName: String?,
        bio: String?
    ) {
        val nicknameField: RequestBody? = nickName?.toRequestBody("text/plain".toMediaTypeOrNull())
        val bioField: RequestBody? = bio?.toRequestBody("text/plain".toMediaTypeOrNull())
        val avatarField: MultipartBody.Part? = avatar?.let {
            createMultipartBody(it.file, it.filename, "avatar")
        }
        val bannerField: MultipartBody.Part? = banner?.let {
            createMultipartBody(it.file, it.filename, "banner")
        }
        ApiClient.api.updateProfile(avatarField, bannerField, nicknameField, bioField)
    }

    override suspend fun registerUserWithPassword(loginName: String, password: String) {
        val resp = ApiClient.api.register(RegisterRequestBody(loginName, password))

        if (!resp.isSuccessful) {
            parseErrorResponse(resp.errorBody())?.let {
                throw it.toServiceException()
            }
            throw ServiceException("Failed to register")
        }
    }

    override suspend fun changeAccountPassword(oldPassword: String, newPassword: String) {
        ApiClient.api.changePassword(ChangePasswordRequestBody(oldPassword, newPassword))
    }

    override suspend fun getMyLikeNotice(page: Int, pageSize: Int): ListContainer<AccountLike> {
        val resp = ApiClient.api.getMyLikeNotices(page, pageSize)
        val body = resp.body() ?: throw ServiceException("Failed to get account")
        return body
    }

    override suspend fun getMyFollowNotice(page: Int, pageSize: Int): ListContainer<AccountFollow> {
        val resp = ApiClient.api.getMyFollowNotices(page, pageSize)
        val body = resp.body() ?: throw ServiceException("Failed to get account")
        return body
    }

    override suspend fun getMyFavouriteNotice(
        page: Int,
        pageSize: Int
    ): ListContainer<AccountFavourite> {
        val resp = ApiClient.api.getMyFavouriteNotices(page, pageSize)
        val body = resp.body() ?: throw ServiceException("Failed to get account")
        return body
    }

    override suspend fun getMyNoticeInfo(): AccountNotice {
        val resp = ApiClient.api.getMyNoticeInfo()
        val body = resp.body() ?: throw ServiceException("Failed to get account")
        return body.data
    }

    override suspend fun updateNotice(payload: UpdateNoticeRequestBody) {
        ApiClient.api.updateNoticeInfo(payload)
    }

    override suspend fun registerMessageChannel(client: String, identifier: String) {
        ApiClient.api.registerMessageChannel(RegisterMessageChannelRequestBody(client, identifier))
    }

    override suspend fun unregisterMessageChannel(client: String, identifier: String) {
        ApiClient.api.unRegisterMessageChannel(UnRegisterMessageChannelRequestBody(client, identifier))
    }

    override suspend fun resetPassword(email: String) {
        val resp = ApiClient.api.resetPassword(
            ResetPasswordRequestBody(
                username = email
            )
        )
        if (!resp.isSuccessful) {
            parseErrorResponse(resp.errorBody())?.let {
                throw it.toServiceException()
            }
            throw ServiceException("Failed to reset password")
        }
    }

    override suspend fun updateUserExtra(language: String, timeOffset: Int, timezone: String) {
        ApiClient.api.updateUserExtra(UpdateUserLangRequestBody(language, timeOffset, timezone))
    }

    override suspend fun getMyTrtcSign(): TrtcSignResponseBody {
        val resp = ApiClient.api.getChatSign()
        val body = resp.body() ?: throw ServiceException("Failed to get trtc sign")
        return body.data
    }

    override suspend fun getAppConfig(): AppConfig {
        val resp = ApiClient.api.getAppConfig()
        val body = resp.body() ?: throw ServiceException("Failed to get app config")
        return body.data
    }
}