package com.handong.smartservice.controller.api;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import com.handong.smartservice._AG;
import com.handong.smartservice.JwtAuth.JwtProvider;
import com.handong.smartservice.component.CtErrorCode;
import com.handong.smartservice.component.CtResponse;
import com.handong.smartservice.component.ErrorCode;
import com.handong.smartservice.component.UserInfo;
import com.handong.smartservice.service.AccountService;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.util.List;
import java.util.Map;
import java.util.HashMap;


@RestController
@RequestMapping("/api")
class AuthController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final AccountService accountService;
    private final PasswordEncoder passwordEncoder;
    private final JwtProvider jwtProvider;


    public AuthController(AccountService accountService, PasswordEncoder passwordEncoder, JwtProvider jwtProvider) {
        this.accountService = accountService;
        this.passwordEncoder = passwordEncoder;
        this.jwtProvider = jwtProvider;
    }

    @RequestMapping(value = "/sign-in.do", method = RequestMethod.POST)
    public CtResponse signIn(HttpServletRequest request, HttpServletResponse response, @RequestBody Map<String, String> body) {
        logger.info("req: " + request.getRequestURI());

        String user_id = body.get("id");
        String user_pw = body.get("pw");

        logger.info("user_id = " + user_id);    //TestComment

        CtResponse result = accountService.getAccount(0L, user_id);
        Map<String, Object> mapAccount = (Map<String, Object>)result.get("result");

        if (mapAccount == null) {    // not found
            result.setErrCode(ErrorCode.INVALID_USER);
            return result;
        }

        if ("2".equals(mapAccount.get("state"))) {  // stopped user
            result.setErrCode(ErrorCode.INVALID_USER);
            return result;
        }

        Long gid = (Long)mapAccount.get("gid");
        logger.info("gid: " + gid);

        String nick_name = (String)mapAccount.get("nick_name");
        Long permission = (Long)mapAccount.get("permission");
        Long biz_group_id = (Long)mapAccount.get("biz_group_id");
        String encPw = (String)mapAccount.get("user_pw");
        // 1 : $2a$10$HaPODuNOvfKE/MD0JxTrX.CxZ4zeGxjmcwaGE.jyx0KzWGQh3vVeG
        // 1234: $2a$10$fg4gH81OiYVm3AItCvKQvOPWnRx8YsXHymIDJI88XCTKk/3Kah092

        // password check
        logger.info("------ enc pw: " + passwordEncoder.encode(user_pw));
        if (passwordEncoder.matches(user_pw, encPw) == false) {
             result.setErrCode(ErrorCode.INVALID_USER);
             return result;
        }

        //mapAccount.put("sval1", jwtProvider.createAccessToken(gid, user_id, nick_name, permission, biz_group_id));
        mapAccount.put("sval1", jwtProvider.createAccessToken(gid, _AG.createUserInfoMap(user_id, nick_name, permission, biz_group_id)));
        String refreshToken = jwtProvider.createRefreshToken(gid);        

        /*
        ResponseCookie cookie = ResponseCookie.from("sval2", refreshToken)
            .httpOnly(true)
            .secure(true)
            .sameSite("Strict")
            .path("/")
            .maxAge(jwtProvider.getRefreshExpire())
            .build();
        */
        ResponseCookie cookie = ResponseCookie.from("sval2", refreshToken)
            .httpOnly(true)
            .secure(false)
            .sameSite("Lax")
            .path("/")
            .build();
        response.addHeader("Set-Cookie", cookie.toString());
        
        return result;
    }

    @RequestMapping(value = "/sign-out.do", method = RequestMethod.POST)
    public CtResponse signOut(HttpServletRequest request, HttpServletResponse response, 
        @RequestBody Map<String, String> body, Authentication authentication) {
        logger.info("req: " + request.getRequestURI());

        Long gid = _AG.toLong(body.get("gid"));
        UserInfo userInfo = (UserInfo)authentication.getPrincipal();
        
        CtResponse result = new CtResponse();
        if (gid != userInfo.getGid()) {
            result.setErrCode(CtErrorCode.UNCORRECT_DATA);
            return result;
        }

        jwtProvider.delete(gid);
        
        return result;
    }

    @PostMapping("/sval2.do")   // security value 2(token refresh)
    public ResponseEntity<?> tokenRefresh(HttpServletRequest request, @CookieValue(value = "sval2", required = false) String refreshToken) {
        logger.info("req: " + request.getRequestURI());

        if (refreshToken == null) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        }

        if (jwtProvider.isValidate(refreshToken) == false) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        }

        Long gid = jwtProvider.getGid(refreshToken);

        logger.info("gid: " + gid);

        CtResponse result = accountService.getAccount(gid, null);
        Map<String, Object> mapAccount = (Map<String, Object>)result.get("result");

        if (mapAccount == null) {    // not found
            result.setErrCode(ErrorCode.INVALID_USER);
            return ResponseEntity.ok(result);
        }

        if ("2".equals(mapAccount.get("state"))) {  // stopped user
            result.setErrCode(ErrorCode.INVALID_USER);
            return ResponseEntity.ok(result);
        }

        String user_id = (String)mapAccount.get("user_id");
        String nick_name = (String)mapAccount.get("user_id");
        Long permission = (Long)mapAccount.get("permission");
        Long biz_group_id = (Long)mapAccount.get("biz_group_id");
        //String newAccessToken = jwtProvider.createAccessToken(gid, user_id, nick_name, permission, biz_group_id);
        String newAccessToken = jwtProvider.createAccessToken(gid, _AG.createUserInfoMap(user_id, nick_name, permission, biz_group_id));
        
        mapAccount.put("sval1", newAccessToken);

        return ResponseEntity.ok(result);
    }
}
