package com.erp.controller;

import com.erp.dto.ApiResponse;
import com.erp.service.FileService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;

@RestController
@RequestMapping("/api/files")
@RequiredArgsConstructor
@Slf4j
public class FileController {

    private final FileService fileService;

    // ── 목록 조회 ─────────────────────────────────────────────────────────────

    @GetMapping
    public ResponseEntity<ApiResponse<Map<String, Object>>> getFileList(
            @RequestAttribute("company_code") String companyCode,
            @RequestParam Map<String, Object> params) {
        params.put("company_code", companyCode);
        return ResponseEntity.ok(ApiResponse.success(fileService.getFileList(params)));
    }

    @GetMapping("/list")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getFileListAlias(
            @RequestAttribute("company_code") String companyCode,
            @RequestParam Map<String, Object> params) {
        params.put("company_code", companyCode);
        return ResponseEntity.ok(ApiResponse.success(fileService.getFileList(params)));
    }

    // ── 파일 정보 (public) ────────────────────────────────────────────────────

    @GetMapping("/info/{objid}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> getFileInfo(
            @PathVariable Long objid) {
        Map<String, Object> params = new HashMap<>();
        params.put("objid", objid);
        Map<String, Object> fileInfo = fileService.getFileInfoPublic(params);
        if (fileInfo == null) {
            return ResponseEntity.status(404).body(ApiResponse.error("파일을 찾을 수 없습니다."));
        }
        // 공개 응답: 메타데이터만 반환
        Map<String, Object> result = new HashMap<>();
        result.put("objid", fileInfo.get("objid"));
        result.put("real_file_name", fileInfo.get("real_file_name"));
        result.put("file_size", fileInfo.get("file_size"));
        result.put("file_ext", fileInfo.get("file_ext"));
        result.put("file_path", fileInfo.get("file_path"));
        result.put("regdate", fileInfo.get("regdate"));
        result.put("is_representative", fileInfo.get("is_representative"));
        return ResponseEntity.ok(ApiResponse.success(result));
    }

    // ── 타겟별 파일 목록 ─────────────────────────────────────────────────────

    @GetMapping("/linked/{tableName}/{recordId}")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getLinkedFiles(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable String tableName,
            @PathVariable String recordId) {
        Map<String, Object> params = new HashMap<>();
        params.put("company_code", companyCode);
        params.put("target_objid", tableName + ":" + recordId);
        return ResponseEntity.ok(ApiResponse.success(fileService.getFilesByTarget(params)));
    }

    // ── 업로드 ────────────────────────────────────────────────────────────────

    @PostMapping("/upload")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> uploadFiles(
            @RequestAttribute("company_code") String companyCode,
            @RequestAttribute(value = "user_id", required = false) String userId,
            @RequestParam("file") List<MultipartFile> files,
            @RequestParam Map<String, Object> params) {
        try {
            params.put("company_code", companyCode);
            params.put("user_id", userId != null ? userId : "system");
            List<Map<String, Object>> results = fileService.uploadFiles(files, params);
            return ResponseEntity.ok(ApiResponse.success(results, "파일 업로드 완료"));
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(ApiResponse.error(e.getMessage()));
        } catch (IOException e) {
            log.error("파일 업로드 실패", e);
            return ResponseEntity.status(500).body(ApiResponse.error("파일 업로드 중 오류가 발생했습니다."));
        }
    }

    // ── 다운로드 ─────────────────────────────────────────────────────────────

    @GetMapping("/download/{objid}")
    public ResponseEntity<Resource> downloadFile(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Long objid) {
        Map<String, Object> params = new HashMap<>();
        params.put("company_code", companyCode);
        params.put("objid", objid);
        Map<String, Object> fileInfo = fileService.getFileInfo(params);
        if (fileInfo == null) {
            return ResponseEntity.notFound().build();
        }
        try {
            Path filePath = fileService.resolveFilePath(fileInfo);
            if (!Files.exists(filePath)) {
                return ResponseEntity.notFound().build();
            }
            String realFileName = (String) fileInfo.getOrDefault("real_file_name", "download");
            String encodedName = URLEncoder.encode(realFileName, StandardCharsets.UTF_8)
                                           .replace("+", "%20");
            Resource resource = new FileSystemResource(filePath);
            String contentType = Files.probeContentType(filePath);
            if (contentType == null) contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;

            return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedName)
                .contentType(MediaType.parseMediaType(contentType))
                .body(resource);
        } catch (IOException e) {
            log.error("파일 다운로드 실패: objid={}", objid, e);
            return ResponseEntity.status(500).build();
        }
    }

    // ── 미리보기 (public) ─────────────────────────────────────────────────────

    @GetMapping("/preview/{objid}")
    public ResponseEntity<Resource> previewFile(@PathVariable Long objid) {
        Map<String, Object> params = new HashMap<>();
        params.put("objid", objid);
        Map<String, Object> fileInfo = fileService.getFileInfoPublic(params);
        if (fileInfo == null) return ResponseEntity.notFound().build();
        try {
            Path filePath = fileService.resolveFilePath(fileInfo);
            if (!Files.exists(filePath)) return ResponseEntity.notFound().build();
            String contentType = Files.probeContentType(filePath);
            if (contentType == null) contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
            Resource resource = new FileSystemResource(filePath);
            return ResponseEntity.ok()
                .header(HttpHeaders.CACHE_CONTROL, "max-age=3600")
                .contentType(MediaType.parseMediaType(contentType))
                .body(resource);
        } catch (IOException e) {
            log.error("파일 미리보기 실패: objid={}", objid, e);
            return ResponseEntity.status(500).build();
        }
    }

    // ── 삭제 (소프트 삭제) ────────────────────────────────────────────────────

    @DeleteMapping("/{objid}")
    public ResponseEntity<ApiResponse<Map<String, Object>>> deleteFile(
            @RequestAttribute("company_code") String companyCode,
            @PathVariable Long objid) {
        Map<String, Object> params = new HashMap<>();
        params.put("company_code", companyCode);
        params.put("objid", objid);
        fileService.deleteFile(params);
        return ResponseEntity.ok(ApiResponse.success(null, "파일이 삭제되었습니다."));
    }
}
