package com.pangu.web.controller.system;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.pangu.common.core.domain.AjaxResult;

/**
 * 角色管理Controller
 * 
 * @author 湖北新华业务中台研发团队
 */
@RestController
@RequestMapping("/api/system/role")
public class SysRoleController {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 查询角色列表
     */
    @GetMapping("/list")
    public AjaxResult list(
            @RequestParam(required = false) String roleName,
            @RequestParam(required = false) String roleKey,
            @RequestParam(required = false) String status,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {

        StringBuilder sql = new StringBuilder();
        sql.append("SELECT role_id, role_name, role_key, role_sort, data_scope, status, create_time, remark ");
        sql.append("FROM sys_role WHERE del_flag = '0' ");

        List<Object> params = new ArrayList<>();
        if (roleName != null && !roleName.isEmpty()) {
            sql.append("AND role_name LIKE ? ");
            params.add("%" + roleName + "%");
        }
        if (roleKey != null && !roleKey.isEmpty()) {
            sql.append("AND role_key LIKE ? ");
            params.add("%" + roleKey + "%");
        }
        if (status != null && !status.isEmpty()) {
            sql.append("AND status = ? ");
            params.add(status);
        }

        String countSql = "SELECT COUNT(*) FROM (" + sql.toString() + ") t";
        Integer total = jdbcTemplate.queryForObject(countSql, Integer.class, params.toArray());

        sql.append("ORDER BY role_sort LIMIT ? OFFSET ?");
        params.add(pageSize);
        params.add((pageNum - 1) * pageSize);

        List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql.toString(), params.toArray());

        return AjaxResult.success().put("rows", rows).put("total", total != null ? total : 0);
    }

    /**
     * 获取角色详情
     */
    @GetMapping("/{roleId}")
    public AjaxResult getInfo(@PathVariable Long roleId) {
        String sql = "SELECT * FROM sys_role WHERE role_id = ? AND del_flag = '0'";
        Map<String, Object> role = jdbcTemplate.queryForMap(sql, roleId);

        String menuSql = "SELECT menu_id FROM sys_role_menu WHERE role_id = ?";
        List<Long> menuIds = jdbcTemplate.queryForList(menuSql, Long.class, roleId);
        role.put("menuIds", menuIds);

        return AjaxResult.success(role);
    }

    /**
     * 新增角色
     */
    @PostMapping
    public AjaxResult add(@RequestBody Map<String, Object> role) {
        String roleName = (String) role.get("roleName");
        String roleKey = (String) role.get("roleKey");

        Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(*) FROM sys_role WHERE role_name = ? AND del_flag = '0'",
                Integer.class, roleName);
        if (count != null && count > 0) {
            return AjaxResult.error("角色名称已存在");
        }

        String sql = "INSERT INTO sys_role (role_name, role_key, role_sort, data_scope, status, " +
                "create_by, create_time, remark) VALUES (?, ?, ?, ?, ?, 'admin', NOW(), ?)";

        jdbcTemplate.update(sql,
                roleName,
                roleKey,
                role.getOrDefault("roleSort", 0),
                role.getOrDefault("dataScope", "1"),
                role.getOrDefault("status", "0"),
                role.get("remark"));

        Long roleId = jdbcTemplate.queryForObject("SELECT LAST_INSERT_ID()", Long.class);
        saveRoleMenu(roleId, role);

        return AjaxResult.success();
    }

    /**
     * 修改角色
     */
    @PutMapping
    public AjaxResult edit(@RequestBody Map<String, Object> role) {
        Long roleId = Long.valueOf(role.get("roleId").toString());

        if (roleId == 1) {
            return AjaxResult.error("不允许修改超级管理员角色");
        }

        String sql = "UPDATE sys_role SET role_name = ?, role_key = ?, role_sort = ?, " +
                "data_scope = ?, status = ?, remark = ?, update_by = 'admin', update_time = NOW() " +
                "WHERE role_id = ?";

        jdbcTemplate.update(sql,
                role.get("roleName"),
                role.get("roleKey"),
                role.getOrDefault("roleSort", 0),
                role.getOrDefault("dataScope", "1"),
                role.getOrDefault("status", "0"),
                role.get("remark"),
                roleId);

        jdbcTemplate.update("DELETE FROM sys_role_menu WHERE role_id = ?", roleId);
        saveRoleMenu(roleId, role);

        return AjaxResult.success();
    }

    private void saveRoleMenu(Long roleId, Map<String, Object> role) {
        if (role.get("menuIds") != null) {
            @SuppressWarnings("unchecked")
            List<Integer> menuIds = (List<Integer>) role.get("menuIds");
            for (Integer menuId : menuIds) {
                jdbcTemplate.update("INSERT INTO sys_role_menu (role_id, menu_id) VALUES (?, ?)", roleId, menuId);
            }
        }
    }

    /**
     * 删除角色
     */
    @DeleteMapping("/{roleIds}")
    public AjaxResult remove(@PathVariable String roleIds) {
        String[] ids = roleIds.split(",");
        for (String id : ids) {
            if ("1".equals(id)) {
                return AjaxResult.error("不允许删除超级管理员角色");
            }
            Integer count = jdbcTemplate.queryForObject(
                    "SELECT COUNT(*) FROM sys_user_role WHERE role_id = ?",
                    Integer.class, Long.valueOf(id));
            if (count != null && count > 0) {
                return AjaxResult.error("角色已分配给用户，无法删除");
            }
            jdbcTemplate.update("UPDATE sys_role SET del_flag = '2' WHERE role_id = ?", Long.valueOf(id));
        }
        return AjaxResult.success();
    }

    /**
     * 修改状态
     */
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody Map<String, Object> role) {
        Long roleId = Long.valueOf(role.get("roleId").toString());
        if (roleId == 1) {
            return AjaxResult.error("不允许修改超级管理员角色状态");
        }
        String status = (String) role.get("status");
        jdbcTemplate.update("UPDATE sys_role SET status = ?, update_time = NOW() WHERE role_id = ?", status, roleId);
        return AjaxResult.success();
    }

    /**
     * 获取菜单树
     */
    @GetMapping("/menuTree")
    public AjaxResult menuTree() {
        List<Map<String, Object>> menus = jdbcTemplate.queryForList(
                "SELECT menu_id, parent_id, menu_name FROM sys_menu WHERE status = '0' ORDER BY parent_id, order_num");
        return AjaxResult.success(buildTree(menus, 0L));
    }

    /**
     * 获取角色已选菜单ID
     */
    @GetMapping("/roleMenuIds/{roleId}")
    public AjaxResult roleMenuIds(@PathVariable Long roleId) {
        List<Long> menuIds = jdbcTemplate.queryForList(
                "SELECT menu_id FROM sys_role_menu WHERE role_id = ?", Long.class, roleId);
        return AjaxResult.success(menuIds);
    }

    private List<Map<String, Object>> buildTree(List<Map<String, Object>> list, Long parentId) {
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map<String, Object> item : list) {
            Long pid = ((Number) item.get("parent_id")).longValue();
            if (pid.equals(parentId)) {
                Map<String, Object> node = new HashMap<>();
                Long id = ((Number) item.get("menu_id")).longValue();
                node.put("id", id);
                node.put("label", item.get("menu_name"));
                List<Map<String, Object>> children = buildTree(list, id);
                if (!children.isEmpty()) {
                    node.put("children", children);
                }
                result.add(node);
            }
        }
        return result;
    }
}
