package com.flowable.devops.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.flowable.devops.entity.NodeType;
import com.flowable.devops.service.NodeTypeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;

/**
 * 节点类型REST API控制器
 * 
 * 提供节点类型管理的HTTP API接口
 */
@Slf4j
@RestController
@RequestMapping("/api/node-types")
@CrossOrigin(origins = "*")
public class NodeTypeController {
    
    @Autowired
    private NodeTypeService nodeTypeService;
    
    /**
     * 获取所有节点类型
     */
    @GetMapping
    public Mono<ResponseEntity<List<NodeType>>> getAllNodeTypes() {
        log.info("获取所有节点类型");
        
        return Mono.fromCallable(() -> nodeTypeService.getAllNodeTypes())
                .map(nodeTypes -> {
                    log.info("返回 {} 个节点类型", nodeTypes.size());
                    return ResponseEntity.ok(nodeTypes);
                })
                .onErrorResume(e -> {
                    log.error("获取节点类型列表失败", e);
                    return Mono.just(ResponseEntity.internalServerError().build());
                });
    }
    
    /**
     * 根据分类获取节点类型
     */
    @GetMapping("/category/{category}")
    public Mono<ResponseEntity<List<NodeType>>> getNodeTypesByCategory(@PathVariable String category) {
        log.info("获取分类节点类型: {}", category);
        
        return Mono.fromCallable(() -> nodeTypeService.getNodeTypesByCategory(category))
                .map(nodeTypes -> {
                    log.info("分类 {} 返回 {} 个节点类型", category, nodeTypes.size());
                    return ResponseEntity.ok(nodeTypes);
                })
                .onErrorResume(e -> {
                    log.error("获取分类节点类型失败: {}", category, e);
                    return Mono.just(ResponseEntity.internalServerError().build());
                });
    }
    
    /**
     * 根据ID获取节点类型
     */
    @GetMapping("/{id}")
    public Mono<ResponseEntity<NodeType>> getNodeType(@PathVariable String id) {
        log.info("获取节点类型: {}", id);
        
        return Mono.fromCallable(() -> nodeTypeService.getNodeType(id))
                .map(ResponseEntity::ok)
                .onErrorResume(e -> {
                    log.error("获取节点类型失败: {}", id, e);
                    return Mono.just(ResponseEntity.notFound().build());
                });
    }
    
    /**
     * 创建节点类型
     */
    @PostMapping
    public Mono<ResponseEntity<NodeType>> createNodeType(@Valid @RequestBody NodeType nodeType) {
        log.info("创建节点类型: {}", nodeType.getId());
        
        return Mono.fromCallable(() -> nodeTypeService.createNodeType(nodeType))
                .map(created -> {
                    log.info("节点类型创建成功: {}", created.getId());
                    return ResponseEntity.ok(created);
                })
                .onErrorResume(e -> {
                    log.error("创建节点类型失败: {}", nodeType.getId(), e);
                    return Mono.just(ResponseEntity.badRequest().build());
                });
    }
    
    /**
     * 更新节点类型
     */
    @PutMapping("/{id}")
    public Mono<ResponseEntity<NodeType>> updateNodeType(
            @PathVariable String id,
            @Valid @RequestBody NodeType nodeType) {
        log.info("更新节点类型: {}", id);
        
        return Mono.fromCallable(() -> nodeTypeService.updateNodeType(id, nodeType))
                .map(updated -> {
                    log.info("节点类型更新成功: {}", id);
                    return ResponseEntity.ok(updated);
                })
                .onErrorResume(e -> {
                    log.error("更新节点类型失败: {}", id, e);
                    return Mono.just(ResponseEntity.badRequest().build());
                });
    }
    
    /**
     * 删除节点类型
     */
    @DeleteMapping("/{id}")
    public Mono<ResponseEntity<Void>> deleteNodeType(@PathVariable String id) {
        log.info("删除节点类型: {}", id);
        
        return Mono.fromRunnable(() -> nodeTypeService.deleteNodeType(id))
                .then(Mono.fromCallable(() -> {
                    log.info("节点类型删除成功: {}", id);
                    return ResponseEntity.ok().<Void>build();
                }))
                .onErrorResume(e -> {
                    log.error("删除节点类型失败: {}", id, e);
                    return Mono.just(ResponseEntity.badRequest().build());
                });
    }
    
