package com.zioinfo.kintex.system.rolemenu;

import com.zioinfo.kintex.common.error.ApiException;
import com.zioinfo.kintex.common.error.ErrorCode;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/** 역할-메뉴 매핑 서비스. 저장은 전체 치환(clear→insert). */
@Service
public class RoleMenuService {

    private final RoleMenuMapper mapper;

    public RoleMenuService(RoleMenuMapper mapper) {
        this.mapper = mapper;
    }

    public List<RoleMenuDto> listByRole(String roleCode) {
        if (mapper.roleExists(roleCode) == 0) {
            throw new ApiException(ErrorCode.NOT_FOUND, "역할을 찾을 수 없습니다.");
        }
        return mapper.findByRole(roleCode).stream().map(RoleMenuService::toDto).toList();
    }

    @Transactional
    public void save(String roleCode, RoleMenuSaveRequest req) {
        if (mapper.roleExists(roleCode) == 0) {
            throw new ApiException(ErrorCode.NOT_FOUND, "역할을 찾을 수 없습니다.");
        }
        mapper.clear(roleCode);
        if (req.menus() != null) {
            for (RoleMenuSaveRequest.Entry e : req.menus()) {
                if (e.menuId() == null || e.menuId().isBlank()) {
                    continue;
                }
                mapper.add(roleCode, e.menuId(),
                        norm(e.readYn(), "Y"), norm(e.writeYn(), "N"));
            }
        }
    }

    private static String norm(String v, String def) {
        return "Y".equalsIgnoreCase(v) ? "Y" : ("N".equalsIgnoreCase(v) ? "N" : def);
    }

    private static RoleMenuDto toDto(Map<String, Object> r) {
        return new RoleMenuDto(str(r.get("menuId")), str(r.get("menuName")), str(r.get("parentId")),
                intv(r.get("sortOrder")), bool(r.get("mapped")), str(r.get("readYn")), str(r.get("writeYn")));
    }
    private static String str(Object o) { return o == null ? null : String.valueOf(o); }
    private static Integer intv(Object o) {
        if (o instanceof Number n) return n.intValue();
        return o == null ? 0 : Integer.parseInt(String.valueOf(o));
    }
    private static boolean bool(Object o) {
        if (o instanceof Boolean b) return b;
        return o != null && Boolean.parseBoolean(String.valueOf(o));
    }
}
