//
//  LiveApi.swift
//  SodaLive
//
//  Created by klaus on 2023/08/09.
//

import Foundation
import Moya

enum LiveApi {
    case roomList(request: GetRoomListRequest)
    case recentVisitRoomUsers
    case getReservations(isActive: Bool)
    case getReservation(reservationId: Int)
    case cancelReservation(request: CancelLiveReservationRequest)
    case getRoomDetail(roomId: Int)
    case makeReservation(request: MakeLiveReservationRequest)
    case enterRoom(request: EnterOrQuitLiveRoomRequest)
    case getTags
    case getRecentRoomInfo
    case createRoom(parameters: [MultipartFormData])
    case startLive(request: StartLiveRequest)
    case cancelRoom(request: CancelLiveRequest)
    case editLiveRoomInfo(roomId: Int, parameters: [MultipartFormData])
    case quitRoom(roomId: Int)
    case getRoomInfo(roomId: Int)
    case donation(request: LiveRoomDonationRequest)
    case refundDonation(roomId: Int)
    case setListener(request: SetManagerOrSpeakerOrAudienceRequest)
    case setSpeaker(request: SetManagerOrSpeakerOrAudienceRequest)
    case setManager(request: SetManagerOrSpeakerOrAudienceRequest)
    case kickOut(request: LiveRoomKickOutRequest)
    case donationStatus(roomId: Int)
    case donationTotal(roomId: Int)
    case getDonationMessageList(roomId: Int)
    case deleteDonationMessage(roomId: Int, messageUUID: String)
    case getUserProfile(roomId: Int, userId: Int)
    case getAllMenuPreset(creatorId: Int)
}

extension LiveApi: TargetType {
    var baseURL: URL {
        return URL(string: BASE_URL)!
    }
    
    var path: String {
        switch self {
        case .roomList:
            return "/live/room"
            
        case .recentVisitRoomUsers:
            return "/live/room/recent_visit_room/users"
            
        case .getReservations:
            return "/live/reservation"
            
        case .getReservation(let reservationId):
            return "/live/reservation/\(reservationId)"
            
        case .cancelReservation:
            return "/live/reservation/cancel"
            
        case .getRoomDetail(let roomId):
            return "/live/room/detail/\(roomId)"
            
        case .makeReservation:
            return "/live/reservation"
            
        case .enterRoom:
            return "/live/room/enter"
            
        case .getTags:
            return "/live/tag"
            
        case .getRecentRoomInfo:
            return "/live/room/recent-room-info"
            
        case .createRoom:
            return "/live/room"
            
        case .startLive:
            return "/live/room/start"
            
        case .cancelRoom:
            return "/live/room/cancel"
            
        case .editLiveRoomInfo(let roomId, _):
            return "/live/room/\(roomId)"
            
        case .quitRoom:
            return "/live/room/quit"
            
        case .getRoomInfo(let roomId):
            return "/live/room/info/\(roomId)"
            
        case .donation:
            return "/live/room/donation/v2"
            
        case .refundDonation(let roomId):
            return "/live/room/donation/refund/\(roomId)"
            
        case .setListener:
            return "/live/room/info/set/listener"
            
        case .setSpeaker:
            return "/live/room/info/set/speaker"
            
        case .setManager:
            return "/live/room/info/set/manager"
            
        case .kickOut:
            return "/live/room/kick-out"
            
        case .donationStatus(let roomId):
            return "/live/room/\(roomId)/donation-list"
            
        case .donationTotal(let roomId):
            return "/live/room/\(roomId)/donation-total"
            
        case .getDonationMessageList:
            return "/live/room/donation-message"
            
        case .deleteDonationMessage:
            return "/live/room/donation-message"
            
        case .getUserProfile(let roomId, let userId):
            return "/live/room/\(roomId)/profile/\(userId)"
            
        case .getAllMenuPreset:
            return "/live/room/menu/all"
        }
    }
    
    var method: Moya.Method {
        switch self {
        case .roomList, .recentVisitRoomUsers, .getReservations, .getReservation, .getRoomDetail, .getTags, .getRecentRoomInfo, .getRoomInfo, .donationStatus, .donationTotal, .getDonationMessageList, .getUserProfile, .getAllMenuPreset:
            return .get
            
        case .makeReservation, .enterRoom, .createRoom, .quitRoom, .donation, .refundDonation, .kickOut:
            return .post
            
        case .setListener, .setSpeaker, .setManager, .cancelReservation, .startLive, .cancelRoom, .editLiveRoomInfo:
            return .put
            
        case .deleteDonationMessage:
            return .delete
        }
    }
    
    var task: Moya.Task {
        switch self {
        case .roomList(let request):
            var parameters = [
                "timezone": request.timezone,
                "status": request.status.rawValue,
                "page": request.page - 1,
                "size": request.size,
            ] as [String : Any]
            
            if let dateString = request.dateString {
                parameters["dateString"] = dateString
            }
            
            return .requestParameters(
                parameters: parameters,
                encoding: URLEncoding.queryString)
            
        case .recentVisitRoomUsers, .getTags, .getRecentRoomInfo, .getRoomInfo, .refundDonation, .donationStatus, .donationTotal, .getUserProfile:
            return .requestPlain
            
        case .getReservations(let isActive):
            let parameters = [
                "timezone": TimeZone.current.identifier,
                "isActive": isActive
            ] as [String : Any]
            
            return .requestParameters(
                parameters: parameters,
                encoding: URLEncoding.queryString
            )
            
        case .getReservation:
            let parameters = ["timezone": TimeZone.current.identifier] as [String : Any]
            
            return .requestParameters(
                parameters: parameters,
                encoding: URLEncoding.queryString
            )
            
        case .cancelReservation(let request):
            return .requestJSONEncodable(request)
            
        case .getRoomDetail:
            let parameters = ["timezone": TimeZone.current.identifier] as [String: Any]
            return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
            
        case .makeReservation(let request):
            return .requestJSONEncodable(request)
            
        case .enterRoom(let request):
            return .requestJSONEncodable(request)
            
        case .createRoom(let parameters):
            return .uploadMultipart(parameters)
            
        case .startLive(let request):
            return .requestJSONEncodable(request)
            
        case .cancelRoom(let request):
            return .requestJSONEncodable(request)
            
        case .editLiveRoomInfo(_, let parameters):
            return .uploadMultipart(parameters)
            
        case .quitRoom(let roomId):
            return .requestParameters(parameters: ["id": roomId], encoding: URLEncoding.queryString)
            
        case .donation(let request):
            return .requestJSONEncodable(request)
            
        case .setListener(let request), .setSpeaker(let request), .setManager(let request):
            return .requestJSONEncodable(request)
            
        case .kickOut(let request):
            return .requestJSONEncodable(request)
            
        case .getDonationMessageList(let roomId):
            return .requestParameters(parameters: ["roomId": roomId], encoding: URLEncoding.queryString)
            
        case .deleteDonationMessage(let roomId, let messageUUID):
            return .requestJSONEncodable(DeleteLiveRoomDonationMessage(roomId: roomId, messageUUID: messageUUID))
            
        case .getAllMenuPreset(let creatorId):
            return .requestParameters(parameters: ["creatorId" : creatorId], encoding: URLEncoding.queryString)
        }
    }
    
    var headers: [String : String]? {
        return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"]
    }
}