package com.writeoff.module.system.service;

import com.writeoff.common.api.PageResult;
import com.writeoff.common.exception.BusinessException;
import com.writeoff.module.system.dto.BindPlatformMenuRolesRequest;
import com.writeoff.module.system.dto.BindRoleMenusRequest;
import com.writeoff.module.system.dto.CreateMenuRequest;
import com.writeoff.module.system.dto.ReorderMenusRequest;
import com.writeoff.module.system.dto.UpdateMenuRequest;
import com.writeoff.module.system.model.MenuInfo;
import com.writeoff.security.PermissionService;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class PlatformMenuService {
    private final JdbcTemplate jdbcTemplate;
    private final PermissionService permissionService;

    private static final RowMapper<MenuInfo> MENU_ROW_MAPPER = (rs, n) -> new MenuInfo(
            rs.getLong("id"),
            rs.getString("menu_code"),
            rs.getString("menu_name"),
            rs.getString("route_path"),
            rs.getString("permission_code"),
            rs.getInt("sort_no"),
            rs.getString("status")
    );

    public PlatformMenuService(JdbcTemplate jdbcTemplate, PermissionService permissionService) {
        this.jdbcTemplate = jdbcTemplate;
        this.permissionService = permissionService;
    }

    public PageResult<MenuInfo> list() {
        List<MenuInfo> list = jdbcTemplate.query(
                "SELECT id, menu_code, menu_name, route_path, permission_code, sort_no, status " +
                        "FROM platform_menu WHERE is_deleted=0 ORDER BY sort_no ASC, id ASC",
                MENU_ROW_MAPPER
        );
        return new PageResult<MenuInfo>(list, list.size(), 1, 200);
    }

    public List<MenuInfo> currentUserMenus(Long userId) {
        List<MenuInfo> menus = jdbcTemplate.query(
                "SELECT DISTINCT m.id, m.menu_code, m.menu_name, m.route_path, m.permission_code, m.sort_no, m.status " +
                        "FROM platform_user_role ur " +
                        "JOIN platform_role_menu rm ON ur.role_id=rm.role_id " +
                        "JOIN platform_menu m ON rm.menu_id=m.id " +
                        "WHERE ur.user_id=? AND m.is_deleted=0 AND m.status='ENABLED' " +
                        "ORDER BY m.sort_no ASC, m.id ASC",
                MENU_ROW_MAPPER,
                userId
        );
        java.util.List<String> perms = permissionService.getPlatformPermissions(userId);
        java.util.Set<String> permSet = new java.util.HashSet<String>(perms);
        java.util.List<MenuInfo> filtered = new java.util.ArrayList<MenuInfo>();
        for (MenuInfo menu : menus) {
            String code = menu.getPermissionCode();
            if (code == null || code.trim().isEmpty() || permSet.contains(code)) {
                filtered.add(menu);
            }
        }
        return filtered;
    }

    public MenuInfo create(CreateMenuRequest request) {
        assertPermissionExists(request.getPermissionCode().trim());
        Integer dup = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM platform_menu WHERE menu_code=?",
                Integer.class,
                request.getMenuCode().trim()
        );
        if (dup != null && dup > 0) {
            throw new BusinessException(10001, "菜单编码已存在");
        }
        jdbcTemplate.update(
                "INSERT INTO platform_menu (menu_code, menu_name, route_path, permission_code, sort_no, status, is_deleted, created_by, updated_by) " +
                        "VALUES (?, ?, ?, ?, ?, 'ENABLED', 0, 0, 0)",
                request.getMenuCode().trim(),
                request.getMenuName().trim(),
                request.getRoutePath().trim(),
                request.getPermissionCode().trim(),
                request.getSortNo()
        );
        Long id = jdbcTemplate.queryForObject("SELECT IFNULL(MAX(id), 0) FROM platform_menu", Long.class);
        return findById(id == null ? 0L : id);
    }

    public MenuInfo update(Long id, UpdateMenuRequest request) {
        assertMenuExists(id);
        assertPermissionExists(request.getPermissionCode().trim());
        String status = request.getStatus().trim().toUpperCase();
        if (!"ENABLED".equals(status) && !"DISABLED".equals(status)) {
            throw new BusinessException(10001, "菜单状态非法");
        }
        jdbcTemplate.update(
                "UPDATE platform_menu SET menu_name=?, route_path=?, permission_code=?, sort_no=?, status=?, updated_at=CURRENT_TIMESTAMP " +
                        "WHERE id=?",
                request.getMenuName().trim(),
                request.getRoutePath().trim(),
                request.getPermissionCode().trim(),
                request.getSortNo(),
                status,
                id
        );
        return findById(id);
    }

    public void reorderMenus(ReorderMenusRequest request) {
        if (request.getMenus() == null || request.getMenus().isEmpty()) {
            return;
        }
        for (ReorderMenusRequest.MenuSortItem item : request.getMenus()) {
            assertMenuExists(item.getId());
            jdbcTemplate.update(
                    "UPDATE platform_menu SET sort_no=?, updated_at=CURRENT_TIMESTAMP WHERE id=?",
                    item.getSortNo(),
                    item.getId()
            );
        }
    }

    public List<Long> getMenuRoleIds(Long menuId) {
        assertMenuExists(menuId);
        return jdbcTemplate.queryForList(
                "SELECT role_id FROM platform_role_menu WHERE menu_id=? ORDER BY role_id ASC",
                Long.class,
                menuId
        );
    }

    public List<String> getMenuRoleNames(Long menuId) {
        assertMenuExists(menuId);
        return jdbcTemplate.queryForList(
                "SELECT r.role_name FROM platform_role_menu rm " +
                        "JOIN platform_role r ON rm.role_id=r.id " +
                        "WHERE rm.menu_id=? AND r.is_deleted=0 ORDER BY r.id ASC",
                String.class,
                menuId
        );
    }

    public void bindMenuRoles(Long menuId, BindPlatformMenuRolesRequest request) {
        assertMenuExists(menuId);
        jdbcTemplate.update("DELETE FROM platform_role_menu WHERE menu_id=?", menuId);
        if (request.getRoleIds() == null || request.getRoleIds().isEmpty()) {
            return;
        }
        Long nextId = jdbcTemplate.queryForObject("SELECT IFNULL(MAX(id), 0) + 1 FROM platform_role_menu", Long.class);
        long currentId = nextId == null ? 1L : nextId;
        for (Long roleId : request.getRoleIds()) {
            assertRoleExists(roleId);
            jdbcTemplate.update(
                    "INSERT INTO platform_role_menu (id, role_id, menu_id) VALUES (?, ?, ?)",
                    currentId++,
                    roleId,
                    menuId
            );
        }
    }

    public List<Long> getRoleMenuIds(Long roleId) {
        assertRoleExists(roleId);
        return jdbcTemplate.queryForList(
                "SELECT menu_id FROM platform_role_menu WHERE role_id=? ORDER BY menu_id ASC",
                Long.class,
                roleId
        );
    }

    public void bindRoleMenus(Long roleId, BindRoleMenusRequest request) {
        assertRoleExists(roleId);
        jdbcTemplate.update("DELETE FROM platform_role_menu WHERE role_id=?", roleId);
        if (request.getMenuIds() == null || request.getMenuIds().isEmpty()) {
            return;
        }
        Long nextId = jdbcTemplate.queryForObject("SELECT IFNULL(MAX(id), 0) + 1 FROM platform_role_menu", Long.class);
        long currentId = nextId == null ? 1L : nextId;
        for (Long menuId : request.getMenuIds()) {
            assertMenuExists(menuId);
            jdbcTemplate.update(
                    "INSERT INTO platform_role_menu (id, role_id, menu_id) VALUES (?, ?, ?)",
                    currentId++,
                    roleId,
                    menuId
            );
        }
    }

    private MenuInfo findById(Long id) {
        List<MenuInfo> list = jdbcTemplate.query(
                "SELECT id, menu_code, menu_name, route_path, permission_code, sort_no, status " +
                        "FROM platform_menu WHERE id=? AND is_deleted=0",
                MENU_ROW_MAPPER,
                id
        );
        if (list.isEmpty()) {
            throw new BusinessException(10003, "菜单不存在");
        }
        return list.get(0);
    }

    private void assertMenuExists(Long menuId) {
        Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM platform_menu WHERE id=? AND is_deleted=0",
                Integer.class,
                menuId
        );
        if (count == null || count == 0) {
            throw new BusinessException(10003, "菜单不存在");
        }
    }

    private void assertRoleExists(Long roleId) {
        Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM platform_role WHERE id=? AND is_deleted=0",
                Integer.class,
                roleId
        );
        if (count == null || count == 0) {
            throw new BusinessException(10003, "角色不存在");
        }
    }

    private void assertPermissionExists(String permissionCode) {
        Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM platform_permission WHERE permission_code=?",
                Integer.class,
                permissionCode
        );
        if (count == null || count == 0) {
            throw new BusinessException(10003, "权限码不存在");
        }
    }
}
