package dev.awesomedev.mirim.domain;

import jakarta.persistence.*;

import java.time.Instant;

/**
 * 이 파일이 하는 일:
 * "누가, 언제, 어떤 개인정보(PII)를, 어느 IP에서 열람/내보냈/파기했나"를 남기는 감사로그 테이블.
 *
 * 학습 포인트 ① — 왜 감사로그가 필요한가?
 *   수습생 인적사항(이름·전화·주소·생년월일·비상연락처)은 미성년자의 개인정보다.
 *   개인정보보호법상 회사는 "누가 개인정보에 접근·제공받았는지"를 기록·보관할 의무가 있고,
 *   유출 사고가 나면 이 기록이 "어디서 새어 나갔나"를 추적하는 최초의 단서가 된다.
 *   특히 명단 CSV 다운로드는 데이터가 서버 밖(경리 PC·엑셀)으로 나가는 순간이라 반드시 남긴다.
 *
 * 학습 포인트 ② — 왜 엔티티 연관(User) 없이 값만 복사해 두나?
 *   감사로그는 "그 시점의 사실"을 박제하는 것이다. 나중에 그 학생이 파기(삭제)돼도
 *   "예전에 누가 열람했다"는 기록은 남아야 한다. User를 FK로 연결하면 학생 삭제 시
 *   기록이 함께 사라지거나 참조가 깨진다. 그래서 actor/targetUserId를 값(String/Long)으로 저장한다.
 *   (덤으로 open-in-view:false 환경에서 LAZY 연관 예외 걱정도 없다.)
 *
 * 학습 포인트 ③ — 비밀번호·주민번호 같은 민감정보는 감사로그에도 남기지 않는다.
 *   "누가 무엇을 했다"는 남기되, "그 내용 자체"(비밀번호 값 등)는 남기지 않는다.
 */
@Entity
@Table(name = "audit_log", indexes = @Index(name = "ix_audit_log_created_at", columnList = "createdAt"))
public class AuditLog {

    /** 감사로그에 남길 행위의 종류. 문자열로 저장해 사람이 읽고 조회·필터하기 쉽게 한다. */
    public enum Action {
        EXPORT_STUDENT_CSV,      // 수습생 명단 CSV 다운로드 (최고 민감 — 데이터가 서버 밖으로)
        VIEW_STUDENT_ROSTER,     // 수습생 인적사항 전체 목록 조회 (JSON)
        RESET_STUDENT_PASSWORD,  // 멘토가 학생 비밀번호 재설정 (계정 통제)
        PURGE_STUDENT            // 학생 계정·개인정보 영구 파기 (비가역)
    }

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

    /** 행위자(로그인 아이디). */
    @Column(nullable = false, length = 40)
    private String actor;

    /** 행위자 역할(MENTOR 등) — 나중에 "멘토가 한 일"만 걸러 보기 위해. */
    @Column(nullable = false, length = 20)
    private String actorRole;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 30)
    private Action action;

    /** 사람이 읽을 설명(예: "명단 CSV 다운로드", "학생 #3 파기"). 민감값은 넣지 않는다. */
    @Column(length = 200)
    private String detail;

    /** 대상 학생의 id(개별 대상이 있을 때만). 명단 전체 조회처럼 대상이 '전체'면 null. */
    @Column
    private Long targetUserId;

    @Column(nullable = false, length = 45)
    private String ip;

    @Column(nullable = false)
    private Instant createdAt;

    protected AuditLog() {
    }

    public AuditLog(String actor, String actorRole, Action action, String detail,
                    Long targetUserId, String ip, Instant createdAt) {
        this.actor = actor;
        this.actorRole = actorRole;
        this.action = action;
        this.detail = detail;
        this.targetUserId = targetUserId;
        this.ip = ip;
        this.createdAt = createdAt;
    }

    public Long getId() {
        return id;
    }

    public String getActor() {
        return actor;
    }

    public String getActorRole() {
        return actorRole;
    }

    public Action getAction() {
        return action;
    }

    public String getDetail() {
        return detail;
    }

    public Long getTargetUserId() {
        return targetUserId;
    }

    public String getIp() {
        return ip;
    }

    public Instant getCreatedAt() {
        return createdAt;
    }
}
