import java.net.URI
import org.gradle.api.tasks.compile.JavaCompile

plugins {
    id("com.android.application")
}

val releaseBaseUrl = providers.gradleProperty("WNH_BASE_URL").orElse("")
val debugBaseUrl = providers.gradleProperty("WNH_DEBUG_BASE_URL").orElse("")
val trackingMinTimeMs = providers.gradleProperty("WNH_TRACKING_MIN_TIME_MS").orElse("0")
val trackingHttpTimeoutMs =
    providers.gradleProperty("WNH_TRACKING_HTTP_TIMEOUT_MS").orElse("0")
val instrumentationBuildType =
    providers.gradleProperty("WNH_TEST_BUILD_TYPE").orElse("debug")

fun manifestOrigin(value: String): URI? =
    runCatching { URI(value) }
        .getOrNull()
        ?.takeIf { uri ->
            (uri.scheme == "http" || uri.scheme == "https") && !uri.host.isNullOrBlank()
        }

fun isOriginPath(uri: URI): Boolean =
    uri.path.isNullOrEmpty() || uri.path == "/"

val debugManifestOrigin = manifestOrigin(debugBaseUrl.get())
val releaseManifestOrigin = manifestOrigin(releaseBaseUrl.get())

android {
    namespace = "org.whoneedhelp.mobile"
    compileSdk = 37
    buildToolsVersion = "37.0.0"
    testBuildType = instrumentationBuildType.get()

    defaultConfig {
        applicationId = "org.whoneedhelp.mobile"
        minSdk = 24
        targetSdk = 37
        versionCode = 1
        versionName = "0.1.0"
        buildConfigField("long", "TRACKING_MIN_TIME_MS", "${trackingMinTimeMs.get()}L")
        buildConfigField(
            "long",
            "TRACKING_HTTP_TIMEOUT_MS",
            "${trackingHttpTimeoutMs.get()}L"
        )

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        debug {
            applicationIdSuffix = ".debug"
            versionNameSuffix = "-debug"
            buildConfigField(
                "String",
                "BASE_URL",
                "\"${debugBaseUrl.get().replace("\\", "\\\\").replace("\"", "\\\"")}\""
            )
            manifestPlaceholders["usesCleartextTraffic"] = "true"
            manifestPlaceholders["deepLinkScheme"] = debugManifestOrigin?.scheme ?: "https"
            manifestPlaceholders["deepLinkHost"] =
                debugManifestOrigin?.host ?: "invalid.whoneedhelp.local"
        }

        create("staging") {
            initWith(getByName("debug"))
            applicationIdSuffix = ".staging"
            versionNameSuffix = "-staging"
            buildConfigField(
                "String",
                "BASE_URL",
                "\"${releaseBaseUrl.get().replace("\\", "\\\\").replace("\"", "\\\"")}\""
            )
            manifestPlaceholders["usesCleartextTraffic"] = "false"
            manifestPlaceholders["deepLinkScheme"] = releaseManifestOrigin?.scheme ?: "https"
            manifestPlaceholders["deepLinkHost"] =
                releaseManifestOrigin?.host ?: "invalid.whoneedhelp.local"
            matchingFallbacks += listOf("debug")
        }

        release {
            isMinifyEnabled = true
            isShrinkResources = true
            buildConfigField(
                "String",
                "BASE_URL",
                "\"${releaseBaseUrl.get().replace("\\", "\\\\").replace("\"", "\\\"")}\""
            )
            manifestPlaceholders["usesCleartextTraffic"] = "false"
            manifestPlaceholders["deepLinkScheme"] = releaseManifestOrigin?.scheme ?: "https"
            manifestPlaceholders["deepLinkHost"] =
                releaseManifestOrigin?.host ?: "invalid.whoneedhelp.local"
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }

    buildFeatures {
        buildConfig = true
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }

    testOptions {
        unitTests.isIncludeAndroidResources = false
    }
}

tasks.matching { it.name == "preReleaseBuild" || it.name == "preStagingBuild" }.configureEach {
    doFirst {
        val value = releaseBaseUrl.orNull.orEmpty()
        val uri = runCatching { URI(value) }.getOrNull()

        if (
            uri == null ||
            uri.scheme != "https" ||
            uri.host.isNullOrBlank() ||
            uri.userInfo != null ||
            !isOriginPath(uri) ||
            uri.query != null ||
            uri.fragment != null
        ) {
            throw GradleException(
                "Staging and release builds require "
                    + "-PWNH_BASE_URL=https://your-real-deployment.example"
            )
        }

        validateTrackingConfiguration()
    }
}

tasks.matching { it.name == "preDebugBuild" }.configureEach {
    doFirst {
        val value = debugBaseUrl.orNull.orEmpty()
        val uri = runCatching { URI(value) }.getOrNull()

        if (
            uri == null ||
            (uri.scheme != "http" && uri.scheme != "https") ||
            uri.host.isNullOrBlank() ||
            uri.userInfo != null ||
            !isOriginPath(uri) ||
            uri.query != null ||
            uri.fragment != null
        ) {
            throw GradleException(
                "Debug builds require -PWNH_DEBUG_BASE_URL=http(s)://your-development-host"
            )
        }

        validateTrackingConfiguration()
    }
}

fun validateTrackingConfiguration() {
    val minTime = trackingMinTimeMs.orNull?.toLongOrNull()
    val httpTimeout = trackingHttpTimeoutMs.orNull?.toLongOrNull()

    if (minTime == null || minTime <= 0) {
        throw GradleException(
            "Builds require -PWNH_TRACKING_MIN_TIME_MS=POSITIVE_MILLISECONDS"
        )
    }

    if (httpTimeout == null || httpTimeout <= 0 || httpTimeout > Int.MAX_VALUE) {
        throw GradleException(
            "Builds require -PWNH_TRACKING_HTTP_TIMEOUT_MS=POSITIVE_INT_MILLISECONDS"
        )
    }
}

tasks.withType<JavaCompile>().configureEach {
    options.compilerArgs.add("-Xlint:deprecation")
}

dependencies {
    implementation("androidx.activity:activity:1.13.0")
    implementation("androidx.webkit:webkit:1.16.0")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test:core:1.7.0")
    androidTestImplementation("androidx.test:runner:1.7.0")
    androidTestImplementation("androidx.test:rules:1.7.0")
    androidTestImplementation("androidx.test.ext:junit:1.3.0")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0")
    androidTestImplementation("androidx.test.espresso:espresso-web:3.7.0")
    androidTestImplementation("androidx.test.uiautomator:uiautomator:2.4.0")
}
