package de.cannamanage.api.controller;

import de.cannamanage.api.dto.prevention.PreventionOfficerRequest;
import de.cannamanage.api.dto.staff.CreateStaffRequest;
import de.cannamanage.api.dto.staff.StaffResponse;
import de.cannamanage.api.dto.staff.UpdateStaffRequest;
import de.cannamanage.domain.entity.StaffAccount;
import de.cannamanage.domain.entity.TenantContext;
import de.cannamanage.domain.entity.User;
import de.cannamanage.domain.enums.StaffPermission;
import de.cannamanage.service.PreventionOfficerService;
import de.cannamanage.service.StaffService;
import de.cannamanage.service.StaffTemplates;
import de.cannamanage.service.repository.UserRepository;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

@RestController
@RequestMapping("/api/v1/staff")
@RequiredArgsConstructor
@Tag(name = "Staff Management", description = "Staff CRUD + invite flow (ADMIN only)")
public class StaffController {

    private final StaffService staffService;
    private final PreventionOfficerService preventionOfficerService;
    private final UserRepository userRepository;

    @GetMapping
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "List all active staff members")
    public ResponseEntity<List<StaffResponse>> listStaff() {
        UUID tenantId = TenantContext.getCurrentTenant();
        List<StaffAccount> staffList = staffService.listStaff(tenantId);
        List<StaffResponse> response = staffList.stream()
                .map(staff -> {
                    User user = userRepository.findById(staff.getUserId()).orElse(null);
                    String email = user != null ? user.getEmail() : "unknown";
                    return StaffResponse.from(staff, email);
                })
                .toList();
        return ResponseEntity.ok(response);
    }

    @PostMapping
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "Create staff member + send invite email")
    public ResponseEntity<StaffResponse> createStaff(@Valid @RequestBody CreateStaffRequest request) {
        UUID tenantId = TenantContext.getCurrentTenant();
        StaffAccount staff = staffService.createStaff(
                tenantId,
                request.email(),
                request.displayName(),
                request.permissions(),
                request.templateName()
        );
        return ResponseEntity.status(HttpStatus.CREATED)
                .body(StaffResponse.from(staff, request.email()));
    }

    @GetMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "Get staff member by ID")
    public ResponseEntity<StaffResponse> getStaff(@PathVariable UUID id) {
        UUID tenantId = TenantContext.getCurrentTenant();
        StaffAccount staff = staffService.getStaff(tenantId, id);
        User user = userRepository.findById(staff.getUserId()).orElse(null);
        String email = user != null ? user.getEmail() : "unknown";
        return ResponseEntity.ok(StaffResponse.from(staff, email));
    }

    @PutMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "Update staff permissions/profile (revokes tokens on permission change)")
    public ResponseEntity<StaffResponse> updateStaff(@PathVariable UUID id,
                                                     @RequestBody UpdateStaffRequest request) {
        UUID tenantId = TenantContext.getCurrentTenant();
        StaffAccount staff = staffService.updateStaff(
                tenantId, id,
                request.displayName(),
                request.permissions(),
                request.templateName(),
                request.active()
        );
        User user = userRepository.findById(staff.getUserId()).orElse(null);
        String email = user != null ? user.getEmail() : "unknown";
        return ResponseEntity.ok(StaffResponse.from(staff, email));
    }

    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "Deactivate staff member (revokes all tokens)")
    public ResponseEntity<Void> deactivateStaff(@PathVariable UUID id) {
        UUID tenantId = TenantContext.getCurrentTenant();
        staffService.deactivateStaff(tenantId, id);
        return ResponseEntity.noContent().build();
    }

    @PutMapping("/{id}/prevention-officer")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "Assign or revoke prevention officer status",
            description = "Sets prevention officer flag on a staff member. Enforces club.maxPreventionOfficers limit on assign.")
    public ResponseEntity<StaffResponse> setPreventionOfficer(@PathVariable UUID id,
                                                              @Valid @RequestBody PreventionOfficerRequest request) {
        UUID tenantId = TenantContext.getCurrentTenant();
        StaffAccount staff = preventionOfficerService.setPreventionOfficer(tenantId, id, request.preventionOfficer());
        User user = userRepository.findById(staff.getUserId()).orElse(null);
        String email = user != null ? user.getEmail() : "unknown";
        return ResponseEntity.ok(StaffResponse.from(staff, email));
    }

    @GetMapping("/templates")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "List available permission templates")
    public ResponseEntity<Map<String, Set<StaffPermission>>> listTemplates() {
        return ResponseEntity.ok(StaffTemplates.getAllTemplates());
    }
}
