package com.yaoai.storage.service.impl;

import com.yaoai.common.exception.BizException;
import com.yaoai.common.exception.ErrorCode;
import com.yaoai.storage.service.TosService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@Slf4j
@Service
@Profile("dev-h2")
@ConditionalOnProperty(name = "storage.local.enabled", havingValue = "true")
public class LocalTosServiceImpl implements TosService {

    private final Path rootDir;
    private final String publicBaseUrl;

    public LocalTosServiceImpl(
            @Value("${local-storage.base-dir:./.local-data/storage}") String baseDir,
            @Value("${local-storage.public-base-url:}") String publicBaseUrl,
            @Value("${server.port:8081}") String serverPort) {
        this.rootDir = Paths.get(baseDir).toAbsolutePath().normalize();
        this.publicBaseUrl = normalizePublicBaseUrl(publicBaseUrl, serverPort);
    }

    @Override
    public String upload(String key, InputStream content, long contentLength, String contentType) {
        Path target = resolveKey(key);
        try {
            Files.createDirectories(target.getParent());
            Files.copy(content, target, java.nio.file.StandardCopyOption.REPLACE_EXISTING);
            log.debug("Local storage upload success: key={}, path={}, size={}", key, target, contentLength);
            return key;
        } catch (IOException e) {
            log.error("Local storage upload failed: key={}", key, e);
            throw new BizException(ErrorCode.INTERNAL_ERROR, "本地文件写入失败: " + e.getMessage());
        }
    }

    @Override
    public void delete(String key) {
        try {
            Files.deleteIfExists(resolveKey(key));
        } catch (IOException e) {
            log.warn("Local storage delete failed: key={}, reason={}", key, e.getMessage());
        }
    }

    @Override
    public String presignedGetUrl(String key, long expiresSeconds) {
        return publicUrl(key);
    }

    @Override
    public String publicUrl(String key) {
        return publicBaseUrl + "/local-files?key=" + URLEncoder.encode(key, StandardCharsets.UTF_8);
    }

    @Override
    public String normalizePublicUrl(String url) {
        return url;
    }

    @Override
    public String readText(String key) {
        try {
            return Files.readString(resolveKey(key), StandardCharsets.UTF_8);
        } catch (IOException e) {
            log.error("Local storage readText failed: key={}", key, e);
            throw new BizException(ErrorCode.INTERNAL_ERROR, "读取文件内容失败: " + e.getMessage());
        }
    }

    @Override
    public InputStream getInputStream(String key) throws IOException {
        return Files.newInputStream(resolveKey(key));
    }

    private Path resolveKey(String key) {
        Path path = rootDir.resolve(key).normalize();
        if (!path.startsWith(rootDir)) {
            throw new BizException(ErrorCode.INVALID_PARAM, "非法文件路径");
        }
        return path;
    }

    private String normalizePublicBaseUrl(String configured, String serverPort) {
        String value = configured == null ? "" : configured.trim();
        if (value.isBlank()) {
            value = "http://127.0.0.1:" + (serverPort == null || serverPort.isBlank() ? "8081" : serverPort.trim());
        }
        while (value.endsWith("/")) {
            value = value.substring(0, value.length() - 1);
        }
        return value;
    }
}
