package de.htwsaar.webshop.controller;

import de.htwsaar.webshop.model.OrderModel;
import de.htwsaar.webshop.model.OrderStatus;
import de.htwsaar.webshop.repository.entities.Order;
import de.htwsaar.webshop.service.OrderService;
import de.htwsaar.webshop.service.SessionService;
import de.htwsaar.webshop.service.ValidatorService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

import static de.htwsaar.webshop.config.ControllerPathConfig.ORDER_BASE;
import static de.htwsaar.webshop.config.ControllerPathConfig.ORDER_GET_ALL;
import static de.htwsaar.webshop.config.ParameterConfig.*;
import static de.htwsaar.webshop.util.LoggerUtil.logRequest;

@RestController
@Slf4j
public class OrderController {

    private final OrderService orderService;
    private final ValidatorService validatorService;
    private final SessionService sessionService;

    @Autowired
    public OrderController(OrderService orderService, ValidatorService validatorService, SessionService sessionService) {
        this.orderService = orderService;
        this.validatorService = validatorService;
        this.sessionService = sessionService;
    }

    @RequestMapping(path = ORDER_GET_ALL, method = RequestMethod.GET, produces = "application/json")
    public ResponseEntity<List<OrderModel>> getAll(HttpServletRequest request,
                                                   @RequestParam(value = PARAM_CUSTOMER_ID) Long customerId) {
        logRequest(request);
        List<Order> orders = orderService.getAllOrders(customerId);
        if (orders.isEmpty()) {
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }
        return ResponseEntity.ok(orders.stream().map(Order::toModel).toList());
    }

    @RequestMapping(path = ORDER_GET_ALL, method = RequestMethod.TRACE, produces = "application/json")
    public ResponseEntity<List<OrderModel>> getAll(HttpServletRequest request,
                                                   @RequestParam(value = PARAM_EMAIL) String email,
                                                   @RequestParam(value = PARAM_SESSION) UUID token) {
        logRequest(request);
        if (!sessionService.isAdmin(token, email)) {
            log.warn("[{}] Account isn't allowed to make request {}", request.getRequestURI(), email);
            return ResponseEntity.badRequest().build();
        }

        return ResponseEntity.ok(orderService.findAll().stream().map(Order::toModel).toList());
    }

    @RequestMapping(path = ORDER_BASE, method = RequestMethod.GET, produces = "application/json")
    public ResponseEntity<OrderModel> get(HttpServletRequest request,
                                     @RequestParam(value = PARAM_ID) Long orderId) {
        logRequest(request);
        Order order = orderService.getOrderById(orderId);
        if (order == null) {
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }
        return ResponseEntity.ok(order.toModel());
    }

    @RequestMapping(path = ORDER_BASE, method = RequestMethod.POST, produces = "application/json")
    public ResponseEntity<Boolean> add(HttpServletRequest request,
                                       @RequestBody OrderModel order) {
        logRequest(request);

        if (validatorService.isInvalid(order)) {
            log.warn("[{}] failed Validation, sending bad request", request.getRequestURI());
            return ResponseEntity.badRequest().body(false);
        }
        order.setId(null);
        order.getOrderItems().forEach(orderItem -> orderItem.setId(null));
        Order saved = orderService.save(order);
        return ResponseEntity.ok(saved != null);
    }

    @RequestMapping(path = ORDER_BASE, method = RequestMethod.PATCH, produces = "application/json")
    public ResponseEntity<Boolean> update(HttpServletRequest request,
                                          @RequestParam(value = PARAM_ID) Long orderId,
                                          @RequestParam(value = PARAM_STATUS) OrderStatus status) {
        logRequest(request);
        if (orderId == null) {
            return ResponseEntity.badRequest().build();
        }
        Order order = orderService.getOrderById(orderId);
        if (order == null) {
            return ResponseEntity.notFound().build();
        }
        order.setStatus(status);
        return ResponseEntity.ok(orderService.save(order) != null);
    }

    @RequestMapping(path = ORDER_BASE, method = RequestMethod.DELETE, produces = "application/json")
    public ResponseEntity<Boolean> delete(HttpServletRequest request,
                                          @RequestParam(value = PARAM_ID) Long orderId) {
        logRequest(request);
        if (orderId == null) {
            log.warn("[{}] got invalid orderId", request.getRequestURI());
            return ResponseEntity.badRequest().body(false);
        }
        if (orderService.getOrderById(orderId) != null) {
            log.warn("[{}] got invalid orderId", request.getRequestURI());
            return ResponseEntity.badRequest().body(false);
        }
        orderService.delete(orderId);
        return ResponseEntity.ok().build();
    }
}
