package com.anypreta.bountyboard.data.net

import com.google.gson.JsonObject
import okhttp3.MultipartBody
import okhttp3.ResponseBody
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
import retrofit2.http.Streaming

/**
 * The full BountyBoard HTTP surface (spec §6, api/openapi.yaml). Base path /api/v1.
 * Auth is via cookie jar; CSRF header is injected by [CsrfInterceptor]. All calls
 * return [Response] so the repository can read the {"error":{...}} envelope uniformly.
 */
interface ApiService {

    // ---- Auth ----
    @POST("api/v1/auth/login")
    suspend fun login(@Body body: LoginRequest): Response<AuthResponse>

    @POST("api/v1/auth/register")
    suspend fun register(@Body body: RegisterRequest): Response<AuthResponse>

    @GET("api/v1/auth/me")
    suspend fun me(): Response<AuthResponse>

    @POST("api/v1/auth/logout")
    suspend fun logout(): Response<Unit>

    @POST("api/v1/auth/logout-all")
    suspend fun logoutAll(): Response<RevokedResponse>

    @POST("api/v1/auth/change-password")
    suspend fun changePassword(@Body body: ChangePasswordRequest): Response<Unit>

    @POST("api/v1/auth/forgot")
    suspend fun forgot(@Body body: ForgotRequest): Response<JsonObject>

    @POST("api/v1/auth/reset")
    suspend fun reset(@Body body: ResetRequest): Response<Unit>

    // ---- Developer board ----
    @GET("api/v1/board")
    suspend fun board(
        @Query("customerId") customerId: String? = null,
        @Query("q") q: String? = null,
        @Query("minBounty") minBounty: Double? = null,
        @Query("sort") sort: String? = null,
    ): Response<BoardResponse>

    @GET("api/v1/my-tasks")
    suspend fun myTasks(): Response<MyTasksResponse>

    @GET("api/v1/leaderboard")
    suspend fun leaderboard(): Response<LeaderboardResponse>

    @GET("api/v1/developer/metrics")
    suspend fun developerMetrics(
        @Query("from") from: String? = null,
        @Query("to") to: String? = null,
    ): Response<JsonObject>

    // ---- Consultant ----
    @GET("api/v1/consultant/board")
    suspend fun consultantBoard(
        @Query("customerId") customerId: String? = null,
        @Query("status") status: String? = null,
    ): Response<ConsultantBoardResponse>

    @GET("api/v1/consultant/reviews")
    suspend fun reviews(): Response<TasksResponse>

    @GET("api/v1/consultant/pool")
    suspend fun pool(): Response<PoolResponse>

    @POST("api/v1/consultant/pool")
    suspend fun addToPool(@Body body: PoolAddBody): Response<Unit>

    @DELETE("api/v1/consultant/pool/{developerId}")
    suspend fun removeFromPool(@Path("developerId") developerId: String): Response<Unit>

    @GET("api/v1/consultant/metrics")
    suspend fun consultantMetrics(
        @Query("customerId") customerId: String? = null,
        @Query("developerId") developerId: String? = null,
        @Query("from") from: String? = null,
        @Query("to") to: String? = null,
    ): Response<JsonObject>

    // ---- Tasks ----
    @GET("api/v1/tasks/{id}")
    suspend fun task(@Path("id") id: String): Response<TaskResponse>

    @PATCH("api/v1/tasks/{id}")
    suspend fun patchTask(@Path("id") id: String, @Body body: TaskPatchBody): Response<TaskResponse>

    @POST("api/v1/tasks/{id}/subdivide")
    suspend fun subdivide(@Path("id") id: String, @Body body: SubdivideBody): Response<JobResponse>

    @POST("api/v1/tasks/{id}/extend")
    suspend fun extend(@Path("id") id: String, @Body body: ExtendBody): Response<JobResponse>

    @POST("api/v1/tasks/{id}/publish")
    suspend fun publish(@Path("id") id: String): Response<TaskResponse>

    @POST("api/v1/tasks/publish")
    suspend fun publishBulk(@Body body: IdsBody): Response<BulkResult>

    @POST("api/v1/tasks/archive")
    suspend fun archiveBulk(@Body body: IdsBody): Response<BulkResult>

    @POST("api/v1/tasks/{id}/archive")
    suspend fun archiveTask(@Path("id") id: String): Response<Unit>

    @POST("api/v1/tasks/{id}/claim")
    suspend fun claim(@Path("id") id: String, @Body body: ClaimBody): Response<Unit>

    @POST("api/v1/tasks/{id}/claim/withdraw")
    suspend fun withdrawClaim(@Path("id") id: String): Response<Unit>

    @POST("api/v1/tasks/{id}/approve-claim")
    suspend fun approveClaim(@Path("id") id: String, @Body body: ApproveClaimBody): Response<Unit>

    @POST("api/v1/tasks/{id}/decline-claim")
    suspend fun declineClaim(@Path("id") id: String, @Body body: DeclineClaimBody): Response<Unit>

    @POST("api/v1/tasks/{id}/assign-ai")
    suspend fun assignAi(@Path("id") id: String, @Body body: AssignAiBody): Response<JobResponse>

    @POST("api/v1/tasks/{id}/unassign")
    suspend fun unassign(@Path("id") id: String): Response<Unit>

    @POST("api/v1/tasks/{id}/start")
    suspend fun start(@Path("id") id: String): Response<Unit>

    @POST("api/v1/tasks/{id}/submit-review")
    suspend fun submitReview(@Path("id") id: String): Response<Unit>

