package kr.co.accura.wbx.spring.file;

import kr.co.accura.wbx.spring.common.BusinessException;
import kr.co.accura.wbx.spring.config.WbxSpringProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;

/**
 * Google Cloud Storage 구현 (표준 템플릿)
 * <p>
 * ⚠️ 프로덕션 배포 시 아래 SDK 기반 구현으로 교체를 권장합니다:
 * <pre>
 * // build.gradle
 * implementation 'com.google.cloud:spring-cloud-gcp-starter-storage:5.9.0'
 *
 * // 교체 후: Storage.create() / readAllBytes() / delete() 사용
 * </pre>
 * <p>
 * 현재 구현은 GOOGLE_APPLICATION_CREDENTIALS 환경변수(서비스 계정 JSON)로
 * 인증된 환경에서 GCP JSON API를 직접 호출합니다.
 * <p>
 * 설정:
 * <pre>
 * wbx.spring.file.storage-type: gcp-storage
 * wbx.spring.file.gcp.bucket: ${GCP_STORAGE_BUCKET}
 * wbx.spring.file.gcp.project-id: ${GCP_PROJECT_ID}
 * </pre>
 */
@Slf4j
@Service
@ConditionalOnProperty(name = "wbx.spring.file.storage-type", havingValue = "gcp-storage")
public class GcpStorageService implements FileStorageService {

    private final WbxSpringProperties props;
    private final HttpClient httpClient;

    public GcpStorageService(WbxSpringProperties props) {
        this.props = props;
        this.httpClient = HttpClient.newHttpClient();
    }

    @Override
    public String upload(MultipartFile file, String category) {
        try {
            WbxSpringProperties.FileConfig.GcpConfig gcp = props.getFile().getGcp();
            String objectName = category + "/" + UUID.randomUUID() + getExtension(file.getOriginalFilename());

            String url = String.format(
                    "https://storage.googleapis.com/upload/storage/v1/b/%s/o?uploadType=media&name=%s",
                    gcp.getBucket(), objectName);

            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .header("Content-Type", file.getContentType())
                    .POST(HttpRequest.BodyPublishers.ofByteArray(file.getBytes()))
                    .build();

            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() >= 300) {
                throw new BusinessException("GCS upload failed: " + response.statusCode());
            }

            log.info("GCS uploaded: gs://{}/{}", gcp.getBucket(), objectName);
            return objectName;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            throw new BusinessException("GCS upload failed: " + e.getMessage());
        }
    }

    @Override
    public byte[] download(String fileKey) {
        try {
            WbxSpringProperties.FileConfig.GcpConfig gcp = props.getFile().getGcp();
            String url = String.format("https://storage.googleapis.com/storage/v1/b/%s/o/%s?alt=media",
                    gcp.getBucket(), fileKey);

            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .GET()
                    .build();

            HttpResponse<byte[]> response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray());
            if (response.statusCode() == 404) {
                throw new BusinessException("File not found: " + fileKey);
            }
            return response.body();
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            throw new BusinessException("GCS download failed: " + e.getMessage());
        }
    }

    @Override
    public void delete(String fileKey) {
        try {
            WbxSpringProperties.FileConfig.GcpConfig gcp = props.getFile().getGcp();
            String url = String.format("https://storage.googleapis.com/storage/v1/b/%s/o/%s",
                    gcp.getBucket(), fileKey);

            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(url))
                    .DELETE()
                    .build();
            httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            log.info("GCS deleted: {}", fileKey);
        } catch (Exception e) {
            log.warn("GCS delete failed: {}", e.getMessage());
        }
    }

    @Override
    public String getPresignedUrl(String fileKey, long expirySeconds) {
        WbxSpringProperties.FileConfig.GcpConfig gcp = props.getFile().getGcp();
        // Signed URL (간략 구현 — 프로덕션은 GCP SDK 권장)
        return String.format("https://storage.googleapis.com/%s/%s", gcp.getBucket(), fileKey);
    }

    private String getExtension(String filename) {
        if (filename == null) return "";
        int dot = filename.lastIndexOf('.');
        return dot > 0 ? "." + filename.substring(dot + 1).toLowerCase() : "";
    }
}
