package com.dne.ems.model;

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

import com.dne.ems.model.enums.FeedbackStatus;
import com.dne.ems.model.enums.PollutionType;
import com.dne.ems.model.enums.SeverityLevel;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Lob;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 环境问题反馈实体
 *
 * <p>系统核心实体，记录用户提交的环境问题报告的所有细节，
 * 包括位置、严重程度和处理状态等信息，映射到'feedback'表。
 *
 * <p>主要功能：
 * <ul>
 *   <li>记录环境问题详情</li>
 *   <li>跟踪处理状态</li>
 *   <li>关联附件和任务</li>
 * </ul>
 *
 * @author DNE开发团队
 * @version 1.0
 * @since 2025-06-16
 */
@Entity
@Table(name = "feedback")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Feedback {

    /**
     * 主键ID，反馈记录的唯一标识
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 事件ID，人类可读的唯一标识符
     *
     * <p>用于外部引用和用户沟通
     */
    @Column(nullable = false, unique = true)
    private String eventId;

    /**
     * A brief, descriptive title for the feedback.
     */
    @Column(nullable = false)
    private String title;

    /**
     * A detailed description of the environmental issue.
     * Stored as a large object (TEXT/CLOB) to accommodate long text.
     */
    @Lob // For longer text
    private String description;

    /**
     * The type of pollution being reported.
     * @see PollutionType
     */
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private PollutionType pollutionType;

    /**
     * The perceived severity level of the issue.
     * @see SeverityLevel
     */
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private SeverityLevel severityLevel;

    /**
     * The current status of the feedback in the processing workflow.
     * @see FeedbackStatus
     */
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private FeedbackStatus status;

    /**
     * The text-based address or location description of the event.
     */
    private String textAddress;

    /**
     * The x-coordinate of the grid cell where the event occurred.
     */
    private Integer gridX;

    /**
     * The y-coordinate of the grid cell where the event occurred.
     */
    private Integer gridY;

    /**
     * The ID of the user who submitted the feedback.
     */
    private Long submitterId;

    /**
     * The timestamp when the feedback was created.
     * Automatically set and not updatable.
     */
    @Builder.Default
    @Column(nullable = false, updatable = false)
    private LocalDateTime createdAt = LocalDateTime.now();

    /**
     * The timestamp of the last update to the feedback.
     * Automatically set on creation and updated via {@link #onPreUpdate()}.
     */
    @Builder.Default
    @Column(nullable = false)
    private LocalDateTime updatedAt = LocalDateTime.now();

    /**
     * The {@link UserAccount} who submitted the feedback.
     * This provides a direct link to the user entity.
     */
    @ManyToOne
    @JoinColumn(name = "user_id")
    private UserAccount user;

    /**
     * The geographical latitude where the feedback was reported. Essential for location-based services.
     */
    private Double latitude;

    /**
     * The geographical longitude where the feedback was reported. Essential for location-based services.
     */
    private Double longitude;

    /**
     * A list of {@link Attachment} files associated with this feedback.
     * Configured to cascade all operations and remove orphan attachments.
     */
    @Builder.Default
    @OneToMany(mappedBy = "feedback", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Attachment> attachments = new ArrayList<>();

    /**
     * The task associated with this feedback.
     * Establishes a bidirectional one-to-one relationship.
     * The 'feedback' field in the Task entity owns this relationship.
     */
    @OneToOne(mappedBy = "feedback", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Task task;

    /**
     * JPA callback method to automatically update the {@code updatedAt} timestamp before an entity update.
     */
    @PreUpdate
    public void onPreUpdate() {
        this.updatedAt = LocalDateTime.now();
    }
}