package ru.forbion.f7cloud.feature.files

import okhttp3.FormBody
import okhttp3.Request
import org.json.JSONObject
import ru.forbion.f7cloud.core.auth.AuthSession
import ru.forbion.f7cloud.core.network.NetworkFactory
import ru.forbion.f7cloud.core.network.UnauthorizedException

class FilesTemplatesRepository {
    data class CreatedFile(
        val fileId: Long,
        val name: String,
        val relativePath: String,
    )

    fun createFromTemplate(session: AuthSession, relativeFilePath: String): CreatedFile {
        val client = authedClient(session)
        val url = "${session.serverUrl.trimEnd('/')}/ocs/v2.php/apps/files/api/v1/templates/create?format=json"
        val body = FormBody.Builder()
            .add("filePath", relativeFilePath)
            .add("templatePath", "")
            .add("templateType", "user")
            .build()
        val request = Request.Builder()
            .url(url)
            .header("OCS-APIRequest", "true")
            .header("Accept", "application/json")
            .post(body)
            .build()
        return client.newCall(request).execute().use { response ->
            parseOcsData(response) { data ->
                CreatedFile(
                    fileId = data.optLong("fileid"),
                    name = data.optString("basename"),
                    relativePath = data.optString("filename"),
                )
            }
        }
    }

    fun initializeTemplateDirectory(session: AuthSession): String {
        val client = authedClient(session)
        val url = "${session.serverUrl.trimEnd('/')}/ocs/v2.php/apps/files/api/v1/templates/path?format=json"
        val body = FormBody.Builder()
            .add("templatePath", "")
            .add("copySystemTemplates", "true")
            .build()
        val request = Request.Builder()
            .url(url)
            .header("OCS-APIRequest", "true")
            .header("Accept", "application/json")
            .post(body)
            .build()
        return client.newCall(request).execute().use { response ->
            parseOcsData(response) { data ->
                data.optString("template_path")
            }
        }
    }

    fun openFolderDescription(session: AuthSession, relativeFolderPath: String): String {
        val client = authedClient(session)
        val url = "${session.serverUrl.trimEnd('/')}/ocs/v2.php/apps/text/api/v1/workspace/direct?format=json"
        val body = FormBody.Builder()
            .add("path", relativeFolderPath.ifBlank { "/" })
            .build()
        val request = Request.Builder()
            .url(url)
            .header("OCS-APIRequest", "true")
            .header("Accept", "application/json")
            .post(body)
            .build()
        return client.newCall(request).execute().use { response ->
            parseOcsData(response) { data ->
                data.optString("url").ifBlank {
                    error("Не удалось открыть описание папки")
                }
            }
        }
    }

    private fun <T> parseOcsData(response: okhttp3.Response, block: (JSONObject) -> T): T {
        if (!response.isSuccessful || response.body == null) {
            error("HTTP ${response.code}")
        }
        val ocs = JSONObject(response.body!!.string()).optJSONObject("ocs")
            ?: error("Некорректный ответ сервера")
        val meta = ocs.optJSONObject("meta")
        if (meta?.optString("status").equals("failure", ignoreCase = true)) {
            error(meta?.optString("message").orEmpty().ifBlank { "Ошибка сервера" })
        }
        val data = ocs.optJSONObject("data") ?: JSONObject()
        return block(data)
    }

    private fun authedClient(session: AuthSession) = NetworkFactory.newAuthedClient(
        session.username,
        session.appPassword,
        session.trustAllCerts,
    )
}
