package com.parkingexchange.parking.domain.model;

import com.parkingexchange.common.AssertionConcern;
import jakarta.persistence.*;

import java.time.LocalDateTime;
import java.util.UUID;

@Entity
public class ReservationRequest extends AssertionConcern {

    @Id
    @GeneratedValue
    private UUID requestId;

    @Column(nullable = false)
    private UUID arrivingUserId;

    @Column(nullable = false)
    private UUID leavingUserId;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private RequestStatus status;

    @Column(nullable = false)
    private LocalDateTime requestedAt;

    private LocalDateTime respondedAt;

    private String message;

    @ManyToOne
    private Availability availability;

    protected ReservationRequest() {
    }

    public static ReservationRequest create(UUID arrivingUserId, UUID leavingUserId,
                                            String message, Availability availability) {
        return new ReservationRequest(arrivingUserId, leavingUserId, message, availability);
    }

    private ReservationRequest(UUID arrivingUserId, UUID leavingUserId,
                               String message, Availability availability) {
        this.setArrivingUserId(arrivingUserId);
        this.setLeavingUserId(leavingUserId);
        this.setStatus(RequestStatus.PENDING);
        this.setRequestedAt(LocalDateTime.now());
        this.setMessage(message);
        this.setAvailability(availability);
    }
    // Business methods

    public void respond(UUID leavingUserId, boolean accepted) {
        assertArgumentTrue(this.leavingUserId.equals(leavingUserId), "You do not have permission to respond to this request");
        assertArgumentTrue(this.status.equals(RequestStatus.PENDING), "Request has already been responded to");

        this.setRespondedAt(LocalDateTime.now());
        this.setStatus(accepted ? RequestStatus.ACCEPTED : RequestStatus.REJECTED);
    }

    public void cancel() {
        assertArgumentTrue(this.status == RequestStatus.PENDING, "Only pending requests can be canceled.");
        this.setStatus(RequestStatus.CANCELED);
        this.setRespondedAt(LocalDateTime.now());
    }

    // Getters and Setters with validation

    public UUID getRequestId() {
        return requestId;
    }

    private void setAvailability(Availability availability) {
        this.availability = availability;
    }

    public Availability getAvailability() {
        return availability;
    }

    public UUID getArrivingUserId() {
        return arrivingUserId;
    }

    private void setArrivingUserId(UUID arrivingUserId) {
        assertArgumentNotNull(arrivingUserId, "ArrivingUserId cannot be null");
        this.arrivingUserId = arrivingUserId;
    }

    public UUID getLeavingUserId() {
        return leavingUserId;
    }

    private void setLeavingUserId(UUID leavingUserId) {
        assertArgumentNotNull(leavingUserId, "LeavingUserId cannot be null");
        this.leavingUserId = leavingUserId;
    }

    public RequestStatus getStatus() {
        return status;
    }

    private void setStatus(RequestStatus status) {
        assertArgumentNotNull(status, "Status cannot be null");
        this.status = status;
    }

    public LocalDateTime getRequestedAt() {
        return requestedAt;
    }

    private void setRequestedAt(LocalDateTime requestedAt) {
        this.requestedAt = requestedAt;
    }

    public LocalDateTime getRespondedAt() {
        return respondedAt;
    }

    private void setRespondedAt(LocalDateTime respondedAt) {
        this.respondedAt = respondedAt;
    }

    public String getMessage() {
        return message;
    }

    private void setMessage(String message) {
        this.message = message;
    }
}
Provide documentation