/*
 * F7cloud Talk - Android Client
 *
 * SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

package ru.f7cloud.talk.threadsoverview

import android.content.Intent
import android.os.Bundle
import android.text.format.DateUtils
import android.util.Log
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModelProvider
import autodagger.AutoInjector
import ru.f7cloud.talk.R
import ru.f7cloud.talk.activities.BaseActivity
import ru.f7cloud.talk.api.NcApi
import ru.f7cloud.talk.application.F7cloudTalkApplication
import ru.f7cloud.talk.chat.ChatActivity
import ru.f7cloud.talk.chat.ChatActivity.Companion.TAG
import ru.f7cloud.talk.components.ColoredStatusBar
import ru.f7cloud.talk.components.StandardAppBar
import ru.f7cloud.talk.data.database.mappers.asModel
import ru.f7cloud.talk.models.json.threads.ThreadInfo
import ru.f7cloud.talk.threadsoverview.components.ThreadRow
import ru.f7cloud.talk.threadsoverview.viewmodels.ThreadsOverviewViewModel
import ru.f7cloud.talk.users.UserManager
import ru.f7cloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
import ru.f7cloud.talk.utils.bundle.BundleKeys.KEY_THREAD_ID
import javax.inject.Inject

@AutoInjector(F7cloudTalkApplication::class)
class ThreadsOverviewActivity : BaseActivity() {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory

    @Inject
    lateinit var ncApi: NcApi

    @Inject
    lateinit var userManager: UserManager

    lateinit var threadsOverviewViewModel: ThreadsOverviewViewModel

    var threadsSourceUrl: String = ""
    var appbarTitle: String = ""

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        F7cloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
        threadsOverviewViewModel = ViewModelProvider(
            this,
            viewModelFactory
        )[ThreadsOverviewViewModel::class.java]

        val colorScheme = viewThemeUtils.getColorScheme(this)

        val extras: Bundle? = intent.extras
        threadsSourceUrl = extras?.getString(KEY_THREADS_SOURCE_URL).orEmpty()
        appbarTitle = extras?.getString(KEY_APPBAR_TITLE).orEmpty()

        setContent {
            val backgroundColor = colorResource(id = R.color.bg_default)

            MaterialTheme(
                colorScheme = colorScheme
            ) {
                ColoredStatusBar()
                Scaffold(
                    modifier = Modifier
                        .statusBarsPadding(),
                    topBar = {
                        StandardAppBar(
                            title = appbarTitle,
                            null
                        )
                    },
                    content = { paddingValues ->
                        val uiState by threadsOverviewViewModel.threadsListState.collectAsState()

                        Column(
                            Modifier
                                .padding(0.dp, paddingValues.calculateTopPadding(), 0.dp, 0.dp)
                                .background(backgroundColor)
                                .fillMaxSize()
                        ) {
                            ThreadsOverviewScreen(
                                uiState,
                                onThreadClick = { roomToken, threadId ->
                                    navigateToChatActivity(roomToken, threadId)
                                }
                            )
                        }
                    }
                )
            }
        }
    }

    private fun navigateToChatActivity(roomToken: String, threadId: Int) {
        val bundle = Bundle()
        bundle.putString(KEY_ROOM_TOKEN, roomToken)
        bundle.putLong(KEY_THREAD_ID, threadId.toLong())
        val chatIntent = Intent(context, ChatActivity::class.java)
        chatIntent.putExtras(bundle)
        startActivity(chatIntent)
    }

    override fun onResume() {
        super.onResume()
        supportActionBar?.show()
        threadsOverviewViewModel.init(threadsSourceUrl)
    }

    companion object {
        val TAG = ThreadsOverviewActivity::class.java.simpleName
        val KEY_APPBAR_TITLE = "KEY_APPBAR_TITLE"
        val KEY_THREADS_SOURCE_URL = "KEY_THREADS_SOURCE_URL"
    }
}

@Composable
fun ThreadsOverviewScreen(
    uiState: ThreadsOverviewViewModel.ThreadsListUiState,
    onThreadClick: (roomToken: String, threadId: Int) -> Unit
) {
    when (val state = uiState) {
        is ThreadsOverviewViewModel.ThreadsListUiState.None -> {
            LoadingIndicator()
        }

        is ThreadsOverviewViewModel.ThreadsListUiState.Success -> {
            ThreadsList(
                threads = state.threadsList!!,
                onThreadClick = onThreadClick
            )
        }

        is ThreadsOverviewViewModel.ThreadsListUiState.Error -> {
            Log.e(TAG, "Error when retrieving threads", uiState.exception)
            ErrorView(message = stringResource(R.string.nc_common_error_sorry))
        }
    }
}

@Composable
fun ThreadsList(threads: List<ThreadInfo>, onThreadClick: (roomToken: String, threadId: Int) -> Unit) {
    val space = ' '
    if (threads.isEmpty()) {
        Box(
            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp),
            contentAlignment = Alignment.Center
        ) {
            Text(stringResource(R.string.threads_list_empty))
        }
        return
    }

    LazyColumn(
        modifier = Modifier.fillMaxSize(),
        contentPadding = PaddingValues(horizontal = 8.dp, vertical = 8.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        items(
            items = threads,
            key = { threadInfo -> threadInfo.thread!!.id }
        ) { threadInfo ->
            val messageJson = threadInfo.last ?: threadInfo.first
            val messageModel = messageJson?.asModel()

            ThreadRow(
                roomToken = threadInfo.thread!!.roomToken,
                threadId = threadInfo.thread!!.id,
                title = threadInfo.thread?.title.orEmpty(),
                numReplies = pluralStringResource(
                    R.plurals.thread_replies,
                    threadInfo.thread?.numReplies ?: 0,
                    threadInfo.thread?.numReplies ?: 0
                ),
                secondLineTitle = messageModel?.actorDisplayName?.substringBefore(space)?.let { "$it:" }.orEmpty(),
                secondLine = messageModel?.text.orEmpty(),
                date = getLastActivityDate(threadInfo), // replace with value from api when available
                onClick = onThreadClick
            )
        }
        item {
            Spacer(modifier = Modifier.height(32.dp))
        }
    }
}

@Suppress("MagicNumber")
private fun getLastActivityDate(threadInfo: ThreadInfo): String {
    val oneSecond = 1000L

    val lastActivityTimestamp = threadInfo.thread?.lastActivity ?: 0

    val lastActivityDate = DateUtils.getRelativeTimeSpanString(
        lastActivityTimestamp.times(oneSecond),
        System.currentTimeMillis(),
        0,
        DateUtils.FORMAT_ABBREV_RELATIVE
    ).toString()
    return lastActivityDate
}

@Composable
fun LoadingIndicator() {
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        CircularProgressIndicator()
    }
}

@Composable
fun ErrorView(message: String) {
    Box(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        contentAlignment = Alignment.Center
    ) {
        Text(text = message, color = MaterialTheme.colorScheme.error)
    }
}
