package incheon.guide.web;

import incheon.com.cmm.ComDefaultVO;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 개발자 가이드 메인 컨트롤러
 */
@Controller
@SessionAttributes(types = ComDefaultVO.class)
@RequestMapping("/guide")
public class GuideController {

    /** Log Info */
    protected Log log = LogFactory.getLog(this.getClass());

    /**
     * @MethodDESC : 개발자 가이드 메인 페이지를 보여준다.
     */
    @GetMapping("/index")
    public String main(ModelMap model) {
        log.debug("개발자 가이드 메인 페이지 호출");

        // 가이드 카테고리 정보 설정
        model.addAttribute("pageTitle", "인천 공간정보 플랫폼 개발자 가이드");
        model.addAttribute("pageDescription", "화면개발, API, 컴포넌트 사용법을 안내합니다.");

        return "guide/index";
    }
    /**
     * @MethodDESC : 컴포넌트 가이드 목록을 반환한다.
     */
    @GetMapping("/component")
    public String componentList(ModelMap model) {
        log.debug("컴포넌트 가이드 목록 호출");
        return "guide/component/list";
    }

    /**
     * @MethodDESC : 특정 컴포넌트의 상세 정보를 반환한다.
     */
    @GetMapping("/component/{componentName}")
    public String componentDetail(@PathVariable("componentName") String componentName, ModelMap model) {
        log.debug("컴포넌트 상세 정보 호출: " + componentName);

        model.addAttribute("componentName", componentName);

        // 컴포넌트별 상세 JSP 파일 경로 반환
        return "guide/component/details/" + componentName;
    }

    /**
     * @MethodDESC : AJAX 팝업 데모 - 사용자 목록 페이지
     */
    @GetMapping("/popup/user/list")
    public String popupUserList(ModelMap model) {
        log.debug("AJAX 팝업 데모 - 사용자 목록 페이지 호출");

        // 샘플 사용자 데이터 생성
        java.util.List<java.util.Map<String, Object>> users = new java.util.ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            java.util.Map<String, Object> user = new java.util.HashMap<>();
            user.put("id", i);
            user.put("name", "사용자" + i);
            user.put("email", "user" + i + "@incheon.go.kr");
            user.put("department", i % 3 == 0 ? "정보통신과" : i % 2 == 0 ? "도시계획과" : "건설과");
            user.put("role", i <= 3 ? "관리자" : "일반사용자");
            users.add(user);
        }

        model.addAttribute("users", users);
        model.addAttribute("totalCount", users.size());

