package com.bytesw.bytebot.controller;

import com.bytesw.bytebot.bean.AgentBean;
import com.bytesw.bytebot.controller.bean.ResponseController;
import com.bytesw.bytebot.http.FileValidationResponse;
import com.bytesw.bytebot.service.*;
import com.bytesw.xdf.annotation.ProgramSecurity;
import com.bytesw.xdf.sql.beans.Pagination;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.swagger.annotations.ApiParam;

import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@Log4j2
@RestController
@RequestMapping("/service/agent")
@ProgramSecurity("conversational_agent")
public class AgentController {

    @Autowired
    private AgentService agentService;

    @Autowired
    private FileManagementService fileManagementService;

    @Autowired
    private GsonBuilder gsonBuilder;

    @Autowired
    private OrquestadorService orquestadorService;

    @PostMapping(value = "/page")
    @PreAuthorize("hasPermission(this, 'view')")
    public ResponseEntity<String> paginationConversationalAgent(@RequestBody Pagination<AgentBean> pagination) {
        HttpStatus hs = HttpStatus.OK;

        try {
            agentService.searchByPagination(pagination);
            return new ResponseEntity<>(gsonBuilder.create().toJson(pagination), hs);
        } catch (Exception e) {
            log.error("Error detectado: ", e);

            hs = HttpStatus.INTERNAL_SERVER_ERROR;
            return new ResponseEntity<>(gsonBuilder.create().toJson(ExceptionUtils.getFullStackTrace(e)), hs);
        }
    }

    @GetMapping(value = "/{id}")
    @PreAuthorize("hasPermission(this, 'view')")
    public ResponseEntity<String> getConversartionalAgentById(@ApiParam(value = "id", required = true) @PathVariable("id") Long id) {
        HttpStatus hs = HttpStatus.OK;

        try {
            return new ResponseEntity<>(gsonBuilder.create().toJson(agentService.getAgent(id)), hs);
        } catch (Exception e) {
            log.error("Error detectado: ", e);

            hs = HttpStatus.INTERNAL_SERVER_ERROR;
            return new ResponseEntity<>(gsonBuilder.create().toJson(ExceptionUtils.getFullStackTrace(e)), hs);
        }
    }

    @PutMapping(value = "/")
    @PreAuthorize("hasPermission(this, 'new')")
    public ResponseEntity<String> createConversationalAgent(@RequestBody AgentBean agentBean) {

        HttpStatus hs = HttpStatus.OK;

        try {
            agentService.save(agentBean);
            return new ResponseEntity<>(gsonBuilder.create().toJson(new ResponseController("agent.insert.success", hs.value())), hs);
        } catch (Exception e) {
            log.error("Error detectado: ", e);

            hs = HttpStatus.INTERNAL_SERVER_ERROR;
            return new ResponseEntity<>(gsonBuilder.create().toJson(ExceptionUtils.getFullStackTrace(e)), hs);
        }
    }

    @PutMapping(value = "/{id}")
    @PreAuthorize("hasPermission(this, 'edit')")
    public ResponseEntity<String> updateConversationalAgent(@PathVariable("id") Long id,
                                                       @RequestBody AgentBean agentBean) {
        HttpStatus hs = HttpStatus.OK;

        try {
            if (id != null) {
                agentService.save(agentBean);
                return new ResponseEntity<>(gsonBuilder.create().toJson(new ResponseController("agent.update.success", hs.value())), hs);
            } else {
                hs = HttpStatus.UNAUTHORIZED;
                return new ResponseEntity<>(gsonBuilder.create().toJson(new ResponseController("agent.update.error", hs.value())), hs);
            }
        } catch (Exception e) {
            log.error("Error detectado: ", e);
            hs = HttpStatus.INTERNAL_SERVER_ERROR;
            return new ResponseEntity<>(gsonBuilder.create().toJson(ExceptionUtils.getFullStackTrace(e)), hs);
        }
    }

