package de.votian.services.controller;

import de.votian.services.dto.UserSessionDto;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.GenericExportWorkspaceService;
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/export-workspace")
public class GenericExportWorkspaceController {

    private final GenericExportWorkspaceService genericExportWorkspaceService;
    private final AccessControlService accessControlService;

    public GenericExportWorkspaceController(GenericExportWorkspaceService genericExportWorkspaceService,
                                            AccessControlService accessControlService) {
        this.genericExportWorkspaceService = genericExportWorkspaceService;
        this.accessControlService = accessControlService;
    }

    @GetMapping("/bootstrap")
    public ResponseEntity<GenericExportWorkspaceService.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(genericExportWorkspaceService.bootstrap(user, hqId));
    }

    @GetMapping("/profiles")
    public ResponseEntity<List<GenericExportWorkspaceService.ProfileRow>> profiles(@RequestParam Long hqId,
                                                                                   @RequestParam(required = false) Long customerId,
                                                                                   @RequestParam Long categoryId,
                                                                                   Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(genericExportWorkspaceService.findProfiles(user, hqId, customerId, categoryId));
    }

    @PostMapping("/profiles")
    public ResponseEntity<GenericExportWorkspaceService.ProfileRow> createProfile(@RequestBody ProfileRequest request,
                                                                                  Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(genericExportWorkspaceService.saveProfile(
                user,
                request.hqId,
                request.customerId,
                request.categoryId,
                null,
                request.name,
                request.parameterString,
                request.headline,
                request.beginOfLineChars,
                request.endOfLineChars,
                request.beginOfFileChars,
                request.endOfFileChars,
                request.fileExtension
        ));
    }

    @PutMapping("/profiles/{id}")
    public ResponseEntity<GenericExportWorkspaceService.ProfileRow> updateProfile(@PathVariable Long id,
                                                                                  @RequestBody ProfileRequest request,
                                                                                  Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(genericExportWorkspaceService.saveProfile(
                user,
                request.hqId,
                request.customerId,
                request.categoryId,
                id,
                request.name,
                request.parameterString,
                request.headline,
                request.beginOfLineChars,
                request.endOfLineChars,
                request.beginOfFileChars,
                request.endOfFileChars,
                request.fileExtension
        ));
    }

    @DeleteMapping("/profiles/{id}")
    public ResponseEntity<Void> deleteProfile(@PathVariable Long id,
                                              @RequestParam Long hqId,
                                              @RequestParam(required = false) Long customerId,
                                              @RequestParam Long categoryId,
                                              Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        genericExportWorkspaceService.deleteProfile(user, hqId, customerId, categoryId, id);
        return ResponseEntity.ok().build();
    }

    @PostMapping("/run")
    public ResponseEntity<GenericExportWorkspaceService.ExportResult> runExport(@RequestBody ExportRequest request,
                                                                                Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(genericExportWorkspaceService.generateExport(
                user,
                request.hqId,
                request.customerId,
                request.categoryId,
                request.profileId,
                request.from,
                request.to,
                request.statusFilter,
                request.customerCodeFilter,
                request.delimiter,
                request.fileName,
                request.includeHeadline
        ));
    }

    @GetMapping("/files")
    public ResponseEntity<List<GenericExportWorkspaceService.ExportFileRow>> files(@RequestParam Long hqId,
                                                                                   @RequestParam(required = false) Long customerId,
                                                                                   Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(genericExportWorkspaceService.listFiles(user, hqId, customerId));
    }

    @GetMapping("/files/{id}/content")
    public ResponseEntity<byte[]> download(@PathVariable Long id,
                                           @RequestParam Long hqId,
                                           @RequestParam(required = false) Long customerId,
                                           Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        GenericExportWorkspaceService.ExportFileRow file = genericExportWorkspaceService.listFiles(user, hqId, customerId).stream()
                .filter(row -> row.id().equals(id))
                .findFirst()
                .orElse(null);
        if (file == null) {
            return ResponseEntity.notFound().build();
        }
        byte[] data = genericExportWorkspaceService.downloadFile(user, hqId, customerId, id);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("text/plain;charset=UTF-8"));
        headers.setContentDisposition(ContentDisposition.attachment().filename(file.fileName()).build());
        return new ResponseEntity<>(data, headers, HttpStatus.OK);
    }

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

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

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

    public static class ProfileRequest {
        public Long hqId;
        public Long customerId;
        public Long categoryId;
        public String name;
        public String parameterString;
        public boolean headline;
        public String beginOfLineChars;
        public String endOfLineChars;
        public String beginOfFileChars;
        public String endOfFileChars;
        public String fileExtension;
    }

    public static class ExportRequest {
        public Long hqId;
        public Long customerId;
        public Long categoryId;
        public Long profileId;
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
        public LocalDate from;
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
        public LocalDate to;
        public Integer statusFilter;
        public String customerCodeFilter;
        public String delimiter;
        public String fileName;
        public boolean includeHeadline;
    }
}
