package de.avatic.lcc.controller.bulk;


import com.azure.core.annotation.BodyParam;
import de.avatic.lcc.dto.bulk.BulkFileType;
import de.avatic.lcc.dto.bulk.BulkOperationDTO;
import de.avatic.lcc.service.bulk.BulkOperationService;
import de.avatic.lcc.service.bulk.TemplateExportService;
import de.avatic.lcc.util.exception.base.BadRequestException;
import jakarta.annotation.security.RolesAllowed;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * REST controller for handling bulk operations, including file uploads, template generation,
 * and export downloads. It provides a comprehensive set of endpoints to manage processing
 * operations for supported file types based on defined business requirements.
 */
@RestController
@RequestMapping("/api/bulk")
public class BulkOperationController {

    private final BulkOperationService bulkOperationService;
    private final TemplateExportService templateExportService;


    private final ThreadPoolTaskExecutor executor;

    public BulkOperationController(BulkOperationService bulkOperationService, TemplateExportService templateExportService, @Qualifier("bulkProcessingExecutor") ThreadPoolTaskExecutor executor) {
        this.bulkOperationService = bulkOperationService;
        this.templateExportService = templateExportService;
        this.executor = executor;
    }

    @GetMapping("/monitor")
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING', 'MATERIAL')")
    public Map<String, Object> getBulkThreadInfo() {
        Map<String, Object> info = new HashMap<>();
        info.put("activeCount", executor.getActiveCount());
        info.put("poolSize", executor.getPoolSize());
        info.put("corePoolSize", executor.getCorePoolSize());
        info.put("maxPoolSize", executor.getMaxPoolSize());
        info.put("queueSize", executor.getThreadPoolExecutor().getQueue().size());
        info.put("completedTaskCount", executor.getThreadPoolExecutor().getCompletedTaskCount());
        return info;
    }

    @GetMapping({"/status/", "/status"})
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING', 'MATERIAL')")
    public ResponseEntity<List<BulkOperationDTO>> getBulkStatus() {
        return ResponseEntity.ok(bulkOperationService.getStatus());
    }

    @PostMapping({"/upload/{type}", "/upload/{type}/"})
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING', 'MATERIAL')")
    public ResponseEntity<Void> uploadFile(@PathVariable BulkFileType type, @BodyParam("file") MultipartFile file) {
        bulkOperationService.processFileImport(type, file);
        return ResponseEntity.ok().build();
    }

    @GetMapping({"/templates/{type}", "/templates/{type}/"})
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING', 'MATERIAL')")
    public ResponseEntity<InputStreamResource> generateTemplate(@PathVariable BulkFileType type) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition", "attachment; filename=lcc_template_" + type.name().toLowerCase() + ".xlsx");

        return ResponseEntity
                .ok()
                .headers(headers)
                .contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
                .body(new InputStreamResource(templateExportService.generateTemplate(BulkFileType.valueOf(type.name().toUpperCase()))));
    }


    @GetMapping({"/download/{type}", "/download/{type}/"})
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING', 'MATERIAL')")
    public ResponseEntity<Void> scheduleDownload(@PathVariable BulkFileType type) {
        bulkOperationService.processFileExport(type);
        return ResponseEntity.ok().build();
    }


    @GetMapping({"/download/{type}/{validity_period_id}", "/download/{type}/{validity_period_id}/"})
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING', 'MATERIAL')")
    public ResponseEntity<Void> scheduleDownload(@PathVariable BulkFileType type, @PathVariable("validity_period_id") Integer validityPeriodId) {
        bulkOperationService.processFileExport(type, validityPeriodId);
        return ResponseEntity.ok().build();

    }

    @GetMapping({"/file/{processId}", "/file/{processId}/"})
    @PreAuthorize("hasAnyRole('SUPER', 'FREIGHT', 'PACKAGING', 'MATERIAL')")
    public ResponseEntity<InputStreamResource> download(@PathVariable("processId") Integer id) {
        var op = bulkOperationService.getBulkOperation(id);

        if (op == null)
            throw new BadRequestException("No such file.", "No file found with id: " + id);

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition", "attachment; filename=lcc_export_" + op.getFileType().name().toLowerCase() + ".xlsx");

        return ResponseEntity
                .ok()
                .headers(headers)
                .contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
                .body(new InputStreamResource(new ByteArrayResource(op.getFile())));
    }

}
