package services

import (
	"fmt"
	"log"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
)

type OSSService struct {
	Client     *oss.Client
	Bucket     *oss.Bucket
	BucketName string
	Endpoint   string
}

// Configuración del OSS
type OSSConfig struct {
	Endpoint        string
	AccessKeyID     string
	AccessKeySecret string
	BucketName      string
}

// Constructor del servicio OSS
func NewOSSService(cfg OSSConfig) (*OSSService, error) {
	client, err := oss.New(cfg.Endpoint, cfg.AccessKeyID, cfg.AccessKeySecret)
	if err != nil {
		return nil, fmt.Errorf("error creando cliente OSS: %w", err)
	}

	bucket, err := client.Bucket(cfg.BucketName)
	if err != nil {
		return nil, fmt.Errorf("error obteniendo bucket: %w", err)
	}

	return &OSSService{
		Client:     client,
		Bucket:     bucket,
		BucketName: cfg.BucketName,
		Endpoint:   cfg.Endpoint,
	}, nil
}

// Subir un archivo
func (s *OSSService) UploadFile(objectKey string, filePath string) error {
	err := s.Bucket.PutObjectFromFile(objectKey, filePath)
	if err != nil {
		return fmt.Errorf("error subiendo archivo: %w", err)
	}
	log.Printf("Archivo '%s' subido como '%s'", filePath, objectKey)
	return nil
}

// Listar archivos en el bucket
func (s *OSSService) ListFiles() ([]string, error) {
	objects, err := s.Bucket.ListObjects()
	if err != nil {
		return nil, fmt.Errorf("error listando archivos: %w", err)
	}

	var keys []string
	for _, obj := range objects.Objects {
		keys = append(keys, obj.Key)
	}
	return keys, nil
}

// NewOSSServiceFromDB construye OSSService desde el último registro activo
func NewOSSServiceFromDB() (*OSSService, error) {
	cfg, err := models.GetLastActiveOssApi()
	if err != nil {
		return nil, fmt.Errorf("error obteniendo configuración OSS activa: %w", err)
	}

	return NewOSSService(OSSConfig{
		Endpoint:        cfg.Endpoint,
		AccessKeyID:     cfg.AccessKeyID,
		AccessKeySecret: cfg.AccessKeySecret,
		BucketName:      cfg.BucketName,
	})
}

// Eliminar un archivo del bucket
func (s *OSSService) DeleteFile(objectKey string) error {
	err := s.Bucket.DeleteObject(objectKey)
	if err != nil {
		return fmt.Errorf("error eliminando archivo '%s' de OSS: %w", objectKey, err)
	}
	log.Printf("Archivo eliminado de OSS: %s", objectKey)
	return nil
}
