package drivebridge

import (
	"context"
	"errors"
	"io"
	"net/http"
	"path"

	"github.com/ultisuite/ulti-backend/internal/api/drive"
	"github.com/ultisuite/ulti-backend/internal/api/query"
	"github.com/ultisuite/ulti-backend/internal/auth"
	"github.com/ultisuite/ulti-backend/internal/nextcloud"
)

// Bridge adapts drive.Service for mail attachment exports.
type Bridge struct {
	Svc *drive.Service
}

func (b *Bridge) claims(email, sub, displayName string) *auth.Claims {
	return &auth.Claims{Email: email, Sub: sub, Name: displayName}
}

func (b *Bridge) ncUser(ctx context.Context, email, sub, displayName string) (string, error) {
	if b.Svc == nil {
		return "", errors.New("drive unavailable")
	}
	return b.Svc.EnsureNextcloudUser(ctx, b.claims(email, sub, displayName))
}

func (b *Bridge) EnsureNextcloudFolder(ctx context.Context, email, sub, displayName, folderPath string) error {
	userID, err := b.ncUser(ctx, email, sub, displayName)
	if err != nil {
		return err
	}
	err = b.Svc.CreateFolder(ctx, userID, folderPath)
	if err == nil || errors.Is(err, drive.ErrConflict) {
		return nil
	}
	var statusErr *nextcloud.HTTPStatusError
	if errors.As(err, &statusErr) && statusErr.StatusCode == http.StatusMethodNotAllowed {
		return nil
	}
	return err
}

func (b *Bridge) UploadFile(ctx context.Context, email, sub, displayName, destPath string, body io.Reader, contentType string, size int64) error {
	userID, err := b.ncUser(ctx, email, sub, displayName)
	if err != nil {
		return err
	}
	return b.Svc.Upload(ctx, userID, destPath, body, contentType, size)
}

func (b *Bridge) NotifyFileChanged(platformUserID, filePath string) {
	if b.Svc == nil {
		return
	}
	b.Svc.PublishFileChanged(platformUserID, filePath)
}

func (b *Bridge) FileExists(ctx context.Context, email, sub, displayName, filePath string) (bool, error) {
	userID, err := b.ncUser(ctx, email, sub, displayName)
	if err != nil {
		return false, err
	}
	parent := path.Dir(filePath)
	name := path.Base(filePath)
	files, err := b.Svc.ListFiles(ctx, userID, parent, query.ListParams{Page: 1, PageSize: 10_000})
	if err != nil {
		return false, err
	}
	for _, f := range files.Files {
		if f.Name == name {
			return true, nil
		}
	}
	return false, nil
}