    /**
     * 获取节点类型分类列表
     */
    @GetMapping("/categories")
    public Mono<ResponseEntity<List<String>>> getCategories() {
        log.info("获取节点类型分类列表");
        
        return Mono.fromCallable(() -> nodeTypeService.getCategories())
                .map(categories -> {
                    log.info("返回 {} 个分类", categories.size());
                    return ResponseEntity.ok(categories);
                })
                .onErrorResume(e -> {
                    log.error("获取分类列表失败", e);
                    return Mono.just(ResponseEntity.internalServerError().build());
                });
    }
    
    /**
     * 获取节点类型输出模式
     */
    @GetMapping("/{id}/output-schema")
    public Mono<ResponseEntity<JsonNode>> getOutputSchema(@PathVariable String id) {
        log.info("获取节点类型输出模式: {}", id);
        
        return Mono.fromCallable(() -> nodeTypeService.getOutputSchema(id))
                .map(schema -> {
                    if (schema != null) {
                        return ResponseEntity.ok(schema);
                    } else {
                        return ResponseEntity.<JsonNode>ok(null);
                    }
                })
                .onErrorResume(e -> {
                    log.error("获取输出模式失败: {}", id, e);
                    return Mono.just(ResponseEntity.notFound().build());
                });
    }
    
    /**
     * 更新节点类型输出模式
     */
    @PutMapping("/{id}/output-schema")
    public Mono<ResponseEntity<NodeType>> updateOutputSchema(
            @PathVariable String id,
            @RequestBody JsonNode outputSchema) {
        log.info("更新节点类型输出模式: {}", id);
        
        return Mono.fromCallable(() -> nodeTypeService.updateOutputSchema(id, outputSchema))
                .map(updated -> {
                    log.info("输出模式更新成功: {}", id);
                    return ResponseEntity.ok(updated);
                })
                .onErrorResume(e -> {
                    log.error("更新输出模式失败: {}", id, e);
                    return Mono.just(ResponseEntity.badRequest().build());
                });
    }
    
    /**
     * 启用/禁用节点类型
     */
    @PostMapping("/{id}/toggle")
    public Mono<ResponseEntity<NodeType>> toggleEnabled(
            @PathVariable String id,
            @RequestBody Map<String, Boolean> request) {
        boolean enabled = request.getOrDefault("enabled", true);
        log.info("{}节点类型: {}", enabled ? "启用" : "禁用", id);
        
        return Mono.fromCallable(() -> nodeTypeService.toggleEnabled(id, enabled))
                .map(updated -> {
                    log.info("节点类型状态更新成功: {} -> {}", id, enabled);
                    return ResponseEntity.ok(updated);
                })
                .onErrorResume(e -> {
                    log.error("更新节点类型状态失败: {}", id, e);
                    return Mono.just(ResponseEntity.badRequest().build());
                });
    }
    
    /**
     * 刷新节点类型注册表
     */
    @PostMapping("/refresh-registry")
    public Mono<ResponseEntity<Map<String, String>>> refreshRegistry() {
        log.info("刷新节点类型注册表");
        
        return Mono.fromRunnable(() -> nodeTypeService.refreshRegistry())
                .then(Mono.fromCallable(() -> {
                    log.info("节点类型注册表刷新完成");
                    return ResponseEntity.ok(Map.of(
                            "status", "success",
                            "message", "节点类型注册表刷新完成",
                            "timestamp", String.valueOf(System.currentTimeMillis())
                    ));
                }))
                .onErrorResume(e -> {
                    log.error("刷新节点类型注册表失败", e);
                    return Mono.just(ResponseEntity.internalServerError().build());
                });
    }
    
    /**
     * 获取节点类型统计信息
     */
    @GetMapping("/statistics")
    public Mono<ResponseEntity<NodeTypeService.NodeTypeStatistics>> getStatistics() {
        log.info("获取节点类型统计信息");
        
        return Mono.fromCallable(() -> nodeTypeService.getStatistics())
                .map(stats -> {
                    log.info("返回统计信息: 总计 {}, 启用 {}, 禁用 {}", 
                            stats.getTotalCount(), stats.getEnabledCount(), stats.getDisabledCount());
                    return ResponseEntity.ok(stats);
                })
                .onErrorResume(e -> {
                    log.error("获取统计信息失败", e);
                    return Mono.just(ResponseEntity.internalServerError().build());
                });
    }
    
    /**
     * 健康检查接口
     */
    @GetMapping("/health")
    public Mono<ResponseEntity<Map<String, String>>> health() {
        return Mono.just(ResponseEntity.ok(Map.of(
                "status", "UP",
                "service", "node-type-service",
                "timestamp", String.valueOf(System.currentTimeMillis())
        )));
    }
}