package handlers

import (
	"bytes"
	"context"
	"io"
	"strings"
	"time"

	filemanager "wucher/internal/domain/file_manager"
	takeoverdomain "wucher/internal/domain/takeover"
)

type takeoverWOPIStorage interface {
	GetObject(ctx context.Context, objectKey string) (io.ReadCloser, filemanager.ObjectMetadata, error)
	HeadObject(ctx context.Context, objectKey string) (filemanager.ObjectMetadata, error)
	PutObject(ctx context.Context, input filemanager.PutObjectInput) (filemanager.ObjectMetadata, error)
	CopyObject(ctx context.Context, sourceObjectKey, destinationObjectKey string) (filemanager.ObjectMetadata, error)
	DeleteObject(ctx context.Context, objectKey string) error
}

type takeoverWOPIFileInfo struct {
	BaseFileName               string `json:"BaseFileName"`
	Version                    string `json:"Version"`
	OwnerId                    string `json:"OwnerId,omitempty"`
	UserId                     string `json:"UserId,omitempty"`
	UserFriendlyName           string `json:"UserFriendlyName,omitempty"`
	Size                       int64  `json:"Size"`
	ReadOnly                   bool   `json:"ReadOnly"`
	UserCanWrite               bool   `json:"UserCanWrite"`
	SupportsUpdate             bool   `json:"SupportsUpdate"`
	SupportsLocks              bool   `json:"SupportsLocks"`
	SupportsGetLock            bool   `json:"SupportsGetLock"`
	SupportsRename             bool   `json:"SupportsRename"`
	SupportsExtendedLockLength bool   `json:"SupportsExtendedLockLength"`
	LastModifiedTime           string `json:"LastModifiedTime,omitempty"`
}

func takeoverHasUserAccess(row *takeoverdomain.TakeoverAc, userID []byte) bool {
	if row == nil || len(userID) != 16 {
		return false
	}
	if bytes.Equal(row.CreatedBy, userID) {
		return true
	}
	for i := range row.RosterCrews {
		crew := row.RosterCrews[i]
		if len(crew.UserID) != 16 || crew.DeletedAt != nil {
			continue
		}
		if bytes.Equal(crew.UserID, userID) {
			return true
		}
	}
	return false
}

func takeoverHasUserAccessOrAdmin(h *TakeoverHandler, row *takeoverdomain.TakeoverAc, userID []byte) bool {
	if h != nil && h.takeoverUserHasGlobalAccessForUserID(context.Background(), userID) {
		return true
	}
	return takeoverHasUserAccess(row, userID)
}

func takeoverFindFileByID(row *takeoverdomain.TakeoverAc, fileID []byte) (*filemanager.File, error) {
	if row == nil || len(fileID) != 16 {
		return nil, filemanager.ErrFileNotFound
	}
	for i := range row.Files {
		fileAttachment := row.Files[i].FileAttachment
		if fileAttachment == nil || fileAttachment.File == nil {
			continue
		}
		if bytes.Equal(fileAttachment.File.ID, fileID) {
			return fileAttachment.File, nil
		}
	}
	return nil, filemanager.ErrFileNotFound
}

func wopiFileVersion(row *filemanager.File) string {
	if row == nil {
		return ""
	}
	if version := strings.TrimSpace(row.ObjectVersion); version != "" {
		return version
	}
	if etag := strings.TrimSpace(row.ETag); etag != "" {
		return etag
	}
	return row.UpdatedAt.UTC().Format(time.RFC3339Nano)
}
