package com.erp.controller;

import com.erp.dto.ApiResponse;
import com.erp.service.WebTypeStandardService;
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.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 웹타입 표준 관리 컨트롤러 (시스템 전역 테이블 — company_code 없음)
 *
 * GET    /api/admin/web-types                  - 목록 조회 (?active&category&search)
 * GET    /api/admin/web-types/categories       - 카테고리 목록
 * GET    /api/admin/web-types/{webType}        - 단건 조회
 * POST   /api/admin/web-types                  - 생성
 * PUT    /api/admin/web-types/{webType}        - 수정
 * DELETE /api/admin/web-types/{webType}        - 삭제
 * PUT    /api/admin/web-types/sort-order/bulk  - 정렬 순서 일괄 업데이트
 */
@RestController
@RequestMapping("/api/admin/web-types")
@RequiredArgsConstructor
@Slf4j
public class WebTypeStandardController {

    private final WebTypeStandardService service;

    private static final List<String> UPDATABLE_FIELDS = Arrays.asList(
            "type_name", "type_name_eng", "description", "category",
            "component_name", "config_panel", "default_config", "validation_rules",
            "default_style", "input_properties", "sort_order", "is_active"
    );

    @GetMapping
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getWebTypes(
            @RequestParam(required = false) String active,
            @RequestParam(required = false) String category,
            @RequestParam(required = false) String search) {
        try {
            Map<String, Object> params = new HashMap<>();
            if (active   != null) params.put("active",   active);
            if (category != null) params.put("category", category);
            if (search   != null) params.put("search",   search);
            return ResponseEntity.ok(ApiResponse.success(service.getWebTypes(params),
                    "웹타입 목록을 성공적으로 조회했습니다."));
        } catch (Exception e) {
            log.error("웹타입 목록 조회 오류", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("웹타입 목록 조회 중 오류가 발생했습니다."));
        }
    }

    @GetMapping("/categories")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getWebTypeCategories() {
        try {
            return ResponseEntity.ok(ApiResponse.success(service.getWebTypeCategories(),
                    "웹타입 카테고리 목록을 성공적으로 조회했습니다."));
        } catch (Exception e) {
            log.error("웹타입 카테고리 조회 오류", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("카테고리 조회 중 오류가 발생했습니다."));
        }
    }

    @GetMapping("/{webType}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getWebType(
            @PathVariable String webType) {
        try {
            Map<String, Object> result = service.getWebType(webType);
            if (result == null) {
                return ResponseEntity.status(404)
                        .body(ApiResponse.error("해당 웹타입을 찾을 수 없습니다."));
            }
            return ResponseEntity.ok(ApiResponse.success(result, "웹타입 정보를 성공적으로 조회했습니다."));
        } catch (Exception e) {
            log.error("웹타입 상세 조회 오류: webType={}", webType, e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("웹타입 조회 중 오류가 발생했습니다."));
        }
    }

    @PostMapping
    public ResponseEntity<ApiResponse<Map<String, Object>>> createWebType(
            @RequestBody Map<String, Object> body,
            @RequestAttribute("user_id") String userId) {
        if (body.get("web_type") == null && body.get("web_type") != null) {
            body.put("web_type", body.get("web_type"));
        }
        if (body.get("type_name") == null && body.get("type_name") != null) {
            body.put("type_name", body.get("type_name"));
        }
        if (body.get("web_type") == null || body.get("type_name") == null) {
            return ResponseEntity.status(400)
                    .body(ApiResponse.error("웹타입 코드와 이름은 필수입니다."));
        }
        normalizeSnakeToCamel(body);
        body.put("created_by", userId);
        body.put("updated_by", userId);
        try {
            Map<String, Object> result = service.createWebType(body);
            return ResponseEntity.status(HttpStatus.CREATED)
                    .body(ApiResponse.success(result, "웹타입이 성공적으로 생성되었습니다."));
        } catch (IllegalStateException e) {
            if ("DUPLICATE".equals(e.getMessage())) {
                return ResponseEntity.status(409)
                        .body(ApiResponse.error("이미 존재하는 웹타입 코드입니다."));
            }
            log.error("웹타입 생성 오류", e);
            return ResponseEntity.status(500).body(ApiResponse.error("웹타입 생성 중 오류가 발생했습니다."));
        } catch (Exception e) {
            log.error("웹타입 생성 오류", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("웹타입 생성 중 오류가 발생했습니다."));
        }
    }

