package de.votian.services.controller;

import de.votian.services.dto.UserSessionDto;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.CommunicationWorkspaceService;
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.DeleteMapping;
import org.springframework.web.bind.annotation.ExceptionHandler;
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.time.LocalDateTime;
import java.util.List;

@RestController
@RequestMapping("/api/communication-workspace")
public class CommunicationWorkspaceController {

    private final CommunicationWorkspaceService communicationWorkspaceService;
    private final AccessControlService accessControlService;

    public CommunicationWorkspaceController(CommunicationWorkspaceService communicationWorkspaceService,
                                            AccessControlService accessControlService) {
        this.communicationWorkspaceService = communicationWorkspaceService;
        this.accessControlService = accessControlService;
    }

    @GetMapping("/bootstrap")
    public ResponseEntity<CommunicationWorkspaceService.Bootstrap> bootstrap(@RequestParam Long hqId,
                                                                             Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.bootstrap(user, hqId));
    }

    @GetMapping("/tickers")
    public ResponseEntity<List<CommunicationWorkspaceService.TickerRow>> tickers(@RequestParam Long hqId,
                                                                                 Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.findTickers(user, hqId));
    }

    @PostMapping("/tickers")
    public ResponseEntity<CommunicationWorkspaceService.TickerRow> createTicker(@RequestBody TickerRequest request,
                                                                                Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.createTicker(
                user,
                request.hqId,
                request.targetHeadquartersId,
                request.targetEmployeeId,
                request.startAt,
                request.endAt,
                request.text,
                request.unerasable
        ));
    }

    @DeleteMapping("/tickers/{id}")
    public ResponseEntity<Void> deleteTicker(@PathVariable Long id,
                                             @RequestParam Long hqId,
                                             Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        communicationWorkspaceService.deleteTicker(user, hqId, id);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/groups")
    public ResponseEntity<List<CommunicationWorkspaceService.MessageGroupRow>> groups(@RequestParam Long hqId,
                                                                                      Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.findMessageGroups(user, hqId));
    }

    @PostMapping("/groups")
    public ResponseEntity<CommunicationWorkspaceService.MessageGroupRow> createGroup(@RequestBody MessageGroupRequest request,
                                                                                     Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.saveMessageGroup(user, request.hqId, null, request.name));
    }

    @PutMapping("/groups/{id}")
    public ResponseEntity<CommunicationWorkspaceService.MessageGroupRow> updateGroup(@PathVariable Long id,
                                                                                     @RequestBody MessageGroupRequest request,
                                                                                     Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.saveMessageGroup(user, request.hqId, id, request.name));
    }

    @DeleteMapping("/groups/{id}")
    public ResponseEntity<Void> deleteGroup(@PathVariable Long id,
                                            @RequestParam Long hqId,
                                            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        communicationWorkspaceService.deleteMessageGroup(user, hqId, id);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/couriers")
    public ResponseEntity<List<CommunicationWorkspaceService.CourierOption>> couriers(@RequestParam Long hqId,
                                                                                      @RequestParam(required = false) String query,
                                                                                      Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.findCouriers(user, hqId, query));
    }

    @PutMapping("/couriers/{id}/groups")
    public ResponseEntity<CommunicationWorkspaceService.CourierOption> updateCourierGroups(@PathVariable Long id,
                                                                                            @RequestBody CourierGroupRequest request,
                                                                                            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.updateCourierGroups(
                user,
                request.hqId,
                id,
                request.groupIds
        ));
    }

    @GetMapping("/assignments")
    public ResponseEntity<List<CommunicationWorkspaceService.GroupAssignmentRow>> assignments(@RequestParam Long hqId,
                                                                                              Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.findGroupAssignments(user, hqId));
    }

    @GetMapping("/employees")
    public ResponseEntity<List<CommunicationWorkspaceService.EmployeeOption>> employees(@RequestParam Long hqId,
                                                                                        @RequestParam(required = false) String query,
                                                                                        Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.findEmployees(user, hqId, query));
    }

    @GetMapping("/newsletter")
    public ResponseEntity<List<CommunicationWorkspaceService.NewsletterRecipientRow>> newsletter(@RequestParam Long hqId,
                                                                                                 @RequestParam(defaultValue = "all") String type,
                                                                                                 @RequestParam(defaultValue = "all") String status,
                                                                                                 @RequestParam(required = false) String search,
                                                                                                 Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isNewsletterAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.findNewsletterRecipients(user, hqId, type, status, search));
    }

    @PutMapping("/newsletter/{type}/{id}")
    public ResponseEntity<CommunicationWorkspaceService.NewsletterRecipientRow> updateNewsletter(@PathVariable String type,
                                                                                                 @PathVariable Long id,
                                                                                                 @RequestBody NewsletterStateRequest request,
                                                                                                 Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isNewsletterAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.updateNewsletterRecipient(
                user,
                request.hqId,
                type,
                id,
                request.newsletterActive,
                request.dsgvoConfirmed
        ));
    }

    @GetMapping("/messages")
    public ResponseEntity<List<CommunicationWorkspaceService.MessageRow>> messages(@RequestParam Long hqId,
                                                                                   @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from,
                                                                                   @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to,
                                                                                   @RequestParam(required = false) List<Integer> states,
                                                                                   @RequestParam(defaultValue = "all") String type,
                                                                                   @RequestParam(required = false) String search,
                                                                                   Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.findMessages(user, hqId, from, to, states, type, search));
    }

    @PostMapping("/messages/{id}/read")
    public ResponseEntity<CommunicationWorkspaceService.MessageRow> markRead(@PathVariable Long id,
                                                                             @RequestParam Long hqId,
                                                                             Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.markMessageRead(user, hqId, id));
    }

    @PostMapping("/messages/{id}/answer")
    public ResponseEntity<CommunicationWorkspaceService.MessageRow> answer(@PathVariable Long id,
                                                                           @RequestBody AnswerRequest request,
                                                                           Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.answerMessage(
                user,
                request.hqId,
                id,
                request.subject,
                request.body
        ));
    }

    @PostMapping("/send")
    public ResponseEntity<CommunicationWorkspaceService.SendResult> send(@RequestBody SendRequest request,
                                                                         Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(communicationWorkspaceService.sendMessage(
                user,
                request.hqId,
                request.groupIds,
                request.courierSid,
                request.subject,
                request.body,
                request.allActiveCouriers
        ));
    }

    private boolean isAllowed(UserSessionDto user, Long hqId) {
        return accessControlService.canViewCommunication(user)
                && accessControlService.canAccessHeadquarters(user, hqId);
    }

    private boolean isNewsletterAllowed(UserSessionDto user, Long hqId) {
        return isAllowed(user, hqId) && accessControlService.canManageNewsletter(user);
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException exception) {
        return ResponseEntity.badRequest().body(exception.getMessage());
    }

    public static class TickerRequest {
        public Long hqId;
        public Long targetHeadquartersId;
        public Long targetEmployeeId;
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
        public LocalDateTime startAt;
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
        public LocalDateTime endAt;
        public String text;
        public boolean unerasable;
    }

    public static class MessageGroupRequest {
        public Long hqId;
        public String name;
    }

    public static class CourierGroupRequest {
        public Long hqId;
        public List<Long> groupIds;
    }

    public static class NewsletterStateRequest {
        public Long hqId;
        public boolean newsletterActive;
        public boolean dsgvoConfirmed;
    }

    public static class AnswerRequest {
        public Long hqId;
        public String subject;
        public String body;
    }

    public static class SendRequest {
        public Long hqId;
        public List<Long> groupIds;
        public String courierSid;
        public String subject;
        public String body;
        public boolean allActiveCouriers;
    }
}