    @POST("api/v1/tasks/{id}/abandon")
    suspend fun abandon(@Path("id") id: String): Response<Unit>

    @POST("api/v1/tasks/{id}/comments")
    suspend fun addComment(@Path("id") id: String, @Body body: CommentBody): Response<CommentResponse>

    @POST("api/v1/tasks/{id}/time")
    suspend fun logTime(@Path("id") id: String, @Body body: TimeBody): Response<TimeEntryResponse>

    @POST("api/v1/tasks/{id}/review")
    suspend fun review(@Path("id") id: String, @Body body: ReviewBody): Response<Unit>

    // ---- Messaging ----
    @GET("api/v1/conversations")
    suspend fun conversations(): Response<ConversationsResponse>

    @POST("api/v1/conversations")
    suspend fun createConversation(@Body body: CreateConversationBody): Response<ConversationResponse>

    @GET("api/v1/conversations/{id}/messages")
    suspend fun messages(
        @Path("id") id: String,
        @Query("cursor") cursor: String? = null,
        @Query("limit") limit: Int? = null,
    ): Response<MessagesResponse>

    @POST("api/v1/conversations/{id}/messages")
    suspend fun sendMessage(@Path("id") id: String, @Body body: SendMessageBody): Response<MessageResponse>

    @POST("api/v1/conversations/{id}/read")
    suspend fun markConversationRead(@Path("id") id: String): Response<MarkedResponse>

    // ---- Files ----
    @Multipart
    @POST("api/v1/files")
    suspend fun uploadFile(
        @Part file: MultipartBody.Part,
        @Part("scope") scope: okhttp3.RequestBody? = null,
    ): Response<com.anypreta.bountyboard.data.model.FileUploadResult>

    @Streaming
    @GET("files/{id}")
    suspend fun downloadFile(@Path("id") id: String): Response<ResponseBody>

    // ---- Profile / directory ----
    @GET("api/v1/profile")
    suspend fun profile(): Response<UserResponse>

    @PATCH("api/v1/profile")
    suspend fun patchProfile(@Body body: ProfilePatchBody): Response<UserResponse>

    @Multipart
    @POST("api/v1/profile/avatar")
    suspend fun uploadAvatar(@Part file: MultipartBody.Part): Response<AvatarResponse>

    @GET("api/v1/users")
    suspend fun users(@Query("q") q: String? = null): Response<UsersResponse>

    @GET("api/v1/users/{id}/card")
    suspend fun userCard(@Path("id") id: String): Response<CardResponse>

    // ---- Notifications ----
    @GET("api/v1/notifications")
    suspend fun notifications(
        @Query("unread") unread: Boolean? = null,
        @Query("cursor") cursor: String? = null,
        @Query("limit") limit: Int? = null,
    ): Response<NotificationsResponse>

    @POST("api/v1/notifications/read")
    suspend fun markNotificationsRead(@Body body: NotificationsReadBody): Response<MarkedResponse>

    @GET("api/v1/service-health")
    suspend fun serviceHealth(): Response<JsonObject>

    // ---- Admin ----
    @GET("api/v1/admin/users")
    suspend fun adminUsers(
        @Query("q") q: String? = null,
        @Query("role") role: String? = null,
    ): Response<UsersResponse>

    @PATCH("api/v1/admin/users/{id}")
    suspend fun adminPatchUser(@Path("id") id: String, @Body body: JsonObject): Response<UserResponse>

    @DELETE("api/v1/admin/users/{id}")
    suspend fun adminDeleteUser(@Path("id") id: String): Response<Unit>

    @GET("api/v1/admin/customers")
    suspend fun adminCustomers(
        @Query("includeArchived") includeArchived: Boolean? = null,
    ): Response<CustomersResponse>

    @POST("api/v1/admin/customers")
    suspend fun adminCreateCustomer(@Body body: CustomerBody): Response<CustomerResponse>

    @GET("api/v1/admin/customers/{id}")
    suspend fun adminCustomer(@Path("id") id: String): Response<CustomerResponse>

    @PATCH("api/v1/admin/customers/{id}")
    suspend fun adminPatchCustomer(@Path("id") id: String, @Body body: CustomerBody): Response<CustomerResponse>

    @DELETE("api/v1/admin/customers/{id}")
    suspend fun adminDeleteCustomer(@Path("id") id: String): Response<Unit>

    @POST("api/v1/admin/customers/test-connection")
    suspend fun adminTestConnectionNew(@Body body: CustomerBody): Response<TestConnectionResult>

    @POST("api/v1/admin/customers/{id}/test-connection")
    suspend fun adminTestConnection(@Path("id") id: String): Response<TestConnectionResult>

    @POST("api/v1/admin/customers/{id}/sync-now")
    suspend fun adminSyncNow(@Path("id") id: String): Response<Unit>

    @GET("api/v1/admin/settings")
    suspend fun adminSettings(): Response<JsonObject>

    @PATCH("api/v1/admin/settings")
    suspend fun adminPatchSettings(@Body body: JsonObject): Response<JsonObject>

    @GET("api/v1/admin/audit-log")
    suspend fun adminAuditLog(
        @Query("actorId") actorId: String? = null,
        @Query("entityId") entityId: String? = null,
        @Query("cursor") cursor: String? = null,
    ): Response<AuditResponse>

    @GET("api/v1/admin/service-status")
    suspend fun adminServiceStatus(): Response<JsonObject>
}