        return "guide/popup/user-list";
    }

    /**
     * @MethodDESC : 고급 설정 팝업 데모 - 사용자 폼 페이지
     */
    @GetMapping("/popup/user/form")
    public String popupUserForm(@PathVariable(value = "userId", required = false) String userId, ModelMap model) {
        log.debug("고급 설정 팝업 데모 - 사용자 폼 페이지 호출");

        // 기본 사용자 데이터 (편집용)
        java.util.Map<String, Object> user = new java.util.HashMap<>();
        user.put("id", "");
        user.put("name", "");
        user.put("email", "");
        user.put("department", "정보통신과");
        user.put("role", "일반사용자");
        user.put("isNew", true);

        model.addAttribute("user", user);

        return "guide/popup/user-form";
    }

    // ===== FETCH 데모용 API 엔드포인트들 =====

    /**
     * @MethodDESC : GET 요청 데모 - 사용자 정보 조회
     */
    @GetMapping("/api/demo/user/{userId}")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> getDemoUser(@PathVariable("userId") String userId) {
        log.debug("GET 데모 API 호출 - 사용자 ID: " + userId);

        try {
            // 응답 지연 시뮬레이션 (1-2초)
            Thread.sleep(1000 + (int)(Math.random() * 1000));

            Map<String, Object> user = new HashMap<>();
            user.put("id", userId);
            user.put("name", "홍길동" + userId);
            user.put("email", "hong" + userId + "@incheon.go.kr");
            user.put("department", "정보통신과");
            user.put("role", "개발자");
            user.put("phone", "032-440-" + String.format("%04d", Integer.parseInt(userId) + 1000));
            user.put("joinDate", "2024-01-15");
            user.put("status", "active");

            Map<String, Object> company = new HashMap<>();
            company.put("name", "인천광역시청");
            company.put("address", "인천광역시 남동구 정각로 29");
            user.put("company", company);

            return ResponseEntity.ok(user);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            Map<String, Object> error = new HashMap<>();
            error.put("error", "서버 내부 오류");
            error.put("message", "요청 처리 중 오류가 발생했습니다.");
            return ResponseEntity.status(500).body(error);
        }
    }

    /**
     * @MethodDESC : POST 요청 데모 - 사용자 등록
     */
    @PostMapping("/api/demo/users")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> createDemoUser(@RequestBody Map<String, Object> userData, HttpServletRequest request) {
        log.debug("POST 데모 API 호출 - 사용자 데이터: " + userData);

        try {
            // 응답 지연 시뮬레이션 (2-3초)
            Thread.sleep(2000 + (int)(Math.random() * 1000));

            // 입력 데이터 검증
            if (!userData.containsKey("name") || userData.get("name").toString().trim().isEmpty()) {
                Map<String, Object> error = new HashMap<>();
                error.put("error", "유효성 검사 실패");
                error.put("message", "사용자명은 필수 입력 항목입니다.");
                error.put("field", "name");
                return ResponseEntity.status(400).body(error);
            }

            // 새 사용자 ID 생성
            int newId = (int)(Math.random() * 1000) + 100;

            Map<String, Object> result = new HashMap<>();
            result.put("id", newId);
            result.put("name", userData.get("name"));
            result.put("email", userData.get("email"));
            result.put("phone", userData.get("phone"));
            result.put("department", "정보통신과");
            result.put("role", "일반사용자");
            result.put("status", "active");
            result.put("createdAt", new Date());
            result.put("message", "사용자가 성공적으로 등록되었습니다.");

            return ResponseEntity.ok(result);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            Map<String, Object> error = new HashMap<>();
            error.put("error", "서버 내부 오류");
            error.put("message", "사용자 등록 중 오류가 발생했습니다.");
            return ResponseEntity.status(500).body(error);
        }
    }

    /**
     * @MethodDESC : POST 요청 데모 - FormData 방식 게시글 등록
     */
    @PostMapping("/api/demo/posts")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> createDemoPost(
            @RequestParam("title") String title,
            @RequestParam("body") String body,
            @RequestParam("userId") String userId,
            HttpServletRequest request) {
        
        log.debug("FormData POST 데모 API 호출 - 제목: " + title + ", 사용자ID: " + userId);

        try {
            // 응답 지연 시뮬레이션 (1-2초)
            Thread.sleep(1000 + (int)(Math.random() * 1000));

            // 새 게시글 ID 생성
            int newId = (int)(Math.random() * 1000) + 1;

            Map<String, Object> result = new HashMap<>();
            result.put("id", newId);
            result.put("title", title);
            result.put("body", body);
            result.put("userId", userId);
            result.put("author", "홍길동" + userId);
            result.put("createdAt", new Date());
            result.put("status", "published");
            result.put("views", 0);
            result.put("message", "게시글이 성공적으로 등록되었습니다.");

            return ResponseEntity.ok(result);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            Map<String, Object> error = new HashMap<>();
            error.put("error", "서버 내부 오류");
            error.put("message", "게시글 등록 중 오류가 발생했습니다.");
            return ResponseEntity.status(500).body(error);
        }
    }

    /**
     * @MethodDESC : PUT 요청 데모 - 게시글 수정 (고급 설정)
     */
    @PutMapping("/api/demo/posts/{postId}")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> updateDemoPost(
            @PathVariable("postId") String postId,
            @RequestBody Map<String, Object> postData,
            @RequestHeader(value = "X-Custom-Header", required = false) String customHeader,
            @RequestHeader(value = "X-Request-ID", required = false) String requestId,
            HttpServletRequest request) {
        
        log.debug("PUT 데모 API 호출 - 게시글 ID: " + postId + ", 커스텀 헤더: " + customHeader + ", 요청 ID: " + requestId);

        try {
            // 응답 지연 시뮬레이션 (1-3초)
            Thread.sleep(1000 + (int)(Math.random() * 2000));

            // 권한 체크 시뮬레이션 (10% 확률로 권한 오류)
            if (Math.random() < 0.1) {
                Map<String, Object> error = new HashMap<>();
                error.put("error", "권한 없음");
                error.put("message", "이 게시글을 수정할 권한이 없습니다.");
                error.put("code", "PERMISSION_DENIED");
                return ResponseEntity.status(403).body(error);
            }

            // 인증 체크 시뮬레이션 (5% 확률로 인증 오류)
            if (Math.random() < 0.05) {
                Map<String, Object> error = new HashMap<>();
                error.put("error", "인증 필요");
                error.put("message", "로그인이 필요한 서비스입니다.");
                error.put("code", "AUTHENTICATION_REQUIRED");
                return ResponseEntity.status(401).body(error);
            }

            Map<String, Object> result = new HashMap<>();
            result.put("id", postId);
            result.put("title", postData.get("title"));
            result.put("body", postData.get("body"));
            result.put("userId", postData.get("userId"));
            result.put("updatedAt", new Date());
            result.put("version", (int)(Math.random() * 10) + 1);
            result.put("status", "updated");
            result.put("customHeader", customHeader);
            result.put("requestId", requestId);
            result.put("message", "게시글이 성공적으로 수정되었습니다.");

            return ResponseEntity.ok(result);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            Map<String, Object> error = new HashMap<>();
            error.put("error", "서버 내부 오류");
            error.put("message", "게시글 수정 중 오류가 발생했습니다.");
            return ResponseEntity.status(500).body(error);
        }
    }

    /**
     * @MethodDESC : 에러 테스트용 API - 다양한 HTTP 상태 코드 시뮬레이션
     */
    @GetMapping("/api/demo/error/{errorType}")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> simulateError(@PathVariable("errorType") String errorType) {
        log.debug("에러 시뮬레이션 API 호출 - 에러 타입: " + errorType);

        Map<String, Object> error = new HashMap<>();

        switch (errorType.toLowerCase()) {
            case "400":
                error.put("error", "잘못된 요청");
                error.put("message", "요청 파라미터가 올바르지 않습니다.");
                error.put("code", "BAD_REQUEST");
                return ResponseEntity.status(400).body(error);

            case "401":
                error.put("error", "인증 실패");
                error.put("message", "로그인이 필요합니다.");
                error.put("code", "UNAUTHORIZED");
                return ResponseEntity.status(401).body(error);

            case "403":
                error.put("error", "권한 없음");
                error.put("message", "접근 권한이 없습니다.");
                error.put("code", "FORBIDDEN");
                return ResponseEntity.status(403).body(error);

            case "404":
                error.put("error", "리소스 없음");
                error.put("message", "요청한 리소스를 찾을 수 없습니다.");
                error.put("code", "NOT_FOUND");
                return ResponseEntity.status(404).body(error);

            case "500":
                error.put("error", "서버 오류");
                error.put("message", "서버 내부 오류가 발생했습니다.");
                error.put("code", "INTERNAL_SERVER_ERROR");
                return ResponseEntity.status(500).body(error);

            case "timeout":
                try {
                    // 타임아웃 시뮬레이션 (35초 대기)
                    Thread.sleep(35000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                error.put("error", "타임아웃");
                error.put("message", "요청 처리 시간이 초과되었습니다.");
                return ResponseEntity.status(408).body(error);

            default:
                Map<String, Object> success = new HashMap<>();
                success.put("message", "정상 응답입니다.");
                success.put("errorType", errorType);
                success.put("timestamp", new Date());
                return ResponseEntity.ok(success);
        }
    }

    /**
     * @MethodDESC : 파일 업로드 데모 API
     */
    @PostMapping("/api/demo/upload")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> uploadDemoFile(
            @RequestParam("name") String name,
            @RequestParam(value = "file", required = false) MultipartFile file,
            HttpServletRequest request) {
        
        log.debug("파일 업로드 데모 API 호출 - 이름: " + name + ", 파일: " + (file != null ? file.getOriginalFilename() : "없음"));

        try {
            // 응답 지연 시뮬레이션 (2-4초)
            Thread.sleep(2000 + (int)(Math.random() * 2000));

            // 파일 정보 검증
            if (file != null && !file.isEmpty()) {
                // 파일 크기 체크 (10MB 제한 시뮬레이션)
                if (file.getSize() > 10 * 1024 * 1024) {
                    Map<String, Object> error = new HashMap<>();
                    error.put("error", "파일 크기 초과");
                    error.put("message", "파일 크기는 10MB를 초과할 수 없습니다.");
                    error.put("maxSize", "10MB");
                    error.put("currentSize", String.format("%.2fMB", file.getSize() / (1024.0 * 1024.0)));
                    return ResponseEntity.status(413).body(error); // Payload Too Large
                }

                // 파일 확장자 체크 시뮬레이션
                String originalFilename = file.getOriginalFilename();
                if (originalFilename != null) {
                    String extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase();
                    if (!Arrays.asList("jpg", "jpeg", "png", "gif", "pdf", "txt", "doc", "docx", "xls", "xlsx").contains(extension)) {
                        Map<String, Object> error = new HashMap<>();
                        error.put("error", "지원하지 않는 파일 형식");
                        error.put("message", "허용된 파일 형식: jpg, jpeg, png, gif, pdf, txt, doc, docx, xls, xlsx");
                        error.put("extension", extension);
                        return ResponseEntity.status(415).body(error); // Unsupported Media Type
                    }
                }
            }

            // 업로드 성공 응답 생성
            Map<String, Object> result = new HashMap<>();
            result.put("uploadId", "UPLOAD_" + System.currentTimeMillis());
            result.put("name", name);
            
            if (file != null && !file.isEmpty()) {
                Map<String, Object> fileInfo = new HashMap<>();
                fileInfo.put("originalName", file.getOriginalFilename());
                fileInfo.put("size", file.getSize());
                fileInfo.put("contentType", file.getContentType());
                fileInfo.put("savedName", "saved_" + System.currentTimeMillis() + "_" + file.getOriginalFilename());
                fileInfo.put("savedPath", "/uploads/demo/" + fileInfo.get("savedName"));
                result.put("file", fileInfo);
                result.put("message", "파일이 성공적으로 업로드되었습니다.");
            } else {
                result.put("file", null);
                result.put("message", "데이터가 성공적으로 전송되었습니다. (파일 없음)");
            }
            
            result.put("uploadedAt", new Date());
            result.put("status", "success");

            return ResponseEntity.ok(result);

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            Map<String, Object> error = new HashMap<>();
            error.put("error", "서버 내부 오류");
            error.put("message", "파일 업로드 중 오류가 발생했습니다.");
            return ResponseEntity.status(500).body(error);
        }
    }

    /**
     * @MethodDESC : 페이징 데모 페이지 (JSP에서 ui:pagination 태그 렌더링)
     */
    @GetMapping("/pagination-demo")
    public String paginationDemo(
            @RequestParam(defaultValue = "1") int page,
            ModelMap model) {

        // KRDS Default 페이징 정보 설정 (가상 데이터)
        PaginationInfo defaultPaginationInfo = new PaginationInfo();
        defaultPaginationInfo.setCurrentPageNo(page);
        defaultPaginationInfo.setRecordCountPerPage(20);
        defaultPaginationInfo.setPageSize(10);
        defaultPaginationInfo.setTotalRecordCount(1980); // 가상 총 데이터 수 (99페이지까지)

        model.addAttribute("defaultPaginationInfo", defaultPaginationInfo);

        return "guide/pagination-demo";
    }

    /**
     * @MethodDESC : ICAPP.common 가이드 페이지 (사용자/부서 선택 팝업 가이드)
     */
    @GetMapping("/icappCommonGuide.do")
    public String icappCommonGuide(ModelMap model) {
        log.debug("ICAPP.common 가이드 페이지 호출");
        return "guide/icappCommonGuide";
    }

    /**
     * @MethodDESC : RequestContext 가이드 페이지 (ThreadLocal 기반 전역 컨텍스트)
     */
    @GetMapping("/requestContextGuide.do")
    public String requestContextGuide(ModelMap model) {
        log.debug("RequestContext 가이드 페이지 호출");
        return "guide/requestContextGuide";
    }

    /**
     * @MethodDESC : SecurityUtil 권한 체크 가이드 페이지 (Spring Security 기반 권한 검증)
     */
    @GetMapping("/security-permission-guide.do")
    public String securityPermissionGuide(ModelMap model) {
        log.debug("SecurityUtil 권한 체크 가이드 페이지 호출");
        return "guide/security-permission-guide";
    }
}