package com.erp.crosstenant;

import com.erp.dto.ApiResponse;
import com.erp.provisioning.CompanyAuditLogService;
import com.erp.service.RoleService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

/**
 * SUPER_ADMIN 의 cross-tenant ROLE WRITE/READ 엔드포인트 — Phase 2.
 *
 * 권한 그룹은 회사 DB 의 AUTHORITY_MASTER, 멤버/메뉴 권한도 회사 DB 내부 테이블.
 * 어느 회사의 권한 그룹인지 알아야 라우팅 가능 → 모든 endpoint 가 company_code 필수
 * (body 또는 query param).
 *
 * 단일 회사 모드 endpoint ({@link com.erp.controller.RoleController}) 는 무수정.
 *
 * @see CrossTenantExecutor
 * @see CrossTenantUserController  // 같은 패턴, Phase 1
 */
@RestController
@RequestMapping("/api/admin/cross-tenant/roles")
@RequiredArgsConstructor
@Slf4j
public class CrossTenantRoleController {

    private final CrossTenantExecutor executor;
    private final RoleService roleService;
    private final CompanyAuditLogService auditLogService;

    // ── 권한 그룹 CRUD ──────────────────────────────────────────────

    /**
     * POST /api/admin/cross-tenant/roles
     * body: { company_code, auth_name, auth_code, ... }
     */
    @PostMapping
    public ResponseEntity<ApiResponse<Map<String, Object>>> createRole(
            HttpServletRequest request,
            @RequestAttribute(value = "user_id", required = false) String writer,
            @RequestBody Map<String, Object> body) {
        ResponseEntity<ApiResponse<Map<String, Object>>> g = guardMap(request);
        if (g != null) return g;

        String targetCompany = (String) body.get("company_code");
        String actorId = (String) request.getAttribute("user_id");
        try {
            Map<String, Object> result = executor.runInCompany(targetCompany, () -> {
                Map<String, Object> params = new HashMap<>(body);
                params.put("writer", writer);
                params.put("objid", "AM" + System.currentTimeMillis());
                if (params.containsKey("role_name") && !params.containsKey("auth_name")) {
                    params.put("auth_name", params.get("role_name"));
                }
                if (params.containsKey("role_code") && !params.containsKey("auth_code")) {
                    params.put("auth_code", params.get("role_code"));
                }
                return roleService.createRoleGroup(params);
            });
            auditLogService.log(targetCompany, actorId,
                    CompanyAuditLogService.ACTION_CT_ROLE_UPDATE,
                    (String) body.get("auth_code"),
                    auditDetails(request, null));
            return ResponseEntity.status(HttpStatus.CREATED).body(ApiResponse.success(result, "권한 그룹 생성 성공"));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        }
    }

    /**
     * PUT /api/admin/cross-tenant/roles/{id}  body: { company_code, ... }
     */
    @PutMapping("/{id}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> updateRole(
            HttpServletRequest request,
            @PathVariable String id,
            @RequestAttribute(value = "user_id", required = false) String writer,
            @RequestBody Map<String, Object> body) {
        ResponseEntity<ApiResponse<Map<String, Object>>> g = guardMap(request);
        if (g != null) return g;

        String targetCompany = (String) body.get("company_code");
        String actorId = (String) request.getAttribute("user_id");
        try {
            Map<String, Object> result = executor.runInCompany(targetCompany, () -> {
                Map<String, Object> params = new HashMap<>(body);
                params.put("objid", id);
                params.put("writer", writer);
                if (params.containsKey("role_name") && !params.containsKey("auth_name")) {
                    params.put("auth_name", params.get("role_name"));
                }
                if (params.containsKey("role_code") && !params.containsKey("auth_code")) {
                    params.put("auth_code", params.get("role_code"));
                }
                return roleService.updateRoleGroup(params);
            });
            auditLogService.log(targetCompany, actorId,
                    CompanyAuditLogService.ACTION_CT_ROLE_UPDATE,
                    id,
                    auditDetails(request, id));
            return ResponseEntity.ok(ApiResponse.success(result, "권한 그룹 수정 성공"));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        }
    }

