package com.aiosman.ravenow.entity

import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.aiosman.ravenow.AppStore
import com.aiosman.ravenow.data.Agent
import com.aiosman.ravenow.data.ListContainer
import com.aiosman.ravenow.data.AgentService
import com.aiosman.ravenow.data.DataContainer
import com.aiosman.ravenow.data.ServiceException
import com.aiosman.ravenow.data.UploadImage
import com.aiosman.ravenow.data.api.ApiClient
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
import java.io.IOException

/**
 * 智能体
 */
suspend fun createAgent(
    title: String,
    desc: String,
    avatar: UploadImage? = null,
    workflowId: Int = 1,
    isPublic: Boolean = true,
    breakMode: Boolean = false,
    useWorkflow: Boolean = true,
): AgentEntity {
    val textTitle = title.toRequestBody("text/plain".toMediaTypeOrNull())
    val textDesc = desc.toRequestBody("text/plain".toMediaTypeOrNull())
    val workflowIdRequestBody =
        workflowId.toString().toRequestBody("text/plain".toMediaTypeOrNull())
    val isPublicRequestBody = isPublic.toString().toRequestBody("text/plain".toMediaTypeOrNull())
    val breakModeRequestBody = breakMode.toString().toRequestBody("text/plain".toMediaTypeOrNull())
    val useWorkflowRequestBody =
        useWorkflow.toString().toRequestBody("text/plain".toMediaTypeOrNull())
    val workflowInputsValue = "{\"si\":\"$desc\"}"
    val workflowInputsRequestBody =
        workflowInputsValue.toRequestBody("text/plain".toMediaTypeOrNull())

    val avatarField: MultipartBody.Part? = avatar?.let {
        createMultipartBody(it.file, it.filename, "avatar")
    }
    val response = ApiClient.api.createAgent(
        avatarField,
        textTitle,
        textDesc,
        textDesc,
        workflowIdRequestBody,
        isPublicRequestBody,
        breakModeRequestBody,
        useWorkflowRequestBody,
        workflowInputsRequestBody
    )
    val body = response.body()?.data ?: throw ServiceException("Failed to create agent")
    return body.toAgentEntity()

}

/**
 * 智能体信息分页加载器
 */
class AgentPagingSource(
    private val agentRemoteDataSource: AgentRemoteDataSource,
    private val authorId: Int? = null
) : PagingSource<Int, AgentEntity>() {
    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, AgentEntity> {
        return try {
            val currentPage = params.key ?: 1
            val users = agentRemoteDataSource.getAgent(
                pageNumber = currentPage,
                authorId = authorId
            )
            LoadResult.Page(
                data = users?.list ?: listOf(),
                prevKey = if (currentPage == 1) null else currentPage - 1,
                nextKey = if (users?.list?.isNotEmpty() == true) users.page + 1 else  null
            )
        } catch (exception: IOException) {
            return LoadResult.Error(exception)
        }
    }

    override fun getRefreshKey(state: PagingState<Int, AgentEntity>): Int? {
        return state.anchorPosition
    }

}

/**
 * 智能体搜索分页加载器（按标题关键字）
 */
class AgentSearchPagingSource(
    private val agentRemoteDataSource: AgentRemoteDataSource,
    private val keyword: String,
) : PagingSource<Int, AgentEntity>() {
    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, AgentEntity> {
        return try {
            val currentPage = params.key ?: 1
            val agents = agentRemoteDataSource.searchAgentByTitle(
                pageNumber = currentPage,
                title = keyword
            )
            LoadResult.Page(
                data = agents?.list ?: listOf(),
                prevKey = if (currentPage == 1) null else currentPage - 1,
                nextKey = if (agents?.list?.isNotEmpty() == true) currentPage + 1 else null
            )
        } catch (exception: IOException) {
            LoadResult.Error(exception)
        }
    }

    override fun getRefreshKey(state: PagingState<Int, AgentEntity>): Int? {
        return state.anchorPosition
    }
}


class AgentRemoteDataSource(
    private val agentService: AgentService,
) {
    suspend fun getAgent(
        pageNumber: Int,
        authorId: Int? = null
    ): ListContainer<AgentEntity>? {
        return agentService.getAgent(
            pageNumber = pageNumber,
            authorId = authorId
        )
    }

    suspend fun searchAgentByTitle(
        pageNumber: Int,
        title: String
    ): ListContainer<AgentEntity>? {
        return agentService.searchAgentByTitle(
            pageNumber = pageNumber,
            title = title
        )
    }
}

class AgentServiceImpl() : AgentService {
    val agentBackend = AgentBackend()

