package kz.konturai.parser.service;

import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.http.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * MinIO-based implementation of ImageStorageService.
 * 
 * Uploads images to MinIO storage and returns presigned URLs that are publicly
 * accessible for a limited time (7 days). These URLs can be used by Instagram
 * API.
 */
@Service
public class ImageStorageServiceImpl implements ImageStorageService {

    private static final Logger logger = LoggerFactory.getLogger(ImageStorageServiceImpl.class);
    private static final int PRESIGNED_URL_EXPIRY_DAYS = 7;

    private final MinioClient minioClient;
    private final String bucketName;

    public ImageStorageServiceImpl(
            @Value("${minio.endpoint}") String endpoint,
            @Value("${minio.access-key}") String accessKey,
            @Value("${minio.secret-key}") String secretKey,
            @Value("${minio.bucket-name}") String bucketName) {
        this.minioClient = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
        this.bucketName = bucketName;
    }

    @Override
    public String uploadImage(byte[] imageBytes, String filename) {
        try {
            // Generate a unique object name with timestamp and UUID to avoid collisions
            String objectName = generateObjectName(filename);

            // Determine content type based on filename extension
            String contentType = determineContentType(filename);

            // Upload the image to MinIO
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .stream(new ByteArrayInputStream(imageBytes), imageBytes.length, -1)
                    .contentType(contentType)
                    .build());

            logger.info("Successfully uploaded image to MinIO: {}", objectName);

            // Generate a presigned URL that's valid for 7 days
            String presignedUrl = minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.GET)
                            .bucket(bucketName)
                            .object(objectName)
                            .expiry(PRESIGNED_URL_EXPIRY_DAYS, TimeUnit.DAYS)
                            .build());

            logger.info("Generated presigned URL for image: {}", objectName);
            return presignedUrl;

        } catch (Exception e) {
            logger.error("Failed to upload image to MinIO and generate presigned URL: {}", e.getMessage(), e);
            throw new RuntimeException("Failed to upload image to storage: " + e.getMessage(), e);
        }
    }

    /**
     * Generates a unique object name for the image.
     * Format: instagram/{timestamp}-{uuid}-{original-filename}
     */
    private String generateObjectName(String filename) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String uuid = UUID.randomUUID().toString().substring(0, 8);
        String sanitizedFilename = filename != null ? filename.replaceAll("[^a-zA-Z0-9._-]", "_") : "image.jpg";
        return String.format("instagram/%s-%s-%s", timestamp, uuid, sanitizedFilename);
    }

    /**
     * Determines the content type based on the filename extension.
     */
    private String determineContentType(String filename) {
        if (filename == null) {
            return "image/jpeg";
        }

        String lowerFilename = filename.toLowerCase();
        if (lowerFilename.endsWith(".png")) {
            return "image/png";
        } else if (lowerFilename.endsWith(".gif")) {
            return "image/gif";
        } else if (lowerFilename.endsWith(".webp")) {
            return "image/webp";
        } else {
            return "image/jpeg"; // Default to JPEG
        }
    }
}