    @PutMapping("/{webType}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> updateWebType(
            @PathVariable String webType,
            @RequestBody Map<String, Object> body,
            @RequestAttribute("user_id") String userId) {
        normalizeSnakeToCamel(body);
        boolean hasUpdates = UPDATABLE_FIELDS.stream().anyMatch(f -> body.get(f) != null);
        if (!hasUpdates) {
            return ResponseEntity.status(400).body(ApiResponse.error("수정할 내용이 없습니다."));
        }
        body.put("web_type",   webType);
        body.put("updated_by", userId);
        try {
            Map<String, Object> result = service.updateWebType(body);
            if (result == null) {
                return ResponseEntity.status(404)
                        .body(ApiResponse.error("해당 웹타입을 찾을 수 없습니다."));
            }
            return ResponseEntity.ok(ApiResponse.success(result, "웹타입이 성공적으로 수정되었습니다."));
        } catch (Exception e) {
            log.error("웹타입 수정 오류: webType={}", webType, e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("웹타입 수정 중 오류가 발생했습니다."));
        }
    }

    @DeleteMapping("/{webType}")
    public ResponseEntity<ApiResponse<Void>> deleteWebType(@PathVariable String webType) {
        try {
            boolean deleted = service.deleteWebType(webType);
            if (!deleted) {
                return ResponseEntity.status(404)
                        .body(ApiResponse.error("해당 웹타입을 찾을 수 없습니다."));
            }
            return ResponseEntity.ok(ApiResponse.success(null, "웹타입이 성공적으로 삭제되었습니다."));
        } catch (Exception e) {
            log.error("웹타입 삭제 오류: webType={}", webType, e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("웹타입 삭제 중 오류가 발생했습니다."));
        }
    }

    @PutMapping("/sort-order/bulk")
    public ResponseEntity<ApiResponse<Void>> updateWebTypeSortOrder(
            @RequestBody Map<String, Object> body,
            @RequestAttribute("user_id") String userId) {
        Object webTypes = body.get("web_types");
        if (!(webTypes instanceof List)) {
            return ResponseEntity.status(400)
                    .body(ApiResponse.error("유효하지 않은 데이터 형식입니다."));
        }
        body.put("user_id", userId);
        try {
            service.updateWebTypeSortOrder(body);
            return ResponseEntity.ok(ApiResponse.success(null,
                    "웹타입 정렬 순서가 성공적으로 업데이트되었습니다."));
        } catch (Exception e) {
            log.error("웹타입 정렬 순서 업데이트 오류", e);
            return ResponseEntity.status(500)
                    .body(ApiResponse.error("정렬 순서 업데이트 중 오류가 발생했습니다."));
        }
    }

    /**
     * Node 요청 바디(snake_case) → Spring params(camelCase) 변환
     * 프론트엔드가 snake_case로 보내는 경우를 대비해 호환 처리
     */
    private void normalizeSnakeToCamel(Map<String, Object> body) {
        mapField(body, "web_type",         "web_type");
        mapField(body, "type_name",        "type_name");
        mapField(body, "type_name_eng",    "type_name_eng");
        mapField(body, "component_name",   "component_name");
        mapField(body, "config_panel",     "config_panel");
        mapField(body, "default_config",   "default_config");
        mapField(body, "validation_rules", "validation_rules");
        mapField(body, "default_style",    "default_style");
        mapField(body, "input_properties", "input_properties");
        mapField(body, "sort_order",       "sort_order");
        mapField(body, "is_active",        "is_active");
    }

    private void mapField(Map<String, Object> body, String snakeKey, String camelKey) {
        if (body.get(camelKey) == null && body.get(snakeKey) != null) {
            body.put(camelKey, body.get(snakeKey));
        }
    }
}
