package com.pandoli365.bibimbap.controller;

import com.pandoli365.bibimbap.data.RecruitPostData;
import com.pandoli365.bibimbap.mapper.RecruitPostsMapper;
import com.pandoli365.bibimbap.security.CsrfTokens;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
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;
import java.util.Set;

@Controller
public class RecruitController {

    private static final Set<String> ROLES = Set.of("기획", "아트", "프로그래머");
    private static final Set<String> PARTICIPATION_TYPES = Set.of("취미", "수익쉐어", "유급", "게임잼");
    private static final Set<String> PROJECT_STATUSES = Set.of("아이디어 단계", "프로토타입 개발 중", "데모 있음", "출시 준비 중");

    private final RecruitPostsMapper recruitPostsMapper;

    public RecruitController(RecruitPostsMapper recruitPostsMapper) {
        this.recruitPostsMapper = recruitPostsMapper;
    }

    @GetMapping("/recruit")
    public String recruitList(Model model) {
        model.addAttribute("recruitPosts", recruitPostsMapper.getVisibleRecruitPosts());
        return "recruit-list";
    }

    @GetMapping("/recruit/new")
    public String recruitForm(HttpSession session) {
        if (sessionUserId(session) == null) {
            return "redirect:/login";
        }
        return "recruit-form";
    }

    @PostMapping("/recruit/new")
    @Transactional
    public ResponseEntity<Map<String, Object>> createRecruitPost(
            @RequestParam(name = "projectName", required = false) String projectName,
            @RequestParam(name = "genre", required = false) String genre,
            @RequestParam(name = "summary", required = false) String summary,
            @RequestParam(name = "role", required = false) String role,
            @RequestParam(name = "status", required = false) String projectStatus,
            @RequestParam(name = "type", required = false) String participationType,
            @RequestParam(name = "period", required = false) String expectedPeriod,
            @RequestParam(name = "team", required = false) String teamMembers,
            @RequestParam(name = "contact", required = false) String contact,
            @RequestParam(name = "description", required = false) String description,
            HttpServletRequest request,
            HttpSession session
    ) {
        if (!CsrfTokens.isValid(request)) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(CsrfTokens.errorBody());
        }
        Long userId = sessionUserId(session);
        if (userId == null) {
            return response(HttpStatus.UNAUTHORIZED, "로그인이 필요합니다.");
        }

        String normalizedProjectName = trimToNull(projectName);
        String normalizedSummary = trimToNull(summary);
        String normalizedContact = trimToNull(contact);
        String normalizedRole = trimToNull(role);
        String normalizedProjectStatus = trimToNull(projectStatus);
        String normalizedParticipationType = trimToNull(participationType);

        if (normalizedProjectName == null || normalizedProjectName.length() > 80) {
            return response(HttpStatus.BAD_REQUEST, "프로젝트명을 80자 이내로 입력해 주세요.");
        }
        if (normalizedSummary == null || normalizedSummary.length() > 120) {
            return response(HttpStatus.BAD_REQUEST, "한 줄 소개를 120자 이내로 입력해 주세요.");
        }
        if (normalizedContact == null || normalizedContact.length() > 100) {
            return response(HttpStatus.BAD_REQUEST, "연락 방법을 100자 이내로 입력해 주세요.");
        }
        if (!ROLES.contains(normalizedRole)) {
            return response(HttpStatus.BAD_REQUEST, "모집 역할을 확인해 주세요.");
        }
        if (!PROJECT_STATUSES.contains(normalizedProjectStatus)) {
            return response(HttpStatus.BAD_REQUEST, "진행 상태를 확인해 주세요.");
        }
        if (!PARTICIPATION_TYPES.contains(normalizedParticipationType)) {
            return response(HttpStatus.BAD_REQUEST, "참여 방식을 확인해 주세요.");
        }

        String normalizedGenre = trimToEmpty(genre);
        String normalizedExpectedPeriod = trimToEmpty(expectedPeriod);
        String normalizedTeamMembers = trimToEmpty(teamMembers);
        String normalizedDescription = trimToEmpty(description);
        if (normalizedGenre.length() > 60) {
            return response(HttpStatus.BAD_REQUEST, "게임 장르는 60자 이내로 입력해 주세요.");
        }
        if (normalizedExpectedPeriod.length() > 40) {
            return response(HttpStatus.BAD_REQUEST, "예상 기간은 40자 이내로 입력해 주세요.");
        }
        if (normalizedTeamMembers.length() > 80) {
            return response(HttpStatus.BAD_REQUEST, "현재 팀 구성은 80자 이내로 입력해 주세요.");
        }
        if (normalizedDescription.length() > 1200) {
            return response(HttpStatus.BAD_REQUEST, "상세 설명은 1,200자 이내로 입력해 주세요.");
        }

        RecruitPostData post = new RecruitPostData();
        post.setUserId(userId);
        post.setProjectName(normalizedProjectName);
        post.setGenre(normalizedGenre);
        post.setSummary(normalizedSummary);
        post.setRole(normalizedRole);
        post.setProjectStatus(normalizedProjectStatus);
        post.setParticipationType(normalizedParticipationType);
        post.setExpectedPeriod(normalizedExpectedPeriod);
        post.setTeamMembers(normalizedTeamMembers);
        post.setContact(normalizedContact);
        post.setDescription(normalizedDescription);
        post.setReferenceUrl("");
        post.setVisible(true);
        post.setSortOrder(recruitPostsMapper.nextSortOrder());

        recruitPostsMapper.addRecruitPost(post);
        if (post.getId() == null) {
            return response(HttpStatus.INTERNAL_SERVER_ERROR, "모집글 등록 결과를 확인하지 못했습니다.");
        }

        Map<String, Object> body = new LinkedHashMap<>();
        body.put("status", 200);
        body.put("message", "모집글 등록이 완료되었습니다.");
        body.put("recruitPostId", post.getId());
        body.put("location", "/recruit/" + post.getId());
        return ResponseEntity.ok(body);
    }

    @GetMapping("/recruit/{id}")
    public String recruitDetail(@PathVariable("id") long id, Model model) {
        RecruitPostData post = recruitPostsMapper.getRecruitPost(id);
        if (post == null || Boolean.FALSE.equals(post.getVisible())) {
            return "redirect:/recruit";
        }
        model.addAttribute("post", post);
        return "recruit-detail";
    }

    private Long sessionUserId(HttpSession session) {
        if (session == null) {
            return null;
        }
        Object userId = session.getAttribute("userId");
        if (userId instanceof Number number) {
            return number.longValue();
        }
        if (userId instanceof String text) {
            try {
                return Long.parseLong(text);
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }

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

    private String trimToEmpty(String value) {
        String text = trimToNull(value);
        return text == 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);
    }
}
