package com.eactive.testmaster.socket.controller;

import com.eactive.testmaster.socket.entity.NettyServerEntity;
import com.eactive.testmaster.socket.service.NettyServerService;
import java.util.List;
import javax.validation.Valid;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/mgmt/socket")
public class NettyServerController {

    private static final String NETTY_SERVER = "nettyServer";
    private static final String NETTY_SERVER_LIST_VIEW = "page/socket/serverList";
    private static final String NETTY_SERVER_EDIT = "page/socket/serverEdit";
    private static final String REDIRECT_TO_LIST = "redirect:/mgmt/socket/list_view.do";

    private final NettyServerService nettyServerService;

    public NettyServerController(NettyServerService nettyServerService) {
        this.nettyServerService = nettyServerService;
    }

    @GetMapping("/list_view.do")
    @Secured("ROLE_MANAGE_NETTY")
    public ModelAndView listView(@ModelAttribute("serverSearch") NettyServerSearch serverSearch,
        Pageable pageable) {
        ModelAndView mav = new ModelAndView(NETTY_SERVER_LIST_VIEW);
        Page<NettyServerEntity> page = nettyServerService.findAll(serverSearch.buildSpecification(), pageable);
        mav.addObject("page", page);
        mav.addObject("pageable", pageable);
        mav.addObject("modelSearch", serverSearch);
        return mav;
    }

    @GetMapping("/create_view.do")
    @Secured("ROLE_MANAGE_NETTY")
    public ModelAndView createView() {
        ModelAndView mav = new ModelAndView(NETTY_SERVER_EDIT);
        mav.addObject(NETTY_SERVER, new NettyServerEntity());
        return mav;
    }

    @GetMapping("/update_view.do")
    @Secured("ROLE_MANAGE_NETTY")
    public ModelAndView updateView(@RequestParam("id") Long id) {
        ModelAndView mav = new ModelAndView(NETTY_SERVER_EDIT);
        NettyServerEntity server = nettyServerService.findById(id);
        mav.addObject(NETTY_SERVER, server);
        return mav;
    }

    @PostMapping("/register.do")
    @Secured("ROLE_MANAGE_NETTY")
    public String register(@Valid @ModelAttribute(NETTY_SERVER) NettyServerEntity server,
        BindingResult bindingResult,
        ModelMap model) {
        if (bindingResult.hasErrors()) {
            model.addAttribute(NETTY_SERVER, server);
            return NETTY_SERVER_EDIT;
        }

        try {
            nettyServerService.createServer(server);
            return REDIRECT_TO_LIST;
        } catch (Exception e) {
            bindingResult.rejectValue("port", "error.port.inuse",
                "Port is already in use or invalid");
            model.addAttribute(NETTY_SERVER, server);
            return NETTY_SERVER_EDIT;
        }
    }

    @PostMapping("/update.do")
    @Secured("ROLE_MANAGE_NETTY")
    public String update(@RequestParam("id") Long id,
        @Valid @ModelAttribute(NETTY_SERVER) NettyServerEntity server,
        BindingResult bindingResult,
        ModelMap model) {
        if (bindingResult.hasErrors()) {
            model.addAttribute(NETTY_SERVER, server);
            return NETTY_SERVER_EDIT;
        }

        try {
            nettyServerService.updateServer(id, server);
            return REDIRECT_TO_LIST;
        } catch (Exception e) {
            bindingResult.rejectValue("port", "error.update.failed",
                "Failed to update server");
            model.addAttribute(NETTY_SERVER, server);
            return NETTY_SERVER_EDIT;
        }
    }

    @PostMapping("/delete.do")
    @Secured("ROLE_MANAGE_NETTY")
    public String delete(@RequestParam("checkedIdForDel") List<String> ids) {
        for (String id : ids) {
            try {
                nettyServerService.deleteServer(Long.parseLong(id));
            } catch (Exception e) {
                // Log error but continue with other deletions
            }
        }
        return REDIRECT_TO_LIST;
    }

    @PostMapping("/servers/{id}/start")
    @Secured("ROLE_MANAGE_NETTY")
    public ResponseEntity<Void> startServer(@PathVariable Long id) {
        try {
            nettyServerService.startServer(id);
            return ResponseEntity.ok().build();
        } catch (Exception e) {
            return ResponseEntity.internalServerError().build();
        }
    }

    @PostMapping("/servers/{id}/stop")
    @Secured("ROLE_MANAGE_NETTY")
    public ResponseEntity<Void> stopServer(@PathVariable Long id) {
        try {
            nettyServerService.stopServer(id);
            return ResponseEntity.ok().build();
        } catch (Exception e) {
            return ResponseEntity.internalServerError().build();
        }
    }
}
