package de.avatic.lcc.controller.configuration;

import de.avatic.lcc.dto.generic.NodeDTO;
import de.avatic.lcc.dto.configuration.nodes.view.NodeDetailDTO;
import de.avatic.lcc.dto.configuration.nodes.update.NodeUpdateDTO;
import de.avatic.lcc.dto.generic.NodeType;
import de.avatic.lcc.dto.configuration.nodes.userNodes.AddUserNodeDTO;
import de.avatic.lcc.repositories.pagination.SearchQueryResult;
import de.avatic.lcc.service.api.GeoApiService;
import de.avatic.lcc.service.access.NodeService;
import de.avatic.lcc.service.access.UserNodeService;
import de.avatic.lcc.util.Check;
import jakarta.validation.constraints.Min;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/nodes")
@Validated
@PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING')")
public class NodeController {

    private final NodeService nodeService;
    private final GeoApiService geoApiService;
    private final UserNodeService userNodeService;

    public NodeController(NodeService nodeService, GeoApiService geoApiService, UserNodeService userNodeService) {
        this.nodeService = nodeService;
        this.geoApiService = geoApiService;
        this.userNodeService = userNodeService;
    }

    @GetMapping({"","/"})
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING')")
    public ResponseEntity<List<NodeDTO>> listNodes(@RequestParam(required = false) String filter, @RequestParam(defaultValue = "1") @Min(1) Integer page, @RequestParam(defaultValue = "20") @Min(1) Integer limit) {
        nodeService.listNodes(filter, page, limit);

        SearchQueryResult<NodeDTO> nodes = nodeService.listNodes(filter, page, limit);

        return ResponseEntity.ok()
                .header("X-Total-Count", String.valueOf(nodes.getTotalElements()))
                .header("X-Page-Count", String.valueOf(nodes.getTotalPages()))
                .header("X-Current-Page", String.valueOf(page))
                .body(nodes.toList());
    }

    @GetMapping({"/search", "/search/"})
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING')")
    public ResponseEntity<List<NodeDTO>> searchNodes(@RequestParam(required = false) String filter, @RequestParam(defaultValue = "10") @Min(1) int limit, @RequestParam(name = "node_type", required = false) NodeType nodeType, @RequestParam(name = "include_user_node", defaultValue = "false") boolean includeUserNode) {
        return ResponseEntity.ok(nodeService.searchNode(filter, limit, nodeType, includeUserNode));
    }

    @GetMapping({"/{id}","/{id}/"})
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING')")
    public ResponseEntity<NodeDetailDTO> getNode(@PathVariable Integer id) {
        return ResponseEntity.ok(nodeService.getNode(id));
    }

    @DeleteMapping({"/{id}","/{id}/"})
    @PreAuthorize("hasRole('SUPER')")
    public ResponseEntity<Integer> deleteNode(@PathVariable Integer id) {
        return ResponseEntity.ok(nodeService.deleteNode(id));
    }

    @PutMapping({"/{id}","/{id}/"})
    @PreAuthorize("hasRole('SUPER')")
    public ResponseEntity<Integer> updateNode(@PathVariable Integer id, @RequestBody NodeUpdateDTO node) {
        Check.equals(id, node.getId());
        return ResponseEntity.ok(nodeService.updateNode(node));
    }

    @GetMapping({"/locate", "/locate/"})
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING', 'CALCULATION')")
    public ResponseEntity<NodeDTO> locateNode(@RequestParam String address) {
        return ResponseEntity.ok(geoApiService.locateNode(address));
    }

    @PutMapping({"","/"})
    @PreAuthorize("hasAnyRole('SUPER', 'CALCULATION')")
    public ResponseEntity<NodeDTO> addUserNode(@RequestBody AddUserNodeDTO node) {
        return ResponseEntity.ok(userNodeService.addUserNode(node));
    }
}
