package dev.awesomedev.mirim.service;

import dev.awesomedev.mirim.domain.User;
import dev.awesomedev.mirim.repository.CodingSubmissionRepository;
import dev.awesomedev.mirim.repository.CourseProgressRepository;
import dev.awesomedev.mirim.repository.ProgressRepository;
import dev.awesomedev.mirim.repository.QuizResultRepository;
import dev.awesomedev.mirim.repository.StudentProfileRepository;
import dev.awesomedev.mirim.repository.SubmissionRepository;
import dev.awesomedev.mirim.repository.UserRepository;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;

/**
 * 이 파일이 하는 일:
 * 학생 계정과 그 학생의 모든 개인정보·학습기록을 "완전히" 지운다(파기).
 *
 * 학습 포인트 ① — 왜 이 기능이 필요한가(법적 의무).
 *   가입 화면에서 "퇴직 시 관계 법령이 정한 기간이 지나면 지체 없이 파기한다"고 약속했다.
 *   약속했으면 실제로 지울 수단이 있어야 한다 — 없으면 그 동의문은 거짓말이 된다.
 *   개인정보보호법상 목적이 끝난 개인정보는 파기해야 하고, 특히 미성년 정보라 더 엄격하다.
 *
 * 학습 포인트 ② — 삭제 순서(외래키 제약).
 *   users 테이블은 여러 자식 테이블(제출·진도·퀴즈결과·프로필…)이 user_id로 참조한다.
 *   부모(users)를 먼저 지우려 하면 "아직 널 가리키는 자식이 있어"라며 DB가 거부한다(FK 제약).
 *   그래서 반드시 "자식 먼저, 부모 나중" 순서로 지운다. 이 순서 자체가 데이터 관계의 지도다.
 *
 * 학습 포인트 ③ — @Transactional로 "전부 아니면 전무".
 *   여러 테이블을 지우다 중간에 실패하면 "제출만 지워지고 프로필은 남은" 반쪽 상태가 된다.
 *   한 트랜잭션으로 묶어, 하나라도 실패하면 전부 되돌린다(원자성).
 */
@Service
public class StudentPurgeService {

    private final UserRepository userRepository;
    private final StudentProfileRepository studentProfileRepository;
    private final SubmissionRepository submissionRepository;
    private final CodingSubmissionRepository codingSubmissionRepository;
    private final ProgressRepository progressRepository;
    private final CourseProgressRepository courseProgressRepository;
    private final QuizResultRepository quizResultRepository;
    private final TelegramNotifier telegramNotifier;

    public StudentPurgeService(UserRepository userRepository,
                               StudentProfileRepository studentProfileRepository,
                               SubmissionRepository submissionRepository,
                               CodingSubmissionRepository codingSubmissionRepository,
                               ProgressRepository progressRepository,
                               CourseProgressRepository courseProgressRepository,
                               QuizResultRepository quizResultRepository,
                               TelegramNotifier telegramNotifier) {
        this.userRepository = userRepository;
        this.studentProfileRepository = studentProfileRepository;
        this.submissionRepository = submissionRepository;
        this.codingSubmissionRepository = codingSubmissionRepository;
        this.progressRepository = progressRepository;
        this.courseProgressRepository = courseProgressRepository;
        this.quizResultRepository = quizResultRepository;
        this.telegramNotifier = telegramNotifier;
    }

    /**
     * 한 학생의 모든 것을 파기한다. 멘토만 호출할 수 있다(컨트롤러에서 권한 보장).
     * 되돌릴 수 없는 작업이라, 대상이 STUDENT가 아니면(멘토 등) 막는다.
     */
    @Transactional
    public void purge(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "학생을 찾을 수 없습니다."));
        if (!"STUDENT".equals(user.getRole())) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "학생 계정만 파기할 수 있습니다.");
        }

        // 1) 자식 데이터부터 (참조하는 쪽 먼저)
        submissionRepository.deleteByUser(user);
        codingSubmissionRepository.deleteByUser(user);
        progressRepository.deleteByUser(user);
        courseProgressRepository.deleteByUser(user);
        quizResultRepository.deleteByUser(user);
        studentProfileRepository.deleteByUser(user);
        // 2) 마지막으로 계정 본체
        userRepository.delete(user);

        // 멘토에게 파기 사실을 알린다 — 개인정보 파기는 기록으로 남겨야 하는 "사건"이다.
        telegramNotifier.send("🗑️ 학생 계정 파기 완료: " + user.getName() + " (" + user.getUsername() + ")"
                + "\n제출·진도·퀴즈·프로필·계정을 모두 삭제했습니다.");
    }
}