    /**
     * DELETE /api/admin/cross-tenant/roles/{id}?company_code=TEST02
     */
    @DeleteMapping("/{id}")
    public ResponseEntity<ApiResponse<Void>> deleteRole(
            HttpServletRequest request,
            @PathVariable String id,
            @RequestParam("company_code") String companyCode) {
        ResponseEntity<ApiResponse<Void>> g = guardVoid(request);
        if (g != null) return g;

        String actorId = (String) request.getAttribute("user_id");
        try {
            executor.runInCompany(companyCode, () -> {
                Map<String, Object> p = new HashMap<>();
                p.put("objid", id);
                roleService.deleteRoleGroup(p);
            });
            auditLogService.log(companyCode, actorId,
                    CompanyAuditLogService.ACTION_CT_ROLE_UPDATE,
                    id,
                    auditDetails(request, id));
            return ResponseEntity.ok(ApiResponse.success(null, "권한 그룹 삭제 성공"));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        }
    }

    // ── 워크스페이스 / 메뉴 트리 ─────────────────────────────────

    /**
     * GET /api/admin/cross-tenant/roles/{id}/workspace?company_code=TEST02
     * 그룹 + 멤버 + non-members + 메뉴 + 메뉴 권한 한 번에.
     */
    @GetMapping("/{id}/workspace")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getWorkspace(
            HttpServletRequest request,
            @PathVariable String id,
            @RequestParam("company_code") String companyCode) {
        ResponseEntity<ApiResponse<Map<String, Object>>> g = guardMap(request);
        if (g != null) return g;

        try {
            Map<String, Object> ws = executor.runInCompany(companyCode,
                    () -> roleService.getRoleWorkspace(id));
            if (ws == null) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND)
                        .body(ApiResponse.error("권한 그룹을 찾을 수 없습니다."));
            }
            return ResponseEntity.ok(ApiResponse.success(ws, "워크스페이스 조회 성공"));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        }
    }

    /**
     * GET /api/admin/cross-tenant/roles/menus/all?company_code=TEST02
     * 회사 메뉴 트리 (권한 설정용 원천).
     */
    @GetMapping("/menus/all")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getAllMenus(
            HttpServletRequest request,
            @RequestParam("company_code") String companyCode) {
        ResponseEntity<ApiResponse<List<Map<String, Object>>>> g = guardList(request);
        if (g != null) return g;

        try {
            List<Map<String, Object>> menus = executor.runInCompany(companyCode, () -> {
                Map<String, Object> p = new HashMap<>();
                p.put("company_code", companyCode);
                return roleService.getAllMenus(p);
            });
            return ResponseEntity.ok(ApiResponse.success(menus, "메뉴 목록 조회 성공"));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        }
    }

    // ── 멤버 토글 ───────────────────────────────────────────────

    /**
     * POST /api/admin/cross-tenant/roles/{id}/members/{userId}?company_code=TEST02
     */
    @PostMapping("/{id}/members/{userId}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> addSingleMember(
            HttpServletRequest request,
            @PathVariable String id,
            @PathVariable String userId,
            @RequestAttribute(value = "user_id", required = false) String writer,
            @RequestParam("company_code") String companyCode) {
        ResponseEntity<ApiResponse<Map<String, Object>>> g = guardMap(request);
        if (g != null) return g;

        try {
            Map<String, Object> result = executor.runInCompany(companyCode, () -> {
                boolean inserted = roleService.addSingleRoleMember(id, userId, writer);
                Map<String, Object> r = new HashMap<>();
                r.put("inserted", inserted);
                r.put("master_objid", id);
                r.put("user_id", userId);
                return r;
            });
            String msg = Boolean.TRUE.equals(result.get("inserted")) ? "멤버 추가 성공" : "이미 멤버입니다.";
            return ResponseEntity.ok(ApiResponse.success(result, msg));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        }
    }

    /**
     * DELETE /api/admin/cross-tenant/roles/{id}/members/{userId}?company_code=TEST02
     */
    @DeleteMapping("/{id}/members/{userId}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> removeSingleMember(
            HttpServletRequest request,
            @PathVariable String id,
            @PathVariable String userId,
            @RequestParam("company_code") String companyCode) {
        ResponseEntity<ApiResponse<Map<String, Object>>> g = guardMap(request);
        if (g != null) return g;

        try {
            Map<String, Object> result = executor.runInCompany(companyCode, () -> {
                boolean deleted = roleService.removeSingleRoleMember(id, userId);
                Map<String, Object> r = new HashMap<>();
                r.put("deleted", deleted);
                r.put("master_objid", id);
                r.put("user_id", userId);
                return r;
            });
            String msg = Boolean.TRUE.equals(result.get("deleted")) ? "멤버 제거 성공" : "멤버가 존재하지 않습니다.";
            return ResponseEntity.ok(ApiResponse.success(result, msg));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        }
    }

    // ── 메뉴 권한 토글 ──────────────────────────────────────────

    /**
     * PATCH /api/admin/cross-tenant/roles/{id}/menu-permissions/{menuObjid}
     * body: { company_code, create_yn?, read_yn?, update_yn?, delete_yn? }
     */
    @PatchMapping("/{id}/menu-permissions/{menuObjid}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> toggleMenuPermission(
            HttpServletRequest request,
            @PathVariable String id,
            @PathVariable String menuObjid,
            @RequestAttribute(value = "user_id", required = false) String writer,
            @RequestBody Map<String, Object> body) {
        ResponseEntity<ApiResponse<Map<String, Object>>> g = guardMap(request);
        if (g != null) return g;

        String targetCompany = (String) body.get("company_code");
        try {
            Map<String, Object> result = executor.runInCompany(targetCompany, () -> roleService.toggleMenuPermission(
                    id, menuObjid,
                    asYn(body.get("create_yn")),
                    asYn(body.get("read_yn")),
                    asYn(body.get("update_yn")),
                    asYn(body.get("delete_yn")),
                    writer));
            return ResponseEntity.ok(ApiResponse.success(result, "메뉴 권한 토글 성공"));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        }
    }

    // ── 가드 헬퍼 (응답 타입별로 3가지 — Map/Void/List) ────────

    private ResponseEntity<ApiResponse<Map<String, Object>>> guardMap(HttpServletRequest request) {
        try {
            CrossTenantContext.requireManagementHost(request);
        } catch (org.springframework.web.server.ResponseStatusException e) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error(e.getReason(), request.getRequestURI()));
        }
        if (!CrossTenantContext.isSuperAdmin(request)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("super_admin_required", request.getRequestURI()));
        }
        if (!CrossTenantContext.isMetaContext()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error("cross_tenant_requires_meta_context", request.getRequestURI()));
        }
        return null;
    }

    private ResponseEntity<ApiResponse<Void>> guardVoid(HttpServletRequest request) {
        try {
            CrossTenantContext.requireManagementHost(request);
        } catch (org.springframework.web.server.ResponseStatusException e) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error(e.getReason(), request.getRequestURI()));
        }
        if (!CrossTenantContext.isSuperAdmin(request)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("super_admin_required", request.getRequestURI()));
        }
        if (!CrossTenantContext.isMetaContext()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error("cross_tenant_requires_meta_context", request.getRequestURI()));
        }
        return null;
    }

    private ResponseEntity<ApiResponse<List<Map<String, Object>>>> guardList(HttpServletRequest request) {
        try {
            CrossTenantContext.requireManagementHost(request);
        } catch (org.springframework.web.server.ResponseStatusException e) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error(e.getReason(), request.getRequestURI()));
        }
        if (!CrossTenantContext.isSuperAdmin(request)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error("super_admin_required", request.getRequestURI()));
        }
        if (!CrossTenantContext.isMetaContext()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error("cross_tenant_requires_meta_context", request.getRequestURI()));
        }
        return null;
    }

    /** audit log details 기본 맵 생성 헬퍼. */
    private Map<String, Object> auditDetails(HttpServletRequest request, String roleId) {
        Map<String, Object> d = new HashMap<>();
        d.put("host", request.getHeader("Host"));
        if (roleId != null) d.put("role_id", roleId);
        return d;
    }

    /** "Y"/"N"/null 정규화 — RoleController 의 동일 헬퍼 미러. */
    private String asYn(Object raw) {
        if (raw == null) return null;
        if (raw instanceof Boolean b) return b ? "Y" : "N";
        String s = String.valueOf(raw).trim();
        if (s.isEmpty()) return null;
        if ("Y".equalsIgnoreCase(s) || "true".equalsIgnoreCase(s) || "1".equals(s)) return "Y";
        if ("N".equalsIgnoreCase(s) || "false".equalsIgnoreCase(s) || "0".equals(s)) return "N";
        return null;
    }
}
