package de.votian.services.controller;

import de.votian.services.dto.UserSessionDto;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.ReportWorkspaceService;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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.util.List;

@RestController
@RequestMapping("/api/report-workspace")
public class ReportWorkspaceController {

    private final ReportWorkspaceService reportWorkspaceService;
    private final AccessControlService accessControlService;

    public ReportWorkspaceController(ReportWorkspaceService reportWorkspaceService,
                                     AccessControlService accessControlService) {
        this.reportWorkspaceService = reportWorkspaceService;
        this.accessControlService = accessControlService;
    }

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

    @GetMapping("/report-types")
    public ResponseEntity<List<ReportWorkspaceService.ReportTypeOption>> reportTypes(@RequestParam Long hqId,
                                                                                     @RequestParam String objectType,
                                                                                     Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isWorkspaceAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(reportWorkspaceService.findReportTypes(user, hqId, objectType));
    }

    @GetMapping("/search")
    public ResponseEntity<List<ReportWorkspaceService.ObjectOption>> search(@RequestParam Long hqId,
                                                                            @RequestParam String objectType,
                                                                            @RequestParam(required = false) String query,
                                                                            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isWorkspaceAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(reportWorkspaceService.searchObjects(user, hqId, objectType, query));
    }

    @GetMapping("/reports")
    public ResponseEntity<List<ReportWorkspaceService.ReportRow>> reports(
            @RequestParam Long hqId,
            @RequestParam String objectType,
            @RequestParam(required = false) Long objectId,
            @RequestParam(required = false) Integer reportType,
            @RequestParam(required = false) String search,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to,
            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isWorkspaceAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(reportWorkspaceService.findReports(user, hqId, objectType, objectId, from, to, reportType, search));
    }

    @PostMapping("/reports")
    public ResponseEntity<ReportWorkspaceService.ReportRow> createReport(@RequestBody ReportRequest request,
                                                                         Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isWorkspaceAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(reportWorkspaceService.createReport(
                user,
                request.hqId,
                request.objectType,
                request.objectId,
                request.reportType,
                request.text,
                request.confidential
        ));
    }

    @PutMapping("/reports/{id}")
    public ResponseEntity<ReportWorkspaceService.ReportRow> updateReport(@PathVariable Long id,
                                                                         @RequestBody ReportRequest request,
                                                                         Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isWorkspaceAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(reportWorkspaceService.updateReport(
                user,
                request.hqId,
                id,
                request.reportType,
                request.text,
                request.confidential
        ));
    }

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

    @GetMapping("/statistics")
    public ResponseEntity<List<ReportWorkspaceService.StatisticRow>> statistics(
            @RequestParam Long hqId,
            @RequestParam String objectType,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to,
            @RequestParam(defaultValue = "false") boolean splitByReportType,
            @RequestParam(defaultValue = "false") boolean splitByCustomerType,
            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isWorkspaceAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(reportWorkspaceService.statistics(
                user,
                hqId,
                objectType,
                from,
                to,
                splitByReportType,
                splitByCustomerType
        ));
    }

    @GetMapping("/export/history")
    public ResponseEntity<byte[]> exportHistory(
            @RequestParam Long hqId,
            @RequestParam String objectType,
            @RequestParam(required = false) Long objectId,
            @RequestParam(required = false) Integer reportType,
            @RequestParam(required = false) String search,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to,
            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isWorkspaceAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        byte[] data = reportWorkspaceService.exportHistoryCsv(user, hqId, objectType, objectId, from, to, reportType, search);
        return csvResponse(data, "berichte.csv");
    }

    @GetMapping("/export/statistics")
    public ResponseEntity<byte[]> exportStatistics(
            @RequestParam Long hqId,
            @RequestParam String objectType,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate from,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate to,
            @RequestParam(defaultValue = "false") boolean splitByReportType,
            @RequestParam(defaultValue = "false") boolean splitByCustomerType,
            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isWorkspaceAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        byte[] data = reportWorkspaceService.exportStatisticsCsv(
                user,
                hqId,
                objectType,
                from,
                to,
                splitByReportType,
                splitByCustomerType
        );
        return csvResponse(data, "berichtsstatistik.csv");
    }

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

    private ResponseEntity<byte[]> csvResponse(byte[] data, String filename) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("text/csv;charset=UTF-8"));
        headers.setContentDisposition(ContentDisposition.attachment().filename(filename).build());
        return new ResponseEntity<>(data, headers, HttpStatus.OK);
    }

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

    public static class ReportRequest {
        public Long hqId;
        public String objectType;
        public Long objectId;
        public Integer reportType;
        public String text;
        public boolean confidential;
    }
}
