package eu.darken.bluemusic.upgrade.ui

import android.widget.Toast
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.twotone.AutoAwesome
import androidx.compose.material.icons.twotone.Favorite
import androidx.compose.material.icons.twotone.Info
import androidx.compose.material.icons.twotone.Verified
import androidx.compose.material3.Button
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LifecycleEventEffect
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import eu.darken.bluemusic.R
import eu.darken.bluemusic.common.compose.Preview2
import eu.darken.bluemusic.common.compose.PreviewWrapper
import eu.darken.bluemusic.common.error.ErrorEventHandler
import eu.darken.bluemusic.common.navigation.Nav
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle

// Which presentation the FOSS upgrade screen shows: the classic support pitch, or one of the
// status views behind the settings "supporter status" entry.
internal enum class FossUpgradeView {
    PITCH,
    STATUS_FREE,
    STATUS_UPGRADED,
}

@Composable
fun UpgradeScreenHost(
    route: Nav.Main.Upgrade,
    vm: UpgradeViewModel = hiltViewModel(),
) {
    LaunchedEffect(route) { vm.bindRoute(route) }
    ErrorEventHandler(vm)

    val context = LocalContext.current
    val snackbarHostState = remember { SnackbarHostState() }
    // Seeded from the ViewModel's handle-backed pending launch: after a process death while the
    // sponsor page was open, a blank tracker would swallow the very first return. The handle is the
    // authority on whether a return is still expected, so it reconstructs the tracker's state.
    val sponsorReturnTracker = remember(vm) {
        SponsorReturnTracker(wentToBackground = vm.hasPendingSponsorLaunch())
    }

    LaunchedEffect(Unit) {
        vm.snackbarEvents.collect { stringRes ->
            snackbarHostState.showSnackbar(context.getString(stringRes))
        }
    }

    LaunchedEffect(Unit) {
        vm.toastEvents.collect { stringRes ->
            Toast.makeText(context, context.getString(stringRes), Toast.LENGTH_LONG).show()
        }
    }

    LifecycleEventEffect(Lifecycle.Event.ON_STOP) {
        sponsorReturnTracker.onStop()
    }
    LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
        if (sponsorReturnTracker.consumeResumeReturn()) {
            vm.checkSponsorReturn()
        }
    }

    val state by vm.state.collectAsStateWithLifecycle()

    UpgradeScreen(
        // Until the route binding lands (one frame): the default route keeps rendering the pitch
        // exactly as before, only the manage route waits for the status decision.
        view = state.view ?: FossUpgradeView.PITCH.takeIf { !route.manage },
        supporterSince = state.supporterSince,
        snackbarHostState = snackbarHostState,
        onGithubSponsors = vm::goGithubSponsors,
        onOpenSponsors = vm::openSponsors,
        onShowUpgradeOptions = vm::onShowUpgradeOptions,
        onNavigateUp = vm::navUp,
    )
}

@Composable
internal fun UpgradeScreen(
    view: FossUpgradeView? = FossUpgradeView.PITCH,
    supporterSince: Instant? = null,
    snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
    onGithubSponsors: () -> Unit = {},
    onOpenSponsors: () -> Unit = {},
    onShowUpgradeOptions: () -> Unit = {},
    onNavigateUp: () -> Unit = {},
) {
    UpgradeScreenScaffold(
        // Status views describe the existing install, not a support ask — they get the composed
        // flavor title, with the postfix highlighted for supporters like the dashboard does it.
        title = if (view == FossUpgradeView.PITCH) {
            AnnotatedString(stringResource(R.string.upgrade_screen_title))
        } else {
            upgradeScreenTitle(upgraded = view == FossUpgradeView.STATUS_UPGRADED)
        },
        onNavigateUp = onNavigateUp,
        snackbarHostState = snackbarHostState,
    ) { paddingValues ->
        when (view) {
            null -> Unit // Route not bound yet (single frame); content lands with the next state.
            FossUpgradeView.PITCH -> UpgradePitchContent(
                paddingValues = paddingValues,
                onGithubSponsors = onGithubSponsors,
            )

            FossUpgradeView.STATUS_FREE -> UpgradeStatusFreeContent(
                paddingValues = paddingValues,
                onShowUpgradeOptions = onShowUpgradeOptions,
            )

            FossUpgradeView.STATUS_UPGRADED -> UpgradeStatusUpgradedContent(
                paddingValues = paddingValues,
                supporterSince = supporterSince,
                onOpenSponsors = onOpenSponsors,
            )
        }
    }
}