    @DeleteMapping(value = "/{id}")
    @PreAuthorize("hasPermission(this, 'delete')")
    public ResponseEntity<String> deleteConversationalAgent(@ApiParam(value = "id", required = true) @PathVariable("id") Long id) {
        HttpStatus hs = HttpStatus.OK;

        try {
            if (id != null) {
                boolean deleteValid = agentService.delete(id);

                if (deleteValid) {
                    return new ResponseEntity<>(gsonBuilder.create().toJson(new ResponseController("agent.delete.success", hs.value())), hs);
                } else {
//                    hs = HttpStatus.FAILED_DEPENDENCY;
                    return new ResponseEntity<>(gsonBuilder.create().toJson(new ResponseController("agent.delete.error.integrity", hs.FAILED_DEPENDENCY.value())), hs);
                }
            } else {
                hs = HttpStatus.UNAUTHORIZED;
                return new ResponseEntity<>(gsonBuilder.create().toJson(new ResponseController("agent.delete.error.unauthtorized", hs.value())), hs);
            }
        } catch (Exception e) {
            log.error("Error detectado: ", e);

            hs = HttpStatus.INTERNAL_SERVER_ERROR;
            return new ResponseEntity<>(gsonBuilder.create().toJson(ExceptionUtils.getFullStackTrace(e)), hs);
        }
    }

    @GetMapping(value = "/countries")
    public ResponseEntity<String> getCountries() {
        HttpStatus hs = HttpStatus.OK;

        try {
            return new ResponseEntity<>(gsonBuilder.create().toJson(agentService.getCountries()), hs);
        } catch (Exception e) {
            log.error("Error detectado: ", e);

            hs = HttpStatus.INTERNAL_SERVER_ERROR;
            return new ResponseEntity<>(gsonBuilder.create().toJson(ExceptionUtils.getFullStackTrace(e)), hs);
        }
    }

    @GetMapping(value = "/channels")
    public ResponseEntity<String> getChannels() {
        HttpStatus hs = HttpStatus.OK;

        try {
            return new ResponseEntity<>(gsonBuilder.create().toJson(agentService.getChannels()), hs);
        } catch (Exception e) {
            log.error("Error detectado: ", e);

            hs = HttpStatus.INTERNAL_SERVER_ERROR;
            return new ResponseEntity<>(gsonBuilder.create().toJson(ExceptionUtils.getFullStackTrace(e)), hs);
        }
    }

    @PostMapping("/file-upload")
    public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file, Principal principal) {
        Gson gson = gsonBuilder.create();
        try {
            String uuid = UUID.randomUUID().toString();
            FileValidationResponse response = orquestadorService.executeGenerateBCD(uuid, file);
            response.setUser(principal != null ? principal.getName() : null);
            return new ResponseEntity<>(gson.toJson(response), HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @PutMapping("/file-upload/{uuid}")
    public ResponseEntity<String> uploadFile(@PathVariable("uuid") String uuid, Principal principal) {
        Gson gson = gsonBuilder.create();
        try {
            FileValidationResponse response = orquestadorService.retry(uuid);
            response.setUser(principal != null ? principal.getName() : null);
            return new ResponseEntity<>(gson.toJson(response), HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @DeleteMapping("/file-upload/{uuid}")
    public ResponseEntity<String> deleteBdc(@ApiParam(value = "uuid", required = true) @PathVariable("uuid") String uuid) {
        Gson gson = gsonBuilder.create();
        Map<String, String> resp = new HashMap<>();
        try {
            orquestadorService.deleteBcd(uuid);
            resp.put("message", "OK");
            return new ResponseEntity<>(gson.toJson(resp), HttpStatus.OK);
        } catch (Exception e) {
            resp.put("message", "ERROR");
            return new ResponseEntity<>(gson.toJson(resp), HttpStatus.OK);
        }
    }

    @GetMapping("/synchronize/{id}")
    public ResponseEntity<String> synchronizeFiles(@PathVariable("id") Long id,
                                                   @RequestParam("user") String user) {
        Gson gson = new GsonBuilder().create();
        try {
            agentService.synchronizeFiles(id, user);
            return new ResponseEntity<>(HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping(value = "/")
    @PreAuthorize("hasPermission(this, 'view')")
    public ResponseEntity<String> getAgentAll() {
        HttpStatus hs = HttpStatus.OK;
        try {
            return new ResponseEntity<>(gsonBuilder.create().toJson(agentService.getAgentAll()), hs);
        } catch (Exception e) {
            String info = "Error detectado al obtener informacion";
            hs = HttpStatus.INTERNAL_SERVER_ERROR;
            return new ResponseEntity<>(gsonBuilder.create().toJson(info), hs);
        }
    }

}
