package com.ai.trackwalker.capability.api;

import com.ai.trackwalker.api.ApiResponse;
import com.ai.trackwalker.capability.service.CapabilityCompletionService;
import jakarta.validation.Valid;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.nio.charset.StandardCharsets;
import java.util.Map;

@RestController
@RequestMapping("/api/v1")
public class CapabilityCompletionController {
    private final CapabilityCompletionService service;

    public CapabilityCompletionController(CapabilityCompletionService service) {
        this.service = service;
    }

    @GetMapping("/capabilities/completion")
    public ApiResponse<?> completionOverview() {
        return ApiResponse.ok(service.completionOverview());
    }

    @GetMapping("/inspection/plans")
    public ApiResponse<?> plans() {
        return ApiResponse.ok(Map.of("plans", service.listPlans()));
    }

    @PostMapping("/inspection/plans")
    public ApiResponse<?> createPlan(@Valid @RequestBody CapabilityRequests.CreatePlanRequest request) {
        return ApiResponse.ok(service.createPlan(request));
    }

    @PostMapping("/inspection/plans/{planId}/activate")
    public ApiResponse<?> activatePlan(@PathVariable String planId) {
        return ApiResponse.ok(service.activatePlan(planId));
    }

    @PostMapping("/inspection/plans/{planId}/generate-tasks")
    public ApiResponse<?> generatePlanTasks(@PathVariable String planId) {
        return ApiResponse.ok(service.generatePlanTasks(planId));
    }

    @GetMapping("/inspection/objects")
    public ApiResponse<?> objects() {
        return ApiResponse.ok(Map.of("objects", service.listObjects()));
    }

    @PostMapping("/inspection/objects")
    public ApiResponse<?> createObject(@Valid @RequestBody CapabilityRequests.CreateObjectRequest request) {
        return ApiResponse.ok(service.createObject(request));
    }

    @GetMapping("/routes")
    public ApiResponse<?> routes() {
        return ApiResponse.ok(Map.of("routes", service.listRoutes()));
    }

    @PostMapping("/routes")
    public ApiResponse<?> createRoute(@Valid @RequestBody CapabilityRequests.CreateRouteRequest request) {
        return ApiResponse.ok(service.createRoute(request));
    }

    @PostMapping("/route-versions/{versionId}/validate")
    public ApiResponse<?> validateRoute(@PathVariable String versionId) {
        return ApiResponse.ok(service.validateRouteVersion(versionId));
    }

    @PostMapping("/route-versions/{versionId}/publish")
    public ApiResponse<?> publishRoute(
            @PathVariable String versionId,
            @RequestParam(defaultValue = "user-dispatcher") String approvedBy
    ) {
        return ApiResponse.ok(service.publishRouteVersion(versionId, approvedBy));
    }

    @PostMapping("/route-versions/{versionId}/uav-connections/{connectionId}/synchronize")
    public ApiResponse<?> synchronizeRoute(
            @PathVariable String versionId,
            @PathVariable String connectionId
    ) {
        return ApiResponse.ok(service.synchronizeRouteVersion(versionId, connectionId));
    }

    @GetMapping("/uav/connections")
    public ApiResponse<?> connections() {
        return ApiResponse.ok(Map.of("connections", service.listConnections()));
    }

    @PostMapping("/uav/connections")
    public ApiResponse<?> createConnection(@Valid @RequestBody CapabilityRequests.CreateConnectionRequest request) {
        return ApiResponse.ok(service.createConnection(request));
    }

    @PostMapping("/uav/connections/{connectionId}/check")
    public ApiResponse<?> checkConnection(@PathVariable String connectionId) {
        return ApiResponse.ok(service.checkConnection(connectionId));
    }

    @PostMapping("/uav/connections/{connectionId}/sync-devices")
    public ApiResponse<?> syncDevices(@PathVariable String connectionId) {
        return ApiResponse.ok(service.synchronizeDevices(connectionId));
    }

    @GetMapping("/uav/devices")
    public ApiResponse<?> devices() {
        return ApiResponse.ok(Map.of("devices", service.listDevices()));
    }

    @GetMapping("/uav/missions")
    public ApiResponse<?> missions() {
        return ApiResponse.ok(Map.of("missions", service.listMissions()));
    }

    @PostMapping("/uav/missions")
    public ApiResponse<?> dispatchMission(@Valid @RequestBody CapabilityRequests.DispatchMissionRequest request) {
        return ApiResponse.ok(service.dispatchMission(request));
    }

    @PostMapping("/uav/missions/{missionId}/commands")
    public ApiResponse<?> missionCommand(
            @PathVariable String missionId,
            @Valid @RequestBody CapabilityRequests.MissionCommandRequest request
    ) {
        return ApiResponse.ok(service.executeMissionCommand(missionId, request));
    }

    @GetMapping("/uav/missions/{missionId}/telemetry")
    public ApiResponse<?> telemetry(@PathVariable String missionId) {
        return ApiResponse.ok(Map.of("telemetry", service.listTelemetry(missionId)));
    }

