package com.snack.server.common.storage;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.io.File;
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;

/**
 * 本地文件存储实现
 *
 * 文件保存路径：./uploads/{bizType}/{yyyy-MM}/{uuid}.{ext}
 * 访问路径：http://host:port/uploads/...
 */
@Slf4j
@Component
@ConditionalOnProperty(name = "snack.storage.type", havingValue = "local", matchIfMissing = true)
public class LocalFileStorage implements FileStorage {

    /** 上传根目录（相对当前进程） */
    @Value("${snack.upload.path:./uploads/}")
    private String uploadPath;

    /** 访问域名前缀 */
    @Value("${snack.upload.domain:http://localhost:8080/uploads/}")
    private String domain;

    private static final long MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
    private static final DateTimeFormatter DATE_DIR_FMT = DateTimeFormatter.ofPattern("yyyy-MM");

    @Override
    public FileStoreResult store(byte[] bytes, String originalName, String bizType) {
        if (bytes == null || bytes.length == 0) {
            throw new IllegalArgumentException("文件内容为空");
        }
        if (bytes.length > MAX_FILE_SIZE) {
            throw new IllegalArgumentException("文件大小不能超过 " + (MAX_FILE_SIZE / 1024 / 1024) + "MB");
        }
        String ext = StrUtil.subAfter(originalName, '.', true);
        if (StrUtil.isBlank(ext)) {
            ext = "bin";
        }
        ext = ext.toLowerCase();

        // 按 "bizType/yyyy-MM/" 分目录
        String biz = StrUtil.blankToDefault(bizType, "common");
        String monthDir = LocalDate.now().format(DATE_DIR_FMT);
        String relativeDir = biz + "/" + monthDir;
        Path dir = Paths.get(uploadPath, relativeDir).toAbsolutePath();
        try {
            Files.createDirectories(dir);
        } catch (IOException e) {
            log.error("创建上传目录失败 {}", dir, e);
            throw new RuntimeException("创建上传目录失败", e);
        }

        // UUID 文件名
        String storedName = IdUtil.fastSimpleUUID() + "." + ext;
        File target = new File(dir.toFile(), storedName);
        try {
            FileUtil.writeBytes(bytes, target);
        } catch (Exception e) {
            log.error("写入文件失败 {}", target.getAbsolutePath(), e);
            throw new RuntimeException("写入文件失败", e);
        }

        FileStoreResult result = new FileStoreResult();
        String relativePath = relativeDir + "/" + storedName;
        result.setPath(relativePath);
        result.setStoredName(storedName);
        result.setUrl(domain + relativePath);
        result.setName(originalName);
        result.setSize((long) bytes.length);
        result.setContentType(detectContentType(ext));
        log.info("文件已存储 path={} size={}B", relativePath, bytes.length);
        return result;
    }

    @Override
    public void delete(String path) {
        if (StrUtil.isBlank(path)) return;
        File f = new File(uploadPath, path);
        if (f.exists() && f.delete()) {
            log.info("删除文件 {}", path);
        }
    }

    @Override
    public String getAccessUrl(String path) {
        if (StrUtil.isBlank(path)) return null;
        if (path.startsWith("http://") || path.startsWith("https://")) {
            return path; // 已经是完整 URL
        }
        return domain + path;
    }

    /**
     * 从完整 URL 反查 path
     */
    public String parsePathFromUrl(String url) {
        if (StrUtil.isBlank(url)) return null;
        if (!url.startsWith("http://") && !url.startsWith("https://")) {
            return url; // 已经是 path
        }
        int idx = url.indexOf("/uploads/");
        if (idx == -1) return null;
        return url.substring(idx + "/uploads/".length());
    }

    private String detectContentType(String ext) {
        return switch (ext) {
            case "jpg", "jpeg" -> "image/jpeg";
            case "png"          -> "image/png";
            case "gif"          -> "image/gif";
            case "webp"         -> "image/webp";
            case "pdf"          -> "application/pdf";
            case "mp4"          -> "video/mp4";
            default             -> "application/octet-stream";
        };
    }
}
