package com.zioinfo.mall.uiws.schedule.service;

import com.zioinfo.mall.uiws.common.UiwsApiException;
import com.zioinfo.mall.uiws.common.UiwsErrorCode;
import com.zioinfo.mall.uiws.config.UiwsProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * 첨부파일 로컬 스토리지(UIWS 이식). 경로순회 방지(파일명 정규화 + UUID 저장명), 일자별 디렉터리 분리.
 * 저장 결과로 상대경로(file_path)를 반환한다.
 */
@Service
@RequiredArgsConstructor
public class FileStorageService {

    private static final DateTimeFormatter DAY = DateTimeFormatter.ofPattern("yyyy/MM/dd");

    private final UiwsProperties properties;

    public record StoredFile(String originalName, String relativePath, long size) {
    }

    public StoredFile store(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new UiwsApiException(UiwsErrorCode.FILE_EMPTY);
        }
        String original = StringUtils.cleanPath(
                file.getOriginalFilename() != null ? file.getOriginalFilename() : "file");
        original = original.replace("\\", "_").replace("/", "_");
        if (original.contains("..")) {
            original = original.replace("..", "_");
        }
        String ext = "";
        int dot = original.lastIndexOf('.');
        if (dot >= 0) {
            ext = original.substring(dot);
        }
        String subDir = LocalDate.now().format(DAY);
        String storedName = UUID.randomUUID().toString().replace("-", "") + ext;
        String relativePath = subDir + "/" + storedName;

        try {
            Path root = Paths.get(properties.getUpload().getUploadDir()).toAbsolutePath().normalize();
            Path target = root.resolve(relativePath).normalize();
            if (!target.startsWith(root)) {
                throw new UiwsApiException(UiwsErrorCode.FILE_STORAGE_ERROR, "허용되지 않은 저장 경로입니다.");
            }
            Files.createDirectories(target.getParent());
            file.transferTo(target.toFile());
        } catch (IOException e) {
            throw new UiwsApiException(UiwsErrorCode.FILE_STORAGE_ERROR);
        }
        return new StoredFile(original, relativePath, file.getSize());
    }

    public Path resolve(String relativePath) {
        if (relativePath == null || relativePath.isBlank()) {
            throw new UiwsApiException(UiwsErrorCode.ATTACH_NOT_FOUND);
        }
        Path root = Paths.get(properties.getUpload().getUploadDir()).toAbsolutePath().normalize();
        Path target = root.resolve(relativePath).normalize();
        if (!target.startsWith(root)) {
            throw new UiwsApiException(UiwsErrorCode.FILE_STORAGE_ERROR, "허용되지 않은 경로입니다.");
        }
        return target;
    }

    public void delete(String relativePath) {
        if (relativePath == null || relativePath.isBlank()) {
            return;
        }
        try {
            Path root = Paths.get(properties.getUpload().getUploadDir()).toAbsolutePath().normalize();
            Path target = root.resolve(relativePath).normalize();
            if (target.startsWith(root)) {
                Files.deleteIfExists(target);
            }
        } catch (IOException ignore) {
            // 물리파일 삭제 실패는 무시(메타 일관성 우선)
        }
    }
}
