package dev.awesomedev.mirim.domain;

import jakarta.persistence.*;

import java.time.Instant;
import java.time.LocalDate;

/**
 * 이 파일이 하는 일:
 * 수습생의 인적사항(개인정보)을 담는 테이블. 로그인 정보(users)와 "1:1"로 짝을 이룬다.
 *
 * 학습 포인트 ① — 왜 users에 다 넣지 않고 테이블을 나누나?
 *   1) 관심사 분리: users는 "로그인에 필요한 것"만, 여기는 "인사에 필요한 것"만 담는다.
 *   2) 개인정보 보호(privacy by design): SQL 입문 코스에서 학생들이 users 테이블을 실습한다.
 *      개인정보를 users에 섞으면 실습하다 동료의 주소·연락처가 그대로 보인다.
 *      테이블을 나누면 users에는 개인정보가 없어, 실습과 개인정보 보호가 부딪치지 않는다.
 *
 * 학습 포인트 ② — 여기에 주민등록번호·계좌번호는 없다(일부러).
 *   그런 민감정보는 법적으로 암호화 저장 의무가 있고 유출 시 책임이 무겁다.
 *   학습용 플랫폼에 두지 않고, 근로계약서(종이 인사 절차)로 받는다.
 *   "받을 수 있는 것"과 "받아도 되는 것"은 다르다 — 꼭 필요한 최소한만 모은다(최소 수집 원칙).
 */
@Entity
@Table(name = "student_profile")
public class StudentProfile {

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

    /**
     * 이 개인정보가 누구 것인지. users와 1:1.
     * 학습 포인트: @OneToOne도 DB에선 외래키(user_id) 컬럼 하나다. unique를 걸어
     * "한 사용자에 프로필 하나"를 DB가 보장하게 한다.
     */
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "user_id", unique = true)
    private User user;

    /**
     * 회사 이메일의 아이디 부분만 저장한다(예: "hong").
     * 학습 포인트: 도메인(@awesomedev.dev)은 회사 공통이라 저장하지 않고 붙여서 만든다.
     * 같은 값을 모든 행에 반복 저장하는 건 낭비이고, 회사 도메인이 바뀌면 한 곳만 고치면 된다.
     * 전체 이메일이 필요할 때 fullEmail()로 조립한다.
     */
    @Column(name = "company_email_local", nullable = false, unique = true, length = 40)
    private String companyEmailLocal;

    @Column(nullable = false)
    private LocalDate birthDate;

    @Column(nullable = false, length = 20)
    private String phone;

    @Column(nullable = false, columnDefinition = "text")
    private String address;

    /** 출신 학교 */
    @Column(nullable = false, length = 60)
    private String school;

    /** 전공/학과 */
    @Column(nullable = false, length = 60)
    private String major;

    /** 비상 연락처 — 이름 / 관계 / 전화번호 */
    @Column(nullable = false, length = 30)
    private String emergencyName;

    @Column(nullable = false, length = 20)
    private String emergencyRelation;

    @Column(nullable = false, length = 20)
    private String emergencyPhone;

    /**
     * 개인정보 수집·이용에 동의한 시각.
     * 학습 포인트: 동의는 "체크박스를 확인했다"로 끝나지 않는다. 개인정보보호법상
     * 회사는 "언제 동의받았는지"를 증명할 수 있어야 한다. 그래서 체크 여부(boolean)가
     * 아니라 동의 시각(timestamp)을 저장한다 — 시각이 있으면 동의했다는 사실도 담긴다.
     */
    @Column(nullable = false)
    private Instant privacyConsentAt;

    protected StudentProfile() {
    }

    public StudentProfile(User user, String companyEmailLocal, LocalDate birthDate, String phone,
                          String address, String school, String major,
                          String emergencyName, String emergencyRelation, String emergencyPhone,
                          Instant privacyConsentAt) {
        this.user = user;
        this.companyEmailLocal = companyEmailLocal;
        this.birthDate = birthDate;
        this.phone = phone;
        this.address = address;
        this.school = school;
        this.major = major;
        this.emergencyName = emergencyName;
        this.emergencyRelation = emergencyRelation;
        this.emergencyPhone = emergencyPhone;
        this.privacyConsentAt = privacyConsentAt;
    }

    /**
     * 내 정보 수정 — 가입 때 적은 인적사항의 오타·변경을 본인이 고칠 수 있게.
     * 학습 포인트: setter를 열어두지 않고 "수정"이라는 의도가 담긴 메서드 하나로 받는다.
     * (동의 시각 privacyConsentAt은 여기 없다 — 증빙은 본인도 수정할 수 없어야 하니까.)
     */
    public void update(String companyEmailLocal, LocalDate birthDate, String phone,
                       String address, String school, String major,
                       String emergencyName, String emergencyRelation, String emergencyPhone) {
        this.companyEmailLocal = companyEmailLocal;
        this.birthDate = birthDate;
        this.phone = phone;
        this.address = address;
        this.school = school;
        this.major = major;
        this.emergencyName = emergencyName;
        this.emergencyRelation = emergencyRelation;
        this.emergencyPhone = emergencyPhone;
    }

    /** 회사 도메인은 여기 한 곳에서만 정의한다. 바뀌면 이 상수만 고친다. */
    public static final String COMPANY_DOMAIN = "awesomedev.dev";

    /** 저장된 아이디 부분에 회사 도메인을 붙여 전체 이메일을 만든다. */
    public String fullEmail() {
        return companyEmailLocal + "@" + COMPANY_DOMAIN;
    }

    public Long getId() {
        return id;
    }

    public User getUser() {
        return user;
    }

    public String getCompanyEmailLocal() {
        return companyEmailLocal;
    }

    public LocalDate getBirthDate() {
        return birthDate;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }

    public String getSchool() {
        return school;
    }

    public String getMajor() {
        return major;
    }

    public String getEmergencyName() {
        return emergencyName;
    }

    public String getEmergencyRelation() {
        return emergencyRelation;
    }

    public String getEmergencyPhone() {
        return emergencyPhone;
    }

    public Instant getPrivacyConsentAt() {
        return privacyConsentAt;
    }
}
