package com.malk.guangming.controller;

import com.malk.guangming.dto.AppPreviewDto;
import com.malk.guangming.dto.AppSyncResultDto;
import com.malk.guangming.repository.entity.primary.DingTalkAppMappingPo;
import com.malk.guangming.service.AppRoleSyncService;
import com.malk.server.common.McException;
import com.malk.server.common.McR;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/role-sync")
public class AppRoleSyncController {

    @Autowired
    private AppRoleSyncService appRoleSyncService;

    @PostMapping("/single")
    public McR<AppSyncResultDto> single(@RequestParam String appKey) {
        try {
            return McR.success(appRoleSyncService.syncOne(appKey));
        } catch (McException e) {
            return wrap(e);
        }
    }

    /** 异步版 /single:读可见范围+建组后立即返回(status=expanding),部门展开放后台;大部门可见范围避免 HTTP 超时。轮询 /status 至 success 再 /users-sync */
    @PostMapping("/single-async")
    public McR<AppSyncResultDto> singleAsync(@RequestParam String appKey) {
        try {
            return McR.success(appRoleSyncService.syncOneAsync(appKey));
        } catch (McException e) {
            return wrap(e);
        }
    }

    @GetMapping("/preview")
    public McR<AppPreviewDto> preview(@RequestParam String appKey) {
        try {
            return McR.success(appRoleSyncService.previewOne(appKey));
        } catch (McException e) {
            return wrap(e);
        }
    }

    @GetMapping("/status")
    public McR<DingTalkAppMappingPo> status(@RequestParam String appKey) {
        try {
            return McR.success(appRoleSyncService.getStatus(appKey));
        } catch (McException e) {
            return wrap(e);
        }
    }

    /** Phase 2:对单应用绑定钉钉角色 + 全量推送人员 */
    @PostMapping("/users-sync")
    public McR<AppSyncResultDto> usersSync(@RequestParam String appKey) {
        try {
            return McR.success(appRoleSyncService.syncUsersForApp(appKey));
        } catch (McException e) {
            return wrap(e);
        }
    }

    /** Phase 2:全表批量(顺序对每条 mapping 跑 single + users-sync) */
    @PostMapping("/all")
    public McR<java.util.List<AppSyncResultDto>> all() {
        return McR.success(appRoleSyncService.syncAll());
    }

    /** 从钉钉拉取自建应用列表 → 自动 INSERT 到映射表(已存在则跳过) */
    @PostMapping("/import-apps")
    public McR<java.util.Map> importApps() {
        try {
            return McR.success(appRoleSyncService.importApps());
        } catch (McException e) {
            return wrap(e);
        }
    }

    /** 一站式初始化:钉钉新应用 → 落库 + 建角色 + 绑人员 + 反写应用可见范围 */
    @PostMapping("/init")
    public McR<AppSyncResultDto> init(@RequestParam String agentId,
                                       @RequestParam(required = false) String appName,
                                       @RequestParam(required = false) String appGroup) {
        try {
            return McR.success(appRoleSyncService.initApp(agentId, appName, appGroup));
        } catch (McException e) {
            return wrap(e);
        }
    }

    /** 第二步(独立):仅把应用可见范围写回为已建角色(不读可见范围/不建角色/不绑人) */
    @PostMapping("/writeback")
    public McR<java.util.Map> writeback(@RequestParam String agentId) {
        try {
            return McR.success(appRoleSyncService.writeBackOne(agentId));
        } catch (McException e) {
            return wrap(e);
        }
    }

    /** 增量更新角色成员(不动应用本身可见范围) */
    @org.springframework.web.bind.annotation.PostMapping("/users-update")
    public McR<java.util.Map> usersUpdate(@RequestParam String agentId,
                                          @org.springframework.web.bind.annotation.RequestBody com.malk.guangming.dto.UsersUpdateDto body) {
        try {
            return McR.success(appRoleSyncService.updateUsers(agentId,
                    body == null ? null : body.getAddUserIds(),
                    body == null ? null : body.getDelUserIds()));
        } catch (McException e) {
            return wrap(e);
        }
    }

    private static <T> McR<T> wrap(McException e) {
        if ("404".equals(e.getCode())) return (McR<T>) McR.errorParam(e.getMessage());
        return (McR<T>) McR.errorVendor(e.getMessage(), "dingtalk");
    }
}
