package com.betriebsratkanzlei.legalconsenthub.user

import com.betriebsratkanzlei.legalconsenthub.error.UserAlreadyExistsException
import com.betriebsratkanzlei.legalconsenthub.error.UserNotFoundException
import com.betriebsratkanzlei.legalconsenthub.security.CustomJwtTokenPrincipal
import com.betriebsratkanzlei.legalconsenthub_api.model.CreateUserDto
import com.betriebsratkanzlei.legalconsenthub_api.model.UserDto
import com.betriebsratkanzlei.legalconsenthub_api.model.UserStatus
import jakarta.transaction.Transactional
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.stereotype.Service

@Service
class UserService(
    private val userRepository: UserRepository,
    private val roleConverter: UserRoleConverter
) {

    fun getCurrentUser(): User {
        val principal = SecurityContextHolder.getContext().authentication.principal as CustomJwtTokenPrincipal
        val userId = principal.id ?: throw IllegalStateException("User ID not found")

        return userRepository.findById(userId)
            .orElseThrow { UserNotFoundException(userId) }
    }

    fun createUser(createUserDto: CreateUserDto): User {
        if (userRepository.existsById(createUserDto.id)) {
            throw UserAlreadyExistsException(createUserDto.id)
        }

        val user = User(
            id = createUserDto.id,
            name = createUserDto.name,
            status = createUserDto.status
        )

        createUserDto.organizationRoles?.forEach { (orgId, roles) ->
            roleConverter.setRolesForOrganization(user.organizationRoles, orgId, roles)
        }

        return userRepository.save(user)
    }

    fun getUserById(userId: String): User {
        return userRepository.findById(userId)
            .orElseThrow { UserNotFoundException(userId) }
    }

    @Transactional
    fun updateUser(userId: String, userDto: UserDto): User {
        val user = userRepository.findById(userId)
            .orElseThrow { UserNotFoundException(userId) }

        user.name = userDto.name
        user.status = userDto.status

        user.organizationRoles.clear()
        userDto.organizationRoles.forEach { (orgId, roles) ->
            roleConverter.setRolesForOrganization(user.organizationRoles, orgId, roles)
        }

        return userRepository.save(user)
    }

    @Transactional
    fun updateUserFromJwt(userId: String, jwtOrganizationId: String?, jwtRoles: List<String>?): User {
        val existingUser = userRepository.findById(userId)
            .orElseThrow { UserNotFoundException(userId) }

        if (jwtOrganizationId != null && !jwtRoles.isNullOrEmpty()) {
            existingUser.organizationRoles.removeIf { it.organizationId == jwtOrganizationId }

            jwtRoles.forEach { role ->
                val normalizedRole = role.lowercase().replace("_", "_")
                existingUser.organizationRoles.add(
                    UserOrganizationRole(
                        organizationId = jwtOrganizationId,
                        role = normalizedRole
                    )
                )
            }
        }

        return userRepository.save(existingUser)
    }

    fun deleteUser(userId: String) {
        userRepository.deleteById(userId)
    }
}
