/*
 * Queue - A Queueing system that can be used to handle labs in higher education
 * Copyright (C) 2016-2024  Delft University of Technology
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
package nl.tudelft.queue.model;

import java.time.LocalDateTime;
import java.util.List;

import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;

import com.fasterxml.jackson.annotation.JsonIgnore;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import nl.tudelft.librador.dto.view.View;
import nl.tudelft.queue.model.embeddables.RequestEventInfo;

@Data
@Entity
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Where(clause = "deleted_at IS NULL")
@Inheritance(strategy = InheritanceType.JOINED)
@SQLDelete(sql = "UPDATE request SET deleted_at = NOW() WHERE id = ?")
public abstract class Request<QS extends QueueSession<?>> {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	/**
	 * The moment this request was created.
	 */
	@NotNull
	@Builder.Default
	private LocalDateTime createdAt = LocalDateTime.now();

	/**
	 * The information about the events that occurred for this request, summarized in an embeddable aggregate
	 * object.
	 */
	@Embedded
	@JsonIgnore
	@Builder.Default
	private RequestEventInfo eventInfo = new RequestEventInfo();

	/**
	 * The room the student group is in and wants to get a TA sent to.
	 */
	private Long room;

	/**
	 * The session this request takes part in.
	 */
	@NotNull
	@JsonIgnore
	@ManyToOne(targetEntity = QueueSession.class)
	private QS session;

	/**
	 * The comment a student placed describing their current situation or how to find them.
	 */
	@Size(max = 250)
	private String comment;

	/**
	 * The person that created the request in the name of their student group.
	 */
	@NotNull
	private Long requester;

	/**
	 * The student group for which the request was made.
	 */
	@NotNull
	private Long studentGroup;

	@Builder.Default
	private LocalDateTime deletedAt = null;

	/**
	 * @return Whether this request is revokable by the requester.
	 */
	public abstract boolean isRevokable();

	public List<Long> getAllPersonsInvolved() {
		var list = eventInfo.involvedAssistants();
		list.add(requester);
		return list;
	}

	public abstract Class<? extends View<? extends Request<QS>>> viewClass();

}