@Composable
private fun UpgradePitchContent(
    paddingValues: PaddingValues,
    onGithubSponsors: () -> Unit,
) {
    UpgradeScreenContent(
        paddingValues = paddingValues,
    ) {
        UpgradeHeroCard(
            text = stringResource(R.string.upgrade_screen_preamble),
            colors = CardDefaults.elevatedCardColors(
                containerColor = MaterialTheme.colorScheme.primaryContainer,
                contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
            ),
        )

        UpgradeSectionCard(
            title = stringResource(R.string.upgrade_screen_why_title),
            icon = Icons.TwoTone.AutoAwesome,
        ) {
            UpgradeFeatureList(text = stringResource(R.string.upgrade_screen_why_body))
        }

        UpgradeSectionCard(
            title = stringResource(R.string.upgrade_screen_how_title),
            icon = Icons.TwoTone.Favorite,
        ) {
            UpgradeSectionBody(text = stringResource(R.string.upgrade_screen_how_body))
        }

        UpgradeActionCard(
            colors = CardDefaults.elevatedCardColors(
                containerColor = MaterialTheme.colorScheme.tertiaryContainer,
                contentColor = MaterialTheme.colorScheme.onTertiaryContainer,
            ),
        ) {
            Button(
                onClick = onGithubSponsors,
                modifier = Modifier
                    .fillMaxWidth()
                    .testTag(UpgradeScreenTags.FOSS_SPONSOR),
            ) {
                Text(stringResource(R.string.upgrade_screen_sponsor_action))
            }

            UpgradeHintText(text = stringResource(R.string.upgrade_screen_sponsor_action_hint))
        }
    }
}

@Composable
private fun UpgradeStatusFreeContent(
    paddingValues: PaddingValues,
    onShowUpgradeOptions: () -> Unit,
) {
    UpgradeScreenContent(
        paddingValues = paddingValues,
    ) {
        UpgradeHeader()

        UpgradeSectionCard(
            title = stringResource(R.string.upgrade_screen_status_free_title),
            icon = Icons.TwoTone.Info,
            modifier = Modifier.testTag(UpgradeScreenTags.FOSS_STATUS_FREE),
        ) {
            UpgradeSectionBody(text = stringResource(R.string.upgrade_screen_status_free_body))
            Button(
                onClick = onShowUpgradeOptions,
                modifier = Modifier
                    .fillMaxWidth()
                    .testTag(UpgradeScreenTags.FOSS_SHOW_OPTIONS),
            ) {
                Text(stringResource(R.string.upgrade_screen_status_free_action))
            }
        }
    }
}

@Composable
private fun UpgradeStatusUpgradedContent(
    paddingValues: PaddingValues,
    supporterSince: Instant? = null,
    onOpenSponsors: () -> Unit,
) {
    UpgradeScreenContent(
        paddingValues = paddingValues,
    ) {
        UpgradeHeader()

        UpgradeSectionCard(
            title = stringResource(R.string.upgrade_screen_supporter_status_title),
            icon = Icons.TwoTone.Verified,
            modifier = Modifier.testTag(UpgradeScreenTags.FOSS_STATUS_UPGRADED),
            colors = CardDefaults.elevatedCardColors(
                containerColor = MaterialTheme.colorScheme.secondaryContainer,
                contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
            ),
        ) {
            Text(
                text = stringResource(R.string.upgrade_screen_supporter_status_body),
                style = MaterialTheme.typography.bodyMedium,
            )
            supporterSince?.let { since ->
                val formatter = remember {
                    DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withZone(ZoneId.systemDefault())
                }
                Text(
                    text = stringResource(R.string.upgrade_screen_supporter_since, formatter.format(since)),
                    style = MaterialTheme.typography.bodySmall,
                )
            }
        }

        UpgradeActionCard {
            OutlinedButton(
                onClick = onOpenSponsors,
                modifier = Modifier
                    .fillMaxWidth()
                    .testTag(UpgradeScreenTags.FOSS_DONATE),
            ) {
                Text(stringResource(R.string.upgrade_screen_supporter_visit_action))
            }
        }
    }
}

internal class SponsorReturnTracker(
    private var wentToBackground: Boolean = false,
) {

    fun onStop() {
        wentToBackground = true
    }

    fun consumeResumeReturn(): Boolean {
        return if (wentToBackground) {
            wentToBackground = false
            true
        } else {
            false
        }
    }
}

@Preview2
@Composable
private fun UpgradeScreenPreview() {
    PreviewWrapper {
        UpgradeScreen()
    }
}

@Preview2
@Composable
private fun UpgradeScreenStatusFreePreview() {
    PreviewWrapper {
        UpgradeScreen(view = FossUpgradeView.STATUS_FREE)
    }
}

@Preview2
@Composable
private fun UpgradeScreenStatusUpgradedPreview() {
    PreviewWrapper {
        UpgradeScreen(
            view = FossUpgradeView.STATUS_UPGRADED,
            supporterSince = Instant.ofEpochMilli(1_700_000_000_000L),
        )
    }
}