    override suspend fun getAgent(
        pageNumber: Int,
        pageSize: Int,
        authorId: Int?
    ): ListContainer<AgentEntity>? {
        return agentBackend.getAgent(
            pageNumber = pageNumber,
            authorId = authorId
        )
    }

    override suspend fun searchAgentByTitle(
        pageNumber: Int,
        pageSize: Int,
        title: String
    ): ListContainer<AgentEntity>? {
        return agentBackend.searchAgentByTitle(
            pageNumber = pageNumber,
            title = title
        )
    }
}

class AgentBackend {
    val DataBatchSize = 20
    suspend fun getAgent(
        pageNumber: Int,
        authorId: Int? = null
    ): ListContainer<AgentEntity>? {
        // 如果是游客模式且获取我的Agent（authorId为null），返回空列表
        if (authorId == null && AppStore.isGuest) {
            return ListContainer(
                total = 0,
                page = pageNumber,
                pageSize = DataBatchSize,
                list = emptyList()
            )
        }
        
        val resp = if (authorId != null) {
            ApiClient.api.getAgent(
                page = pageNumber,
                pageSize = DataBatchSize,
                authorId = authorId
            )
        } else {
            ApiClient.api.getMyAgent(
                page = pageNumber,
                pageSize = DataBatchSize
            )
        }

        val body = resp.body() ?: return null

        // 处理不同的返回类型
        return if (authorId != null) {
            // getAgent 返回 DataContainer<ListContainer<Agent>>
            val dataContainer =
                body as DataContainer<ListContainer<Agent>>
            val listContainer = dataContainer.data
            ListContainer(
                total = listContainer.total,
                page = pageNumber,
                pageSize = DataBatchSize,
                list = listContainer.list.map { it.toAgentEntity() }
            )
        } else {
            // getMyAgent 返回 ListContainer<Agent>
            val listContainer =
                body as ListContainer<Agent>
            ListContainer(
                total = listContainer.total,
                page = pageNumber,
                pageSize = DataBatchSize,
                list = listContainer.list.map { it.toAgentEntity() }
            )
        }
    }

    suspend fun searchAgentByTitle(
        pageNumber: Int,
        title: String
    ): ListContainer<AgentEntity>? {
        val resp = ApiClient.api.getAgent(
            page = pageNumber,
            pageSize = DataBatchSize,
            withWorkflow = 1,
            title = title
        )
        val body = resp.body() ?: return null
        val dataContainer = body as DataContainer<ListContainer<Agent>>
        val listContainer = dataContainer.data
        return ListContainer(
            total = listContainer.total,
            page = pageNumber,
            pageSize = DataBatchSize,
            list = listContainer.list.map { it.toAgentEntity() }
        )
    }
}

data class AgentEntity(
    //val author: String,
    val avatar: String,
    val breakMode: Boolean,
    val createdAt: String,
    val desc: String,
    val id: Int,
    val isPublic: Boolean,
    val openId: String,
    //val profile: ProfileEntity,
    val title: String,
    val updatedAt: String,
    val useCount: Int,
)


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

class AgentLoaderExtraArgs(
    val authorId: Int? = null
)

class AgentLoader : DataLoader<AgentEntity, AgentLoaderExtraArgs>() {
    override suspend fun fetchData(
        page: Int,
        pageSize: Int,
        extra: AgentLoaderExtraArgs
    ): ListContainer<AgentEntity> {
        // 如果是游客模式且获取我的Agent（authorId为null），返回空列表
        if (extra.authorId == null && AppStore.isGuest) {
            return ListContainer(
                total = 0,
                page = page,
                pageSize = pageSize,
                list = emptyList()
            )
        }
        
        val result = if (extra.authorId != null) {
            ApiClient.api.getAgent(
                page = page,
                pageSize = pageSize,
                authorId = extra.authorId
            )
        } else {
            ApiClient.api.getMyAgent(
                page = page,
                pageSize = pageSize
            )
        }

        val body = result.body() ?: throw ServiceException("Failed to get agent")

        return if (extra.authorId != null) {
            // getAgent 返回 DataContainer<ListContainer<Agent>>
            val dataContainer = body as DataContainer<ListContainer<Agent>>
            val listContainer = dataContainer.data
            ListContainer(
                list = listContainer.list.map { it.toAgentEntity() },
                total = listContainer.total,
                page = page,
                pageSize = pageSize
            )
        } else {
            // getMyAgent 返回 ListContainer<Agent>
            val listContainer =
                body as ListContainer<Agent>
            ListContainer(
                list = listContainer.list.map { it.toAgentEntity() },
                total = listContainer.total,
                page = page,
                pageSize = pageSize
            )
        }
    }
}