package dev.awesomedev.mirim.domain;

import jakarta.persistence.*;

import java.time.Instant;

/**
 * 이 파일이 하는 일:
 * "어떤 사용자가 어떤 체크리스트 항목을 체크했다"는 사실 하나를 기록하는 JPA 엔티티다.
 * 행이 존재하면 체크된 것, 없으면 체크 안 된 것 — 체크 해제는 행 삭제로 표현한다.
 *
 * 학습 포인트: (user, item) 조합에 유니크 제약을 걸어
 * 같은 사용자가 같은 항목을 두 번 체크한 행이 생기는 것을 DB 차원에서 막는다.
 */
@Entity
@Table(
        name = "progress",
        uniqueConstraints = @UniqueConstraint(columnNames = {"user_id", "item_id"})
)
public class Progress {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 체크한 사용자.
     *
     * 학습 포인트: @ManyToOne이 DB에서 뭐가 되나? —
     * progress 테이블에 user_id 라는 숫자 컬럼(외래키, FK)이 생기고,
     * 그 값이 users 테이블의 id를 가리킨다. 자바에선 객체 참조지만 DB에선 그냥 숫자다.
     *
     * fetch = LAZY(지연 로딩): Progress를 조회할 때 User를 즉시 JOIN해서 가져오지 않고,
     * 실제로 getUser()의 내용을 쓰는 순간에 SELECT가 나간다.
     * "체크한 항목 id 목록"처럼 User가 필요 없는 조회에서 불필요한 JOIN을 아끼기 위해서다.
     */
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "user_id")
    private User user;

    /** 체크된 체크리스트 항목. 위와 마찬가지로 DB에는 item_id 외래키 컬럼이 된다. */
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "item_id")
    private ChecklistItem item;

    /** 체크한 시각 */
    @Column(nullable = false)
    private Instant checkedAt;

    protected Progress() {
    }

    public Progress(User user, ChecklistItem item) {
        this.user = user;
        this.item = item;
        this.checkedAt = Instant.now();
    }

    public Long getId() {
        return id;
    }

    public User getUser() {
        return user;
    }

    public ChecklistItem getItem() {
        return item;
    }

    public Instant getCheckedAt() {
        return checkedAt;
    }
}
