package kr.iotdoor.boot.service;

import kr.iotdoor.boot.mapper.UserMapper;
import kr.iotdoor.boot.model.user.AdminUserForm;
import kr.iotdoor.boot.model.user.UserAccount;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

@Service
public class UserManagementService {

    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;

    public UserManagementService(UserMapper userMapper, PasswordEncoder passwordEncoder) {
        this.userMapper = userMapper;
        this.passwordEncoder = passwordEncoder;
    }

    @Transactional(readOnly = true)
    public List<UserAccount> findUsers(String keyword) {
        return userMapper.selectUserList(StringUtils.hasText(keyword) ? keyword.trim() : null);
    }

    @Transactional(readOnly = true)
    public AdminUserForm getForm(String userIdntfNo) {
        if (!StringUtils.hasText(userIdntfNo)) {
            return new AdminUserForm();
        }

        UserAccount userAccount = userMapper.selectByUserIdntfNo(userIdntfNo);
        if (userAccount == null) {
            return new AdminUserForm();
        }

        AdminUserForm form = new AdminUserForm();
        form.setUserIdntfNo(userAccount.getUserIdntfNo());
        form.setUserId(userAccount.getUserId());
        form.setUserNm(userAccount.getUserNm());
        form.setEmlAddr(userAccount.getEmlAddr());
        form.setUserTypeCd(userAccount.getUserTypeCd());
        form.setUserSttsCd(userAccount.getUserSttsCd());
        return form;
    }

    @Transactional(readOnly = true)
    public int countActiveUsers() {
        return userMapper.countActiveUsers();
    }

    @Transactional(readOnly = true)
    public int countAdminUsers() {
        return userMapper.countAdminUsers();
    }

    @Transactional
    public String save(AdminUserForm form) {
        if (!StringUtils.hasText(form.getUserIdntfNo())) {
            return createUser(form);
        }
        return updateUser(form);
    }

    private String createUser(AdminUserForm form) {
        if (!StringUtils.hasText(form.getPassword())) {
            throw new IllegalArgumentException("신규 사용자는 비밀번호가 필요합니다.");
        }

        String userId = form.getUserId().trim();
        if (userMapper.countByUserId(userId) > 0) {
            throw new IllegalArgumentException("이미 사용 중인 아이디입니다.");
        }

        UserAccount userAccount = new UserAccount();
        userAccount.setUserIdntfNo(newIdentifier());
        userAccount.setUserId(userId);
        userAccount.setPswd(passwordEncoder.encode(form.getPassword().trim()));
        userAccount.setUserNm(form.getUserNm().trim());
        userAccount.setEmlAddr(form.getEmlAddr().trim());
        userAccount.setUserTypeCd(defaultUserType(form.getUserTypeCd()));
        userAccount.setUserSttsCd(defaultUserStatus(form.getUserSttsCd()));
        userAccount.setJoinDt(LocalDateTime.now());
        userAccount.setIndvdlInfoAgreDt(LocalDateTime.now());
        userAccount.setLockYn("N");
        userAccount.setLgnFailNmtm(0);
        userMapper.insertUser(userAccount);
        return userAccount.getUserIdntfNo();
    }

    private String updateUser(AdminUserForm form) {
        UserAccount existing = userMapper.selectByUserIdntfNo(form.getUserIdntfNo());
        if (existing == null) {
            throw new IllegalArgumentException("수정할 사용자를 찾을 수 없습니다.");
        }

        existing.setUserNm(form.getUserNm().trim());
        existing.setEmlAddr(form.getEmlAddr().trim());
        existing.setUserTypeCd(defaultUserType(form.getUserTypeCd()));
        existing.setUserSttsCd(defaultUserStatus(form.getUserSttsCd()));

        if (StringUtils.hasText(form.getPassword())) {
            existing.setPswd(passwordEncoder.encode(form.getPassword().trim()));
        } else {
            existing.setPswd(null);
        }

        userMapper.updateUser(existing);
        return existing.getUserIdntfNo();
    }

    private String defaultUserType(String userTypeCd) {
        return StringUtils.hasText(userTypeCd) ? userTypeCd.trim() : "USR";
    }

    private String defaultUserStatus(String userSttsCd) {
        return StringUtils.hasText(userSttsCd) ? userSttsCd.trim() : "A";
    }

    private String newIdentifier() {
        return UUID.randomUUID().toString().replace("-", "");
    }
}
