package de.votian.services.controller;

import de.votian.services.dto.CustomerListItemDto;
import de.votian.services.dto.ImportExecutionResultDto;
import de.votian.services.dto.ImportFileDto;
import de.votian.services.dto.ImportProcessDto;
import de.votian.services.dto.UserSessionDto;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.ImportWorkspaceService;
import de.votian.services.service.ViewDataService;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.DeleteMapping;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Objects;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@RestController
@RequestMapping("/api/imports")
public class ImportController {

    private final ImportWorkspaceService importWorkspaceService;
    private final AccessControlService accessControlService;
    private final ViewDataService viewDataService;

    public ImportController(ImportWorkspaceService importWorkspaceService,
                            AccessControlService accessControlService,
                            ViewDataService viewDataService) {
        this.importWorkspaceService = importWorkspaceService;
        this.accessControlService = accessControlService;
        this.viewDataService = viewDataService;
    }

    @GetMapping("/processes")
    public ResponseEntity<List<ImportProcessDto>> getProcesses(Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageImports(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(importWorkspaceService.getProcesses());
    }

    @GetMapping("/customers")
    public ResponseEntity<List<CustomerListItemDto>> getCustomers(Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageImports(user) || user == null || user.getHeadquartersId() == null) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(viewDataService.findCustomersByHeadquarters(user.getHeadquartersId()));
    }

    @GetMapping("/processes/{processKey}/files")
    public ResponseEntity<List<ImportFileDto>> getFiles(@PathVariable String processKey, Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageImports(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(importWorkspaceService.listFiles(processKey));
    }

    @PostMapping("/processes/{processKey}/files")
    public ResponseEntity<ImportFileDto> uploadFile(@PathVariable String processKey,
                                                    @RequestParam("file") MultipartFile file,
                                                    Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageImports(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(importWorkspaceService.storeFile(processKey, file));
    }

    @DeleteMapping("/processes/{processKey}/files")
    public ResponseEntity<Void> deleteFile(@PathVariable String processKey,
                                           @RequestParam("name") String fileName,
                                           Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageImports(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        importWorkspaceService.deleteFile(processKey, fileName);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/processes/{processKey}/files/content")
    public ResponseEntity<ByteArrayResource> downloadFile(@PathVariable String processKey,
                                                          @RequestParam("name") String fileName,
                                                          Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageImports(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        byte[] content = importWorkspaceService.loadFile(processKey, fileName);
        return ResponseEntity.ok()
                .contentType(Objects.requireNonNull(MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM)))
                .header(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment().filename(fileName).build().toString())
                .body(new ByteArrayResource(Objects.requireNonNull(content)));
    }

    @PostMapping("/processes/{processKey}/execute")
    public ResponseEntity<ImportExecutionResultDto> execute(@PathVariable String processKey,
                                                            @RequestBody ImportExecutionRequest request,
                                                            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!accessControlService.canManageImports(user)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        try {
            return ResponseEntity.ok(importWorkspaceService.execute(
                    processKey,
                    request != null ? request.fileName : null,
                    request != null ? request.customerId : null,
                    user != null ? user.getHeadquartersId() : null
            ));
        } catch (RuntimeException ex) {
            return ResponseEntity.ok(ImportExecutionResultDto.failure(processKey, ex.getMessage()));
        }
    }

    public static class ImportExecutionRequest {
        public String fileName;
        public Long customerId;
    }
}
