//
//  SessionUploadImage.swift
//  Sailassist
//
//  Created by 三浦薫巳 on 2023/11/23.
//

import Foundation
import SwiftUI

class SessionUploadImage : ObservableObject {
    @Published var progress: Double = 0.0
    @Published var isUploading: Bool = false
    static let OnlyOne = SessionUploadImage()   // シングルトン宣言

    private var serverSession = ServerSession()
    private var Calling : Bool = false      // 通信中

    private var uploadTask: URLSessionUploadTask?

    func cancelUpload() {
        uploadTask?.cancel()
        isUploading = false
        progress = 0.0
    }

    /**
     * メッセージ
     */
    func requestUploadImage(_ uploadImage: ReqUploadImage) async throws -> Data {
        print(debug: "calld")
        guard !Calling else {
            throw APIError.busy
        }
        Calling = true
        defer { Calling = false }

        // リクエストURLの組み立て
        guard let req_url = URL(string: HttpRequestType.UploadImage.rawValue) else {
            throw APIError.invalidURL
        }

        let imageFileName = "itemp.jpg"
        let boundary = "----------\(UUID().uuidString)"

        var httpBody = Data()
        func appendFormField(name: String, value: String) {
            httpBody.append("--\(boundary)\r\n".data(using: .utf8)!)
            httpBody.append("Content-Disposition: form-data; name=\"\(name)\"\r\n\r\n".data(using: .utf8)!)
            httpBody.append("\(value)\r\n".data(using: .utf8)!)
        }

        appendFormField(name: "ShipId", value: String(uploadImage.shipId))
        appendFormField(name: "MessageId", value: uploadImage.messageId)
        appendFormField(name: "Location", value: String(uploadImage.location))
        appendFormField(name: "From", value: uploadImage.from)
        appendFormField(name: "FromId", value: uploadImage.fromId)

        httpBody.append("--\(boundary)\r\n".data(using: .utf8)!)
        httpBody.append("Content-Disposition: form-data; name=\"files\"; filename=\"\(imageFileName)\"\r\n".data(using: .utf8)!)
        httpBody.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
        httpBody.append(uploadImage.files)
        httpBody.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)

        var request = URLRequest(url: req_url)
        request.httpMethod = "POST"
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        let session = URLSession(configuration: .default, delegate: UploadProgressDelegate(parent: self), delegateQueue: nil)

        isUploading = true
        uploadTask = session.uploadTask(with: request, from: httpBody)
        uploadTask?.resume()

        let (data, response) = try await session.upload(for: request, from: httpBody)

        isUploading = false
        progress = 0.0

        guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
            throw APIError.serverError
        }

        return data
    }

    func postFormAsync(boundary: String, url: URL, body: Data) async throws -> Data {
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        request.httpBody = body

        let (data, response) = try await URLSession.shared.data(for: request)

        guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
            throw APIError.serverError
        }

        return data
    }

    class UploadProgressDelegate: NSObject, URLSessionTaskDelegate {
        weak var parent: SessionUploadImage?

        init(parent: SessionUploadImage) {
            self.parent = parent
        }

        func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64,
                        totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
            DispatchQueue.main.async {
                self.parent?.progress = Double(totalBytesSent) / Double(totalBytesExpectedToSend)
            }
        }
    }
}
