package com.multi.backend5_1_multi_fc.user.dao;

import com.multi.backend5_1_multi_fc.user.dto.UserDto;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.EmptyResultDataAccessException; // [추가]
import org.springframework.jdbc.core.BeanPropertyRowMapper; // [추가]
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

// import java.util.List; // (Moon님 코드에 없으므로 삭제)

@Repository
@RequiredArgsConstructor
public class UserDao {

    private final JdbcTemplate jdbcTemplate;

    // 회원가입 (INSERT)
    public void insertUser(UserDto user) {

        String sql = "INSERT INTO User (username, password, nickname, email, level, position, gender, address, profile_image) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";

        jdbcTemplate.update(sql,
                user.getUsername(),
                user.getPassword(), // 암호화된 비밀번호
                user.getNickname(),
                user.getEmail(),
                user.getLevel(),
                user.getPosition(),
                user.getGender(),
                user.getAddress(),
                user.getProfileImage() // [수정] user.getProfile_image() -> user.getProfileImage()
        );
    }

    // 아이디 중복 체크
    public int countByUsername(String username) {
        String sql = "SELECT COUNT(*) FROM User WHERE username = ?";
        // 결과가 0 또는 1로 나옴
        return jdbcTemplate.queryForObject(sql, Integer.class, username);
    }

    // 이메일 중복 체크
    public int countByEmail(String email) {
        String sql = "SELECT COUNT(*) FROM User WHERE email = ?";
        return jdbcTemplate.queryForObject(sql, Integer.class, email);
    }

    // 닉네임 중복 체크
    public int countByNickname(String nickname) {
        String sql = "SELECT COUNT(*) FROM User WHERE nickname = ?";
        return jdbcTemplate.queryForObject(sql, Integer.class, nickname);
    }

    // 로그인 기능용
    // UserService의 login 메서드가 호출하는 메서드
    public UserDto findUserByUsername(String username) {
        String sql = "SELECT * FROM User WHERE username = ?";
        try {
            // queryForObject는 결과가 1개일 때 사용합니다.
            // BeanPropertyRowMapper가 DB의 snake_case(user_id)를 DTO의 camelCase(userId)로 자동 변환해줍니다.
            return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(UserDto.class), username);
        } catch (EmptyResultDataAccessException e) {
            // 일치하는 유저가 없으면 null을 반환합니다.
            return null;
        }
    }

    // 1. (아이디 찾기용) 이메일 주소로 사용자 아이디(username)를 찾음
    public String findUsernameByEmail(String email) {
        String sql = "SELECT username FROM User WHERE email = ?";
        try {
            return jdbcTemplate.queryForObject(sql, String.class, email);
        } catch (EmptyResultDataAccessException e) {
            // 일치하는 이메일이 없으면 null 반환
            return null;
        }
    }

    // 2. (비밀번호 찾기용) 아이디와 이메일이 모두 일치하는 사용자가 있는지 확인
    public boolean checkUserByUsernameAndEmail(String username, String email) {
        String sql = "SELECT COUNT(*) FROM User WHERE username = ? AND email = ?";
        Integer count = jdbcTemplate.queryForObject(sql, Integer.class, username, email);
        return count != null && count > 0;
    }

    // 3. (비밀번호 찾기용) 인증번호와 만료시간을 DB에 저장
    public void updateResetCode(String email, String code) {
        // 인증코드를 저장하고, 만료 시간을 '현재시간 + 5분'으로 설정
        String sql = "UPDATE User SET reset_code = ?, reset_code_expires = DATE_ADD(NOW(), INTERVAL 5 MINUTE) WHERE email = ?";
        jdbcTemplate.update(sql, code, email);
    }

    // 4. (비밀번호 찾기용) 이메일과 코드로 사용자 검증
    public boolean verifyResetCode(String email, String code) {
        // 이메일과 코드가 일치하고, 만료시간이 지나지 않았는지 확인
        String sql = "SELECT COUNT(*) FROM User WHERE email = ? AND reset_code = ? AND reset_code_expires > NOW()";
        Integer count = jdbcTemplate.queryForObject(sql, Integer.class, email, code);
        return count != null && count > 0;
    }

    // 5. (비밀번호 찾기용) 새 비밀번호로 업데이트
    public void updatePasswordByEmail(String email, String newEncryptedPassword) {
        // 인증이 완료되었으므로 코드와 만료시간은 초기화(NULL)
        String sql = "UPDATE User SET password = ?, reset_code = NULL, reset_code_expires = NULL WHERE email = ?";
        jdbcTemplate.update(sql, newEncryptedPassword, email);
    }

    // userId로 사용자 정보 조회
    public UserDto findByUserId(Long userId) {
        String sql = "SELECT * FROM User WHERE user_id = ?";
        try {
            return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(UserDto.class), userId);
        } catch (EmptyResultDataAccessException e) {
            // 일치하는 유저가 없으면 null을 반환합니다.
            return null;
        }
    }
    // 닉네임으로 사용자 검색 (부분 일치)
    public List<UserDto> findUsersByNickname(String nickname) {
        String sql = "SELECT * FROM User WHERE nickname LIKE ? LIMIT 10";
        try {
            return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(UserDto.class), "%" + nickname + "%");
        } catch (EmptyResultDataAccessException e) {
            return new ArrayList<>();
        }
    }

}