/*
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package com.runicgateway.app.ui.connect

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.runicgateway.app.R
import com.runicgateway.app.ui.connect.ConnectViewModel.ConnectError

/**
 * First-run "Connect to your shard's website" screen (PLAN.md §3). Nothing else
 * in the app runs until a valid Runic Gateway site is entered and validated.
 */
@Composable
fun ConnectScreen(
    onConnected: () -> Unit,
    modifier: Modifier = Modifier,
    viewModel: ConnectViewModel = hiltViewModel(),
) {
    val state by viewModel.state.collectAsStateWithLifecycle()

    Column(
        modifier = modifier
            .fillMaxSize()
            .padding(24.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
    ) {
        Text(
            text = stringResource(R.string.connect_title),
            style = MaterialTheme.typography.headlineSmall,
            textAlign = TextAlign.Center,
        )
        Text(
            text = stringResource(R.string.connect_subtitle),
            style = MaterialTheme.typography.bodyMedium,
            textAlign = TextAlign.Center,
            modifier = Modifier.padding(top = 8.dp, bottom = 24.dp),
        )

        OutlinedTextField(
            value = state.input,
            onValueChange = viewModel::onInputChange,
            singleLine = true,
            enabled = !state.submitting,
            isError = state.error != null,
            label = { Text(stringResource(R.string.connect_url_label)) },
            placeholder = { Text(stringResource(R.string.connect_url_hint)) },
            keyboardOptions = KeyboardOptions(
                keyboardType = KeyboardType.Uri,
                imeAction = ImeAction.Go,
            ),
            keyboardActions = KeyboardActions(onGo = { viewModel.connect(onConnected) }),
            supportingText = state.error?.let { err ->
                { Text(errorMessage(err), color = MaterialTheme.colorScheme.error) }
            },
            modifier = Modifier.fillMaxWidth(),
        )

        Button(
            onClick = { viewModel.connect(onConnected) },
            enabled = !state.submitting,
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 20.dp),
        ) {
            if (state.submitting) {
                CircularProgressIndicator(
                    strokeWidth = 2.dp,
                    modifier = Modifier.size(20.dp),
                    color = MaterialTheme.colorScheme.onPrimary,
                )
            } else {
                Text(stringResource(R.string.connect_button))
            }
        }
    }
}

@Composable
private fun errorMessage(error: ConnectError): String = when (error) {
    ConnectError.Blank -> stringResource(R.string.connect_error_blank)
    ConnectError.Malformed -> stringResource(R.string.connect_error_malformed)
    ConnectError.UnsupportedScheme -> stringResource(R.string.connect_error_scheme)
    ConnectError.Insecure -> stringResource(R.string.connect_error_insecure)
    ConnectError.NotRunicGateway -> stringResource(R.string.connect_error_not_runic)
    is ConnectError.VersionMismatch -> stringResource(R.string.connect_error_version, error.serverApi)
    ConnectError.Unreachable -> stringResource(R.string.connect_error_unreachable)
    is ConnectError.Server -> stringResource(R.string.connect_error_server, error.status)
}