    @PostMapping("/uploads")
    public ApiResponse<?> createUpload(@Valid @RequestBody CapabilityRequests.CreateUploadSessionRequest request) {
        return ApiResponse.ok(service.createUploadSession(request));
    }

    @GetMapping("/uploads/{sessionId}")
    public ApiResponse<?> upload(@PathVariable String sessionId) {
        return ApiResponse.ok(service.uploadSession(sessionId));
    }

    @PutMapping(value = "/uploads/{sessionId}/parts/{partNo}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ApiResponse<?> uploadPart(
            @PathVariable String sessionId,
            @PathVariable int partNo,
            @RequestPart("chunk") MultipartFile chunk
    ) {
        return ApiResponse.ok(service.uploadPart(sessionId, partNo, chunk));
    }

    @PostMapping("/uploads/{sessionId}/complete")
    public ApiResponse<?> completeUpload(@PathVariable String sessionId) {
        return ApiResponse.ok(service.completeUpload(sessionId));
    }

    @GetMapping("/preprocess/jobs")
    public ApiResponse<?> preprocessJobs() {
        return ApiResponse.ok(Map.of("jobs", service.listPreprocessJobs()));
    }

    @PostMapping("/preprocess/jobs/{jobId}/run")
    public ApiResponse<?> runPreprocess(@PathVariable String jobId) {
        return ApiResponse.ok(service.runPreprocess(jobId));
    }

    @GetMapping("/gis/features")
    public ApiResponse<?> gisFeatures() {
        return ApiResponse.ok(service.gisFeatureCollection());
    }

    @GetMapping("/organizations")
    public ApiResponse<?> organizations() {
        return ApiResponse.ok(Map.of("organizations", service.listOrganizations()));
    }

    @GetMapping("/responsibility-rules")
    public ApiResponse<?> responsibilityRules() {
        return ApiResponse.ok(Map.of("rules", service.listResponsibilityRules()));
    }

    @GetMapping("/notifications")
    public ApiResponse<?> notifications(@RequestParam(required = false) String status) {
        return ApiResponse.ok(Map.of("notifications", service.listNotifications(status)));
    }

    @PostMapping("/notifications/{notificationId}/read")
    public ApiResponse<?> readNotification(@PathVariable String notificationId) {
        return ApiResponse.ok(service.readNotification(notificationId));
    }

    @PostMapping("/workorders/{workorderId}/actions")
    public ApiResponse<?> workOrderAction(
            @PathVariable String workorderId,
            @Valid @RequestBody CapabilityRequests.WorkOrderActionRequest request
    ) {
        return ApiResponse.ok(service.actOnWorkOrder(workorderId, request));
    }

    @GetMapping("/workorders/{workorderId}/actions")
    public ApiResponse<?> workOrderActions(@PathVariable String workorderId) {
        return ApiResponse.ok(Map.of("actions", service.listWorkOrderActions(workorderId)));
    }

    @PostMapping(value = "/workorders/{workorderId}/attachments", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ApiResponse<?> uploadWorkOrderEvidence(
            @PathVariable String workorderId,
            @RequestParam(defaultValue = "AFTER") String phase,
            @RequestParam(defaultValue = "现场处置人员") String uploadedBy,
            @RequestParam(required = false) String captureTime,
            @RequestParam(required = false) Double longitude,
            @RequestParam(required = false) Double latitude,
            @RequestPart("file") MultipartFile file
    ) {
        return ApiResponse.ok(service.addWorkOrderEvidence(workorderId, phase, uploadedBy, captureTime, longitude, latitude, file));
    }

    @GetMapping("/workorders/{workorderId}/attachments")
    public ApiResponse<?> workOrderEvidence(@PathVariable String workorderId) {
        return ApiResponse.ok(Map.of("attachments", service.listWorkOrderEvidence(workorderId)));
    }

    @GetMapping("/workorder-attachments/{attachmentId}/content")
    public ResponseEntity<byte[]> workOrderEvidenceContent(@PathVariable String attachmentId) {
        CapabilityCompletionService.AttachmentContent content = service.readWorkOrderEvidence(attachmentId);
        MediaType mediaType;
        try {
            mediaType = MediaType.parseMediaType(content.contentType());
        } catch (Exception ignored) {
            mediaType = MediaType.APPLICATION_OCTET_STREAM;
        }
        return ResponseEntity.ok()
                .contentType(mediaType)
                .header(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.inline()
                        .filename(content.fileName(), StandardCharsets.UTF_8)
                        .build().toString())
                .body(content.content());
    }

    @PostMapping("/workorders/{workorderId}/reinspection")
    public ApiResponse<?> reinspection(
            @PathVariable String workorderId,
            @RequestBody CapabilityRequests.CreateReinspectionRequest request
    ) {
        return ApiResponse.ok(service.createReinspection(workorderId, request));
    }

    @GetMapping("/archive-packages")
    public ApiResponse<?> archives() {
        return ApiResponse.ok(Map.of("archives", service.listArchives()));
    }

    @PostMapping("/archive-packages")
    public ApiResponse<?> createArchive(@Valid @RequestBody CapabilityRequests.CreateArchiveRequest request) {
        return ApiResponse.ok(service.createArchive(request));
    }
}
