package com.pandoli365.bibimbap.controller;

import com.pandoli365.bibimbap.data.PostCategoryData;
import com.pandoli365.bibimbap.mapper.PostCategoriesMapper;
import com.pandoli365.bibimbap.security.CsrfTokens;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
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.RequestParam;

import java.util.LinkedHashMap;
import java.util.Map;

@Controller
public class PostAdminController {

    private final PostCategoriesMapper postCategoriesMapper;

    public PostAdminController(PostCategoriesMapper postCategoriesMapper) {
        this.postCategoriesMapper = postCategoriesMapper;
    }

    @GetMapping("/admin/post-categories")
    public String postCategoriesPage(HttpServletRequest request, Model model) {
        model.addAttribute("categories", postCategoriesMapper.listActive());
        model.addAttribute("csrfToken", CsrfTokens.getOrCreate(request.getSession()));
        return "admin-post-categories";
    }

    @PostMapping("/admin/post-categories")
    @Transactional
    public ResponseEntity<Map<String, Object>> createCategory(
            @RequestParam(name = "name", required = false) String name,
            @RequestParam(name = "slug", required = false) String slug,
            @RequestParam(name = "sortOrder", required = false) Integer sortOrder,
            HttpServletRequest request
    ) {
        if (!CsrfTokens.isValid(request)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(CsrfTokens.errorBody());
        }

        String normalizedName = trimToNull(name);
        String normalizedSlug = trimToNull(slug);
        if (normalizedName == null || normalizedName.length() > 80) {
            return response(HttpStatus.BAD_REQUEST, "카테고리 이름을 80자 이내로 입력해 주세요.");
        }
        if (normalizedSlug == null || normalizedSlug.length() > 80) {
            return response(HttpStatus.BAD_REQUEST, "슬러그를 80자 이내로 입력해 주세요.");
        }
        int order = sortOrder == null ? 0 : sortOrder;

        PostCategoryData category = new PostCategoryData();
        category.setName(normalizedName);
        category.setSlug(normalizedSlug);
        category.setSortOrder(order);
        category.setIsActive(true);

        try {
            postCategoriesMapper.insert(category);
        } catch (DuplicateKeyException e) {
            return response(HttpStatus.CONFLICT, "이미 사용 중인 슬러그입니다.");
        }

        Map<String, Object> body = new LinkedHashMap<>();
        body.put("status", 200);
        body.put("message", "카테고리를 등록했습니다.");
        body.put("categoryId", category.getId());
        return ResponseEntity.ok(body);
    }

    @PostMapping("/admin/post-categories/{id}")
    @Transactional
    public ResponseEntity<Map<String, Object>> updateCategory(
            @PathVariable("id") long id,
            @RequestParam(name = "name", required = false) String name,
            @RequestParam(name = "slug", required = false) String slug,
            @RequestParam(name = "sortOrder", required = false) Integer sortOrder,
            @RequestParam(name = "isActive", required = false) Boolean isActive,
            HttpServletRequest request
    ) {
        if (!CsrfTokens.isValid(request)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(CsrfTokens.errorBody());
        }

        PostCategoryData existing = postCategoriesMapper.getById(id);
        if (existing == null) {
            return response(HttpStatus.NOT_FOUND, "카테고리를 찾을 수 없습니다.");
        }

        String normalizedName = trimToNull(name);
        if (normalizedName != null) {
            if (normalizedName.length() > 80) {
                return response(HttpStatus.BAD_REQUEST, "카테고리 이름을 80자 이내로 입력해 주세요.");
            }
            existing.setName(normalizedName);
        }
        String normalizedSlug = trimToNull(slug);
        if (normalizedSlug != null) {
            if (normalizedSlug.length() > 80) {
                return response(HttpStatus.BAD_REQUEST, "슬러그를 80자 이내로 입력해 주세요.");
            }
            existing.setSlug(normalizedSlug);
        }
        if (sortOrder != null) {
            existing.setSortOrder(sortOrder);
        }
        if (isActive != null) {
            existing.setIsActive(isActive);
        }

        try {
            postCategoriesMapper.update(existing);
        } catch (DuplicateKeyException e) {
            return response(HttpStatus.CONFLICT, "이미 사용 중인 슬러그입니다.");
        }

        return response(HttpStatus.OK, "카테고리를 수정했습니다.");
    }

    @PostMapping("/admin/post-categories/{id}/delete")
    @Transactional
    public ResponseEntity<Map<String, Object>> deleteCategory(
            @PathVariable("id") long id,
            HttpServletRequest request
    ) {
        if (!CsrfTokens.isValid(request)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(CsrfTokens.errorBody());
        }

        PostCategoryData existing = postCategoriesMapper.getById(id);
        if (existing == null) {
            return response(HttpStatus.NOT_FOUND, "카테고리를 찾을 수 없습니다.");
        }
        if (postCategoriesMapper.countPostsByCategory(id) > 0) {
            return response(HttpStatus.CONFLICT,
                    "소속 PUBLISHED 포스트가 있어 삭제할 수 없습니다. 비활성화(is_active=false)를 권장합니다.");
        }

        postCategoriesMapper.delete(id);
        return response(HttpStatus.OK, "카테고리를 삭제했습니다.");
    }

    private String trimToNull(String value) {
        if (value == null) {
            return null;
        }
        String text = value.trim();
        return text.isBlank() ? null : text;
    }

    private ResponseEntity<Map<String, Object>> response(HttpStatus status, String message) {
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("status", status.value());
        body.put("message", message);
        return ResponseEntity.status(status).body(body);
    }
}
