package drive

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/ultisuite/ulti-backend/internal/driveroot"
	"github.com/ultisuite/ulti-backend/internal/nextcloud"
)

func mountOAuthAccessToken(configEnc []byte) string {
	if len(configEnc) == 0 {
		return ""
	}
	var cfg map[string]any
	if err := json.Unmarshal(configEnc, &cfg); err != nil {
		return ""
	}
	if raw, ok := cfg["token"].(string); ok {
		return nextcloud.ParseOAuthAccessToken(raw)
	}
	return ""
}

// ResolveMountExternalURL returns the provider web URL for a file on an external mount.
func (s *Service) ResolveMountExternalURL(ctx context.Context, ncUserID, mountID, platformUserID, logicalPath string) (string, error) {
	store := s.ensureStore()
	if store == nil {
		return "", fmt.Errorf("store not configured")
	}
	mount, err := store.GetMount(ctx, mountID)
	if err != nil {
		return "", err
	}
	if mount.OwnerUserID == nil || *mount.OwnerUserID != platformUserID {
		return "", ErrForbidden
	}
	logicalPath = nextcloud.NormalizeClientPath(logicalPath)
	if logicalPath == "/" {
		return "", ErrInvalid
	}

	file, err := s.StatFileAtRoot(ctx, ncUserID, driveroot.Mount(mountID, logicalPath))
	if err != nil {
		return "", err
	}
	if file.ExternalURL != "" {
		return file.ExternalURL, nil
	}
	if !file.OpenExternally {
		return "", ErrInvalid
	}

	configEnc, err := store.GetMountConfig(ctx, mountID)
	if err != nil {
		return "", err
	}
	accessToken := mountOAuthAccessToken(configEnc)
	if accessToken == "" {
		return "", fmt.Errorf("mount oauth token not available")
	}

	resolver := &nextcloud.MountCloudResolver{}
	backend := driveroot.NormalizeMountBackend(mount.BackendType)
	switch backend {
	case "google":
		if id := providerIDFromETag(file.ETag); id != "" {
			link, err := resolver.GoogleDriveWebViewLink(ctx, accessToken, id)
			if err == nil && link != "" {
				return link, nil
			}
		}
		return resolver.ResolveGoogleDrivePath(ctx, accessToken, logicalPath)
	case "microsoft":
		return resolver.ResolveMicrosoftDrivePath(ctx, accessToken, logicalPath)
	default:
		return "", ErrInvalid
	}
}

func providerIDFromETag(etag string) string {
	id := strings.Trim(strings.TrimSpace(etag), "\"")
	if id == "" {
		return ""
	}
	for _, r := range id {
		if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '_' || r == '-' {
			continue
		}
		return ""
	}
	if len(id) < 10 {
		return ""
	}
	return id
}
