package cy.hexor.furumi.data.remote

import android.net.Uri
import cy.hexor.furumi.domain.model.AuthException
import javax.inject.Inject

class AuthEndpoints @Inject constructor() {
    fun passwordLogin(baseUrl: String): String = "$baseUrl$PASSWORD_LOGIN_PATH"

    fun ssoExchange(baseUrl: String): String = "$baseUrl$SSO_EXCHANGE_PATH"

    fun refresh(baseUrl: String): String = "$baseUrl$REFRESH_PATH"

    fun logout(baseUrl: String): String = "$baseUrl$LOGOUT_PATH"

    fun ssoStart(baseUrl: String): String {
        return Uri.parse("$baseUrl$SSO_START_PATH")
            .buildUpon()
            .appendQueryParameter("redirect_uri", SSO_REDIRECT_URI)
            .build()
            .toString()
    }

    fun parseSsoCallback(callbackUrl: String): Result<SsoCallback> {
        val uri = runCatching { Uri.parse(callbackUrl) }.getOrElse {
            return Result.failure(AuthException("Invalid SSO callback"))
        }

        if (uri.scheme != SSO_REDIRECT_SCHEME || uri.host != SSO_REDIRECT_HOST || uri.path != SSO_REDIRECT_PATH) {
            return Result.failure(AuthException("Unexpected SSO callback"))
        }

        uri.getQueryParameter("error")?.let { error ->
            return Result.failure(AuthException("SSO error: $error"))
        }

        val code = uri.getQueryParameter("code")
        if (code.isNullOrBlank()) {
            return Result.failure(AuthException("SSO callback does not contain an authorization code"))
        }

        return Result.success(SsoCallback(code))
    }

    fun isLoginOrRefreshPath(path: String): Boolean {
        return path.endsWith(PASSWORD_LOGIN_PATH) ||
            path.endsWith(SSO_EXCHANGE_PATH) ||
            path.endsWith(REFRESH_PATH)
    }

    companion object {
        const val SSO_REDIRECT_URI = "furumi://auth/callback"

        private const val PASSWORD_LOGIN_PATH = "/api/auth/password"
        private const val SSO_EXCHANGE_PATH = "/api/auth/sso/exchange"
        private const val REFRESH_PATH = "/api/auth/refresh"
        private const val LOGOUT_PATH = "/api/auth/logout"
        private const val SSO_START_PATH = "/auth/mobile/oidc/start"
        private const val SSO_REDIRECT_SCHEME = "furumi"
        private const val SSO_REDIRECT_HOST = "auth"
        private const val SSO_REDIRECT_PATH = "/callback"
    }
}

data class SsoCallback(
    val code: String
)
