package kr.lunaticbum.back.lun.controllers

import com.google.gson.Gson
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import kr.lunaticbum.back.lun.configs.GlobalEnvironment
import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.ApiKeyWordKey
import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.EncType11
import kr.lunaticbum.back.lun.configs.GlobalEnvironment.Companion.EncTypeKey
import kr.lunaticbum.back.lun.configs.JwtRule
import kr.lunaticbum.back.lun.model.*
import kr.lunaticbum.back.lun.service.JwtService
import kr.lunaticbum.back.lun.utils.JwtUtil
import kr.lunaticbum.back.lun.utils.LogService
import kr.lunaticbum.back.lun.utils.extractModelData
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType
import org.springframework.http.ResponseCookie
import org.springframework.http.ResponseEntity
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.web.bind.annotation.*
import org.springframework.web.reactive.function.client.WebClient

import java.io.File
import java.util.*


@RestController
@RequestMapping("/user")
class UserController {


    @Autowired
    lateinit var globalEvv : GlobalEnvironment

    @Autowired
    lateinit var logService: LogService

    @Autowired
    lateinit var userManager: UserManager
    @Autowired
    lateinit var jwtService : JwtService

    @GetMapping("join")
    fun hello(httpServletRequest: HttpServletRequest): ResultMV {
        logService.log("onJoin")
        val vm = ResultMV("content/user/join")
//        when(System.currentTimeMillis() % 5L) {
//            0L -> vm.modelMap.put(EncTypeKey,"T4")
//            1L ->    vm.modelMap.put(EncTypeKey,"T3")
//            2L ->    vm.modelMap.put(EncTypeKey,"T2")
//            else -> vm.modelMap.put(EncTypeKey,"T0")
//        }

        val file = File("/")

        logService.log(file.absolutePath)
        vm.modelMap.put(EncTypeKey,EncType11)
        vm.modelMap.put(ApiKeyWordKey,"JOIN")
        return vm
    }

    @GetMapping("login")
    fun userLogin(httpServletRequest: HttpServletRequest): ResultMV {
        logService.log("onJoin")
        val vm = ResultMV("content/user/login")
        vm.modelMap.put(EncTypeKey,EncType11)
        vm.modelMap.put(ApiKeyWordKey,"LOGIN")
        return vm
    }


    @ResponseBody
    @PostMapping("login.ajax")
    fun login(httpServletRequest: HttpServletRequest,   @RequestBody jsonString: String) : ResponseEntity<LoginResult> {
       try {

           logService.log(httpServletRequest.requestURI)
           logService.log(jsonString)
           var lResultCode = 0
           var lResultMsg = "Suscces"
           var u : UserDetails? = null
           var user : User? = null
           var tokenData : TokenData? = null
           jsonString.extractModelData { exception, originDataString ->
               if (exception == null) {
                   logService.log(originDataString)
                   val target = Gson().fromJson(originDataString, User::class.java) ?: User()
                   user = userManager.findById(target.user_id?.trim() ?: "")?.block()
                   if (user == null && ((target.user_id?.trim()?.length ?: 0) > 3 == true)) {
                       user = userManager.findByEmail(target.user_id?.trim() ?: "")?.block()
                   }
                   if (user != null) {
                       if(userManager.isCorrectUser(user!!,target.user_pw!!)){
                           tokenData = jwtService.generate(user!!)
                       } else {
                           lResultMsg = "is wrong infomation id or passord"
                           lResultCode = 7100
                       }
                   } else {
                       lResultMsg = "not founding user[can't find same id,email.. ]"
                       lResultCode = 7100
                   }
               } else {
                   exception.printStackTrace()
                   lResultMsg = exception.message ?: "unknown exception"
                   lResultCode = 7999
               }
           }
           val responce = ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).headers {

           }.body(LoginResult().apply {
               this.isOk = lResultCode == 0
               this.resultCode = lResultCode
               this.resultMsg = lResultMsg
               this.token = setTokenToCookie(JwtRule.ACCESS_PREFIX.value, tokenData?.tokenKey ?: "", globalEvv.ACCESS_EXPIRATION / 1000).toString().replace("access=","")
               this.refresh = setTokenToCookie(JwtRule.REFRESH_PREFIX.value, tokenData?.refreshToken ?: "", globalEvv.REFRESH_EXPIRATION / 1000).toString().replace("refresh=","")
           }).apply {


           }

           return responce
       }catch (e: Exception){
           return ResponseEntity.internalServerError().contentType(MediaType.APPLICATION_JSON).headers {

           }.body(LoginResult().apply {
               this.isOk = false
               this.resultCode = -999
               this.resultMsg = e.message ?: "unknown exception"
               this.token = ""
               this.refresh = ""
           }).apply {


           }
       }
    }


    private fun setTokenToCookie(tokenPrefix: String, token: String, maxAgeSeconds: Long): ResponseCookie {
        return ResponseCookie.from(tokenPrefix, token)
            .path("/")
            .maxAge(maxAgeSeconds)
            .httpOnly(true)
            .sameSite("None")
            .secure(true)
            .build()
    }

    @ResponseBody
    @PostMapping("logout.ajax")
    fun logout(httpServletRequest: HttpServletRequest) : ResponseEntity<ResponceResult> {
        val responce = ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(ResponceResult().apply {

        })
        return responce
    }

    @ResponseBody
    @PostMapping("joinUser.ajax")
    fun joinUser(httpServletRequest: HttpServletRequest, @RequestBody jsonString: String) : ResponseEntity<ResponceResult> {
        logService.log("${httpServletRequest.requestURI}")
        logService.log(jsonString)
        var lResultCode = 0
        var lResultMsg = "Suscces"
        var u : User? = null
        jsonString.extractModelData { exception, s ->
            if (exception == null) {
                val user = Gson().fromJson(s, User::class.java) ?: User()
                if (user.checkValid() == false) {
                    lResultCode = 7009
                    lResultMsg = "user insert Fail  Reason : Not Correct Data"
                }else if (userManager.findById(user!!.user_id!!)?.block() != null) {
                    lResultCode = 7001
                    lResultMsg = "user insert Fail  Reason : already has Same Id"
                }else if (userManager.findByEmail(user!!.user_email!!)?.block() != null ) {
                    lResultCode = 7002
                    lResultMsg = "user insert Fail  Reason : already has Same Email"
                }  else {
                    u = userManager.save(user).block()
                }
            } else {
                exception.printStackTrace()
                lResultMsg = exception.message ?: "unknown exception"
                lResultCode = 7999
            }
        }
        val responce = ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(ResponceResult().apply {
            this.resultCode = lResultCode
            this.resultMsg = lResultMsg
        })
        return responce
    }

    @ResponseBody
    @GetMapping("test/{path}")
    fun test(@PathVariable path : String): String {
        logService.log("path >>> $path")
        val client = WebClient.create()
        return client.get()
            .uri("https://api.telegram.org/${globalEvv.telegramBotKey}/sendMessage?chat_id=${globalEvv.telegramMyId}&text=${path}")
            .retrieve()
            .bodyToMono(String::class.java).block() ?: "FAIL"
    }
}