package de.votian.services.controller;

import de.votian.services.dto.UserSessionDto;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.MetaFieldAdminService;
import org.springframework.http.HttpStatus;
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.util.List;

@RestController
@RequestMapping("/api/meta-admin")
public class MetaFieldAdminController {

    private final MetaFieldAdminService metaFieldAdminService;
    private final AccessControlService accessControlService;

    public MetaFieldAdminController(MetaFieldAdminService metaFieldAdminService,
                                    AccessControlService accessControlService) {
        this.metaFieldAdminService = metaFieldAdminService;
        this.accessControlService = accessControlService;
    }

    @GetMapping("/categories")
    public ResponseEntity<List<MetaFieldAdminService.CategoryRow>> getCategories(@RequestParam Long hqId,
                                                                                 Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.findCategories(hqId));
    }

    @PostMapping("/categories")
    public ResponseEntity<MetaFieldAdminService.CategoryRow> createCategory(@RequestBody CategoryRequest request,
                                                                            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.createCategory(
                request.hqId,
                request.mnemonic,
                request.description,
                request.templateId
        ));
    }

    @PutMapping("/categories/{id}")
    public ResponseEntity<MetaFieldAdminService.CategoryRow> updateCategory(@PathVariable Long id,
                                                                            @RequestBody CategoryRequest request,
                                                                            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.updateCategory(
                id,
                request.hqId,
                request.mnemonic,
                request.description,
                request.templateId
        ));
    }

    @GetMapping("/fields")
    public ResponseEntity<List<MetaFieldAdminService.FieldRow>> getFields(@RequestParam Long hqId,
                                                                          @RequestParam(required = false) String filter,
                                                                          Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.findFields(filter));
    }

    @PostMapping("/fields")
    public ResponseEntity<MetaFieldAdminService.FieldRow> createField(@RequestBody FieldRequest request,
                                                                      Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.createField(request.type, request.name));
    }

    @PutMapping("/fields/{id}")
    public ResponseEntity<MetaFieldAdminService.FieldRow> updateField(@PathVariable Long id,
                                                                      @RequestBody FieldRequest request,
                                                                      Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.updateField(id, request.type, request.name));
    }

    @GetMapping("/templates")
    public ResponseEntity<List<MetaFieldAdminService.TemplateRow>> getTemplates(@RequestParam Long hqId,
                                                                                Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.findTemplates());
    }

    @PostMapping("/templates")
    public ResponseEntity<MetaFieldAdminService.TemplateRow> createTemplate(@RequestBody TemplateRequest request,
                                                                            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.createTemplate(request.name, request.content));
    }

    @PutMapping("/templates/{id}")
    public ResponseEntity<MetaFieldAdminService.TemplateRow> updateTemplate(@PathVariable Long id,
                                                                            @RequestBody TemplateRequest request,
                                                                            Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.updateTemplate(id, request.name, request.content));
    }

    @GetMapping("/categories/{id}/fields")
    public ResponseEntity<List<MetaFieldAdminService.CategoryFieldRow>> getCategoryFields(@PathVariable Long id,
                                                                                          @RequestParam Long hqId,
                                                                                          Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.findCategoryFields(id, hqId));
    }

    @PostMapping("/categories/{id}/fields")
    public ResponseEntity<MetaFieldAdminService.CategoryFieldRow> addCategoryField(@PathVariable Long id,
                                                                                   @RequestBody CategoryFieldRequest request,
                                                                                   Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.addCategoryField(id, request.hqId, request.fieldId));
    }

    @PutMapping("/categories/{id}/fields/order")
    public ResponseEntity<List<MetaFieldAdminService.CategoryFieldRow>> reorderCategoryFields(@PathVariable Long id,
                                                                                              @RequestBody CategoryFieldOrderRequest request,
                                                                                              Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (request == null || !isAllowed(user, request.hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        return ResponseEntity.ok(metaFieldAdminService.reorderCategoryFields(id, request.hqId, request.assignmentIds));
    }

    @DeleteMapping("/category-fields/{assignmentId}")
    public ResponseEntity<Void> deleteCategoryField(@PathVariable Long assignmentId,
                                                    @RequestParam Long hqId,
                                                    Authentication authentication) {
        UserSessionDto user = accessControlService.sessionUser(authentication);
        if (!isAllowed(user, hqId)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
        }
        metaFieldAdminService.deleteCategoryField(assignmentId, hqId);
        return ResponseEntity.ok().build();
    }

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

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

    public static class CategoryRequest {
        public Long hqId;
        public String mnemonic;
        public String description;
        public Long templateId;
    }

    public static class FieldRequest {
        public Long hqId;
        public String type;
        public String name;
    }

    public static class TemplateRequest {
        public Long hqId;
        public String name;
        public String content;
    }

    public static class CategoryFieldRequest {
        public Long hqId;
        public Long fieldId;
    }

    public static class CategoryFieldOrderRequest {
        public Long hqId;
        public List<Long> assignmentIds;
    }
}
