package ai_summarizer

import (
	"context"
	"errors"
	"fmt"
	"net"
	"net/http"
	"strings"

	"github.com/minio/minio-go/v7"
)

// isMinioNotFound reports whether err indicates the object or bucket key is missing.
// The MinIO Go SDK often returns success from GetObject and surfaces NoSuchKey on Read.
func isMinioNotFound(err error) bool {
	if err == nil {
		return false
	}
	var minioErr minio.ErrorResponse
	if errors.As(err, &minioErr) {
		if minioErr.StatusCode == http.StatusNotFound {
			return true
		}
		switch strings.ToLower(minioErr.Code) {
		case "nosuchkey", "notfound":
			return true
		}
	}
	msg := strings.ToLower(err.Error())
	return strings.Contains(msg, "does not exist") ||
		strings.Contains(msg, "nosuchkey") ||
		strings.Contains(msg, "not found")
}

// isMinioConnectionError reports whether err indicates MinIO is unreachable.
func isMinioConnectionError(err error) bool {
	if err == nil {
		return false
	}
	if errors.Is(err, ErrMinIOUnavailable) {
		return true
	}
	if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
		return true
	}
	var netErr net.Error
	if errors.As(err, &netErr) && netErr.Timeout() {
		return true
	}
	var opErr *net.OpError
	if errors.As(err, &opErr) {
		return true
	}
	msg := strings.ToLower(err.Error())
	connectionHints := []string{
		"connection refused",
		"connection reset",
		"no such host",
		"dial tcp",
		"dial udp",
		"i/o timeout",
		"network is unreachable",
		"broken pipe",
		"tls handshake",
		"server gave http response to https client",
		"eof",
	}
	for _, hint := range connectionHints {
		if strings.Contains(msg, hint) {
			return true
		}
	}
	return false
}

// wrapMinIOError attaches ErrMinIOUnavailable when the root cause is connectivity.
func wrapMinIOError(err error) error {
	if err == nil || isMinioNotFound(err) {
		return err
	}
	if isMinioConnectionError(err) {
		return fmt.Errorf("%w: %v", ErrMinIOUnavailable, err)
	}
	return err
}
