package de.votian.services.controller;

import de.votian.services.dto.GroupwareAppointmentCommandDto;
import de.votian.services.dto.GroupwareAppointmentDto;
import de.votian.services.dto.GroupwareCancellationCommandDto;
import de.votian.services.dto.GroupwareOptionsDto;
import de.votian.services.dto.GroupwareResubmissionCommandDto;
import de.votian.services.dto.UserSessionDto;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.GroupwareService;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.util.List;

@RestController
@RequestMapping("/api/groupware")
public class GroupwareController {

    private final GroupwareService groupwareService;
    private final AccessControlService accessControlService;

    public GroupwareController(GroupwareService groupwareService,
                               AccessControlService accessControlService) {
        this.groupwareService = groupwareService;
        this.accessControlService = accessControlService;
    }

    @GetMapping("/options")
    public ResponseEntity<GroupwareOptionsDto> getOptions(Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canViewGroupware(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(groupwareService.loadOptions(user));
    }

    @GetMapping("/appointments")
    public ResponseEntity<List<GroupwareAppointmentDto>> getAppointments(
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to,
            @RequestParam(required = false) Long userId,
            @RequestParam(required = false) Integer category1,
            @RequestParam(required = false) Integer category3,
            @RequestParam(required = false) Integer category4,
            @RequestParam(required = false) Long customerId,
            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canViewGroupware(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(groupwareService.findAppointments(user, from, to, userId, category1, category3, category4, customerId));
    }

    @PostMapping("/appointments")
    public ResponseEntity<GroupwareAppointmentDto> createAppointment(@RequestBody GroupwareAppointmentCommandDto request,
                                                                     Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageGroupware(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(groupwareService.createAppointment(user, request));
    }

    @PutMapping("/appointments/{appointmentId}")
    public ResponseEntity<GroupwareAppointmentDto> updateAppointment(@PathVariable Long appointmentId,
                                                                     @RequestBody GroupwareAppointmentCommandDto request,
                                                                     Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageGroupware(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(groupwareService.updateAppointment(user, appointmentId, request));
    }

    @PostMapping("/appointments/{appointmentId}/cancel")
    public ResponseEntity<Void> cancelAppointment(@PathVariable Long appointmentId,
                                                  @RequestBody(required = false) GroupwareCancellationCommandDto request,
                                                  Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageGroupware(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        groupwareService.cancelAppointment(user, appointmentId, request);
        return ResponseEntity.ok().build();
    }

    @PostMapping("/appointments/{appointmentId}/confirm")
    public ResponseEntity<GroupwareAppointmentDto> confirmAppointment(@PathVariable Long appointmentId,
                                                                      Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageGroupware(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(groupwareService.confirmAppointment(user, appointmentId));
    }

    @PostMapping("/appointments/{appointmentId}/finish")
    public ResponseEntity<GroupwareAppointmentDto> finishAppointment(@PathVariable Long appointmentId,
                                                                     Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageGroupware(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(groupwareService.finishAppointment(user, appointmentId));
    }

    @PostMapping("/appointments/{appointmentId}/resubmission")
    public ResponseEntity<GroupwareAppointmentDto> resubmitAppointment(@PathVariable Long appointmentId,
                                                                       @RequestBody GroupwareResubmissionCommandDto request,
                                                                       Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageGroupware(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(groupwareService.resubmitAppointment(user, appointmentId, request));
    }
}
