package com.zioinfo.kintex.system.menu;

import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** 메뉴 트리 구성·관리. 역할별 노출(required_role) 필터를 적용해 사이드바 트리를 제공한다. */
@Service
public class MenuService {

    private final MenuMapper mapper;

    public MenuService(MenuMapper mapper) {
        this.mapper = mapper;
    }

    /** 사용자 전역역할(rank)로 필터링된 메뉴 트리. isAdmin 이면 전체. */
    public List<MenuDto> tree(String userRole, boolean isAdmin) {
        List<Map<String, Object>> rows = mapper.findAll();
        int rank = rank(isAdmin ? "ADMIN" : userRole);
        // 1) 노드 생성(가시성 필터: use_yn=Y 이고 required_role 이하)
        Map<String, MenuDto> byId = new HashMap<>();
        List<Map<String, Object>> visible = new ArrayList<>();
        for (Map<String, Object> r : rows) {
            if (!"Y".equals(str(r.get("useYn")))) continue;
            String req = str(r.get("requiredRole"));
            if (req != null && rank < rank(req)) continue;
            visible.add(r);
        }
        for (Map<String, Object> r : visible) {
            byId.put(str(r.get("id")), toNode(r, new ArrayList<>()));
        }
        // 2) 부모-자식 연결
        List<MenuDto> roots = new ArrayList<>();
        for (Map<String, Object> r : visible) {
            String id = str(r.get("id"));
            String parentId = str(r.get("parentId"));
            MenuDto node = byId.get(id);
            if (parentId != null && byId.containsKey(parentId)) {
                byId.get(parentId).children().add(node);
            } else {
                roots.add(node);
            }
        }
        return roots;
    }

    public List<MenuDto> flat() {
        return mapper.findAll().stream().map(r -> toNode(r, List.of())).toList();
    }

    public void save(MenuDto m) {
        Map<String, Object> p = new HashMap<>();
        p.put("id", m.id());
        p.put("parentId", m.parentId());
        p.put("menuName", m.menuName());
        p.put("menuPath", m.menuPath());
        p.put("icon", m.icon());
        p.put("prgType", m.prgType());
        p.put("requiredRole", m.requiredRole());
        p.put("sortOrder", m.sortOrder());
        p.put("useYn", m.useYn());
        mapper.upsert(p);
    }

    public void delete(String id) {
        mapper.delete(id);
    }

    private static MenuDto toNode(Map<String, Object> r, List<MenuDto> children) {
        return new MenuDto(str(r.get("id")), str(r.get("parentId")), str(r.get("menuName")),
                str(r.get("menuPath")), str(r.get("icon")), str(r.get("prgType")),
                str(r.get("requiredRole")), intVal(r.get("sortOrder")), str(r.get("useYn")), children);
    }

    /** 역할 서열: USER<MANAGER<ADMIN. */
    private static int rank(String role) {
        if (role == null) return 0;
        return switch (role) {
            case "ADMIN" -> 3;
            case "MANAGER" -> 2;
            case "USER" -> 1;
            default -> 0;
        };
    }
    private static String str(Object o) { return o == null ? null : String.valueOf(o); }
    private static int intVal(Object o) {
        if (o instanceof Number n) return n.intValue();
        try { return o == null ? 0 : Integer.parseInt(String.valueOf(o)); }
        catch (NumberFormatException e) { return 0; }
    }
}
