package com.hclsoftware.sso.kerberos.controller;

import com.hclsoftware.sso.kerberos.dto.LoginDto;
import com.hclsoftware.sso.kerberos.service.IBMiConnectorService;
import com.hclsoftware.sso.kerberos.utils.Serializer;
import com.ibm.as400.access.AS400;
import com.ibm.as400.security.auth.ProfileTokenCredential;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider;
import org.springframework.web.bind.annotation.*;

import javax.security.auth.login.LoginException;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.net.URI;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Base64;
import java.util.function.Consumer;

@RestController
@RequestMapping("/api/auth")
public class AuthController {

    @Autowired
    private KerberosAuthenticationProvider kerberosAuthenticationProvider;
    @Autowired
    private IBMiConnectorService ibMiConnectorService;

    @PostMapping("/sign-in")
    public ResponseEntity authenticateUser(@RequestBody LoginDto loginDto) throws IOException {

        Authentication authentication = kerberosAuthenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        ProfileTokenCredential profileTokenCredential;
        try {
            profileTokenCredential = ibMiConnectorService.ibmIMc();
        } catch (PropertyVetoException e) {
            throw new RuntimeException(e);
        } catch (GSSException e) {
            throw new RuntimeException(e);
        } catch (LoginException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        byte[] serialize = Serializer.serialize(profileTokenCredential);//SerializationUtils.serialize(gssCredential);
        String token = Base64.getEncoder().encodeToString(serialize);
        //return new ResponseEntity<>(gssCredential1, HttpStatus.OK);
        return new ResponseEntity<>(token, HttpStatus.OK);
    }

    @PostMapping("/gssToken")
    public ResponseEntity getGssCredential(@RequestBody LoginDto loginDto) throws IOException {

        Authentication authentication = kerberosAuthenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        GSSCredential gssCredential;
        try {
            gssCredential = ibMiConnectorService.getGssCredential();
        } catch (GSSException e) {
            throw new RuntimeException(e);
        } catch (Exception e){
            throw new RuntimeException(e);
        }
        /*byte[] serialize = Serializer.serialize(gssCredential);//SerializationUtils.serialize(gssCredential);
        String token = Base64.getEncoder().encodeToString(serialize);*/
        //return new ResponseEntity<>(gssCredential1, HttpStatus.OK);
        //return new ResponseEntity<>(token, HttpStatus.OK);
        return new ResponseEntity<>(gssCredential, HttpStatus.OK);
    }

    @PostMapping("/authenticate")
    public ResponseEntity authenticate(@RequestBody LoginDto loginDto) throws IOException {

        Authentication authentication = kerberosAuthenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword()));
        /*SecurityContextHolder.getContext().setAuthentication(authentication);
        GSSCredential gssCredential;
        try {
            gssCredential = ibMiConnectorService.getGssCredential();
        } catch (GSSException e) {
            throw new RuntimeException(e);
        } catch (Exception e){
            throw new RuntimeException(e);
        }*/
        byte[] serialize = Serializer.serialize(authentication);//SerializationUtils.serialize(gssCredential);
        String token = Base64.getEncoder().encodeToString(serialize);
        //return new ResponseEntity<>(gssCredential1, HttpStatus.OK);
        return new ResponseEntity<>(token, HttpStatus.OK);
    }

    @PostMapping("/getAs400")
    public ResponseEntity getAs400(@RequestBody LoginDto loginDto) throws IOException {

        Authentication authentication = kerberosAuthenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        AS400 as400;
        try {
            as400 = ibMiConnectorService.getAs400();
        } catch (GSSException e) {
            throw new RuntimeException(e);
        }
        byte[] serialize = Serializer.serialize(as400);//SerializationUtils.serialize(gssCredential);
        String token = Base64.getEncoder().encodeToString(serialize);
        //return new ResponseEntity<>(gssCredential1, HttpStatus.OK);
        return new ResponseEntity<>(token, HttpStatus.OK);
    }

    @PostMapping(value = "/sign-in-userId", produces =  MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity authenticateUser2(@RequestBody LoginDto loginDto) throws IOException, PropertyVetoException, GSSException, LoginException {

        Authentication authentication = kerberosAuthenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);

        return new ResponseEntity<>(ibMiConnectorService.getResponseDtoForIbmIMc(), HttpStatus.OK);
    }


}
