import UIKit
import PlaygroundSupport // Only needed when using Playground


/*
 Setup (API URL + Context)
 */

let subdomain = "sandbox"  // Replace with the subdomain given to you
let environment = "test_env"  // Replace with the environment given to you

let baseUrl = "https://\(subdomain).froomle.com/api/\(environment)/"


struct Context {
    var channel: String
    var page_type: String
    var context_item: String
    var context_item_type: String
    var device_id: String
    var user_id: String
}

// Set up the context according to the page, the item that is viewed, the user and the device.
let context = Context(
    channel: "www-desktop",
    page_type: "article_detail",
    context_item: "item-id-123",
    context_item_type: "article",
    device_id: "device-id-123",
    user_id: "user-id-123"
)


/*
 Getting Recommendations: https://docs.froomle.com/froomle-doc-main/api_reference/recommendations/index
 */

struct RequestList: Codable {
    var list_name: String
    var list_size: Int
    var limit: Int
}

struct RecommendationRequest: Codable {
    var channel: String
    var device_id: String
    var page_type: String
    var lists: [RequestList]
}

struct Item: Codable {
    var rank: Int
    var item_id: String
    var item_type: String = "article"
    var uri: String
    var images: [String]
}

struct ResponseList: Codable {
    var list_name: String
    var list_size: Int
    var limit: Int
    var list_key: String
    var items: [Item]
}

struct Recommendations: Codable {
    var device_id: String
    var request_id: String
    var user_id: String
    var lists: [ResponseList]

}

let exampleRecommendationsRequest = RecommendationRequest(
    channel: context.channel,
    device_id: context.device_id,
    page_type: context.page_type,
    lists: [
        RequestList(list_name: "reco_list_001", list_size: 5, limit: 2)
    ]
)


// Send recommendations request
Task {
    guard let recommendationsUrl = URL(string: baseUrl + "recommendations/requests") else { fatalError("Missing URL for Recommendations") }
    let payload = try JSONEncoder().encode(exampleRecommendationsRequest)

    var recommendationRequest = URLRequest(url: recommendationsUrl)
    recommendationRequest.httpMethod = "POST"
    recommendationRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")

    let (data, response) = try await URLSession.shared.upload(for: recommendationRequest, from: payload)
    guard (response as? HTTPURLResponse)?.statusCode == 200 else { print("Error \((response as! HTTPURLResponse).statusCode) while fetching recommendations: \(String(data:data, encoding: .utf8) ?? ""))") }
    print("Successfully received recommendations")

    let recommendations = try JSONDecoder().decode(Recommendations.self, from: data)

    print("Example recommendations:", String(data: try JSONEncoder().encode(recommendations), encoding: .utf8) ?? "No recommendations...")
}



/*
 Sending Events: https://docs.froomle.com/froomle-doc-main/api_reference/events/events_api.html
 */

struct Event: Codable {
    var event_type: String
    var page_type: String
    var device_id: String
    var user_id: String
    var action_item: String
    var action_item_type: String
    var channel: String
    var list_name: String? = nil
    var request_id: String? = nil
}


struct Events: Codable {
    var events: [Event]
}

// This is an example of recommendations that you have fetched earlier
let fetchedRecommendations = Recommendations(device_id: context.device_id, request_id: "6461", user_id: context.user_id,
                                              lists: [
                                                ResponseList(list_name: "reco_list_001", list_size: 2, limit: 2, list_key: "reco_list_001",
                                                             items: [
                                                                Item(rank: 1, item_id: "item-id-123", uri: "https://link.com/123", images: ["https://via.placeholder.com/150"]),
                                                                Item(rank: 2, item_id: "item-id-321", uri: "https://link.com/321", images: ["https://via.placeholder.com/150"])
                                                             ])
                                              ]
)

let viewedItem = fetchedRecommendations.lists[0].items[0]
let clickedOnItem = fetchedRecommendations.lists[0].items[1]

let exampleEvents = Events(events: [
    Event(event_type: "detail_pageview", page_type: context.page_type, device_id: context.device_id, user_id: context.user_id, action_item: context.context_item, action_item_type: context.context_item_type, channel: context.channel),
    Event(event_type: "impression", page_type: context.page_type, device_id: context.device_id, user_id: context.user_id, action_item: viewedItem.item_id, action_item_type: viewedItem.item_type, channel: context.channel, list_name: fetchedRecommendations.lists[0].list_name, request_id: fetchedRecommendations.request_id),
    Event(event_type: "click_on_recommendation", page_type: context.page_type, device_id: context.device_id, user_id: context.user_id, action_item: clickedOnItem.item_id, action_item_type: clickedOnItem.item_type, channel: context.channel, list_name: fetchedRecommendations.lists[0].list_name, request_id: fetchedRecommendations.request_id),
])


Task {
    guard let eventsUrl = URL(string: baseUrl + "events") else { fatalError("Missing URL for Events") }
    let payload = try JSONEncoder().encode(exampleEvents)

    var eventsRequest = URLRequest(url: eventsUrl)
    eventsRequest.httpMethod = "POST"
    eventsRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")

    let (data, response) = try await URLSession.shared.upload(for: eventsRequest, from: payload)
    guard (response as? HTTPURLResponse)?.statusCode == 200 else { print("Error \((response as! HTTPURLResponse).statusCode) while sending events: \(String(data:data, encoding: .utf8) ?? ""))") }

    print("\nEvents are sent successfully!")
}

PlaygroundPage.current.needsIndefiniteExecution = true // Only needed when using Playground