package online.wesal.wesal.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import online.wesal.wesal.dto.AcceptInvitationRequest;
import online.wesal.wesal.dto.ApiResponse;
import online.wesal.wesal.dto.CancelInvitationRequest;
import online.wesal.wesal.dto.CategorizedInvitationsResponse;
import online.wesal.wesal.dto.CreateInvitationRequest;
import online.wesal.wesal.dto.InvitationResponse;
import online.wesal.wesal.service.InvitationService;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/invitations")
@CrossOrigin(origins = "*")
@Tag(name = "Invitations", description = "Invitation management endpoints")
public class InvitationController {
    
    @Autowired
    private InvitationService invitationService;
    
    @PostMapping(value = "/create", consumes = "application/json", produces = "application/json")
    @Operation(summary = "Create invitation", description = "Create a new invitation")
    public ResponseEntity<ApiResponse<InvitationResponse>> createInvitation(
            @Valid @RequestBody CreateInvitationRequest request,
            BindingResult bindingResult,
            Authentication authentication) {
        
        if (bindingResult.hasErrors()) {
            String errorMessage = bindingResult.getFieldErrors().stream()
                .map(error -> {
                    String field = error.getField();
                    if ("title".equals(field)) return "Title is required";
                    if ("description".equals(field)) return "Description is required";
                    if ("maxParticipants".equals(field)) return "Maximum participants must be a positive number";
                    if ("tagId".equals(field)) return "Tag ID is required";
                    return error.getDefaultMessage();
                })
                .collect(Collectors.joining(", "));
            return ResponseEntity.badRequest().body(ApiResponse.error(errorMessage));
        }
        
        try {
            String userEmail = authentication.getName();
            InvitationResponse response = invitationService.createInvitation(request, userEmail);
            return ResponseEntity.ok(ApiResponse.success(response));
        } catch (RuntimeException e) {
            String message;
            if (e.getMessage().contains("User not found")) {
                message = "Authentication error. Please log in again.";
            } else if (e.getMessage().contains("Tag not found")) {
                message = "The selected tag does not exist.";
            } else {
                message = "Something went wrong.. We're sorry but try again later";
            }
            return ResponseEntity.badRequest().body(ApiResponse.error(message));
        }
    }
    
    @GetMapping("/get")
    @Operation(summary = "Get invitation", description = "Get invitation by ID")
    public ResponseEntity<ApiResponse<InvitationResponse>> getInvitation(@RequestParam Long id) {
        if (id == null || id <= 0) {
            return ResponseEntity.badRequest().body(ApiResponse.error("Valid invitation ID is required"));
        }
        
        try {
            return invitationService.getInvitationById(id)
                    .map(invitation -> ResponseEntity.ok(ApiResponse.success(invitation)))
                    .orElse(ResponseEntity.status(404).body(ApiResponse.error("Invitation not found")));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
        }
    }
    
    @GetMapping("/all")
    @Operation(summary = "Get all categorized invitations", description = "Get invitations in three categories: created, accepted, and available")
    public ResponseEntity<ApiResponse<CategorizedInvitationsResponse>> getAllCategorizedInvitations(Authentication authentication) {
        try {
            String userEmail = authentication.getName();
            CategorizedInvitationsResponse response = invitationService.getAllCategorizedInvitations(userEmail);
            return ResponseEntity.ok(ApiResponse.success(response));
        } catch (RuntimeException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
        }
    }
    
    @PostMapping("/accept")
    @Operation(summary = "Accept invitation", description = "Accept an invitation by ID")
    public ResponseEntity<ApiResponse<Void>> acceptInvitation(
            @Valid @RequestBody AcceptInvitationRequest request,
            Authentication authentication) {
        
        try {
            String userEmail = authentication.getName();
            invitationService.acceptInvitation(request.getId(), userEmail);
            return ResponseEntity.ok(new ApiResponse<>(true));
        } catch (RuntimeException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
        }
    }
    
    @PostMapping("/cancel")
    @Operation(summary = "Cancel invitation", description = "Cancel an invitation - attendee leaves or organizer deletes entire invitation")
    public ResponseEntity<ApiResponse<Void>> cancelInvitation(
            @Valid @RequestBody CancelInvitationRequest request,
            Authentication authentication) {
        
        try {
            String userEmail = authentication.getName();
            invitationService.cancelInvitation(request.getId(), userEmail);
            return ResponseEntity.ok(new ApiResponse<>(true));
        } catch (RuntimeException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
        }
    }
}