package handlers

import (
	"context"

	filemanager "wucher/internal/domain/file_manager"
)

func resolveFileIDFromAttachment(ctx context.Context, svc filemanager.Service, attachmentID []byte) ([]byte, error) {
	if len(attachmentID) != 16 || svc == nil {
		return nil, nil
	}
	attachment, err := svc.GetAttachmentByID(ctx, attachmentID)
	if err != nil || attachment == nil {
		return nil, err
	}
	return attachment.FileID, nil
}

func syncAttachmentLifecycleSwap(
	ctx context.Context,
	svc filemanager.Service,
	oldAttachmentID []byte,
	newAttachmentID []byte,
	actorID []byte,
) error {
	lifecycle, ok := svc.(filemanager.LifecycleManager)
	if !ok {
		return nil
	}
	oldFileID, err := resolveFileIDFromAttachment(ctx, svc, oldAttachmentID)
	if err != nil {
		return err
	}
	newFileID, err := resolveFileIDFromAttachment(ctx, svc, newAttachmentID)
	if err != nil {
		return err
	}
	if len(newFileID) == 16 {
		if err := lifecycle.MarkFileActive(ctx, newFileID, actorID); err != nil {
			return err
		}
	}
	if len(oldFileID) == 16 && (len(newFileID) != 16 || string(oldFileID) != string(newFileID)) {
		if err := lifecycle.ReconcileFileLifecycle(ctx, oldFileID, actorID); err != nil {
			return err
		}
	}
	return nil
}

func syncAttachmentLifecycleClear(
	ctx context.Context,
	svc filemanager.Service,
	oldAttachmentID []byte,
	actorID []byte,
) error {
	return syncAttachmentLifecycleSwap(ctx, svc, oldAttachmentID, nil, actorID)
}

func syncFileLifecycleSwap(
	ctx context.Context,
	svc filemanager.Service,
	oldFileID []byte,
	newFileID []byte,
	actorID []byte,
) error {
	lifecycle, ok := svc.(filemanager.LifecycleManager)
	if !ok {
		return nil
	}
	if len(newFileID) == 16 {
		if err := lifecycle.MarkFileActive(ctx, newFileID, actorID); err != nil {
			return err
		}
	}
	if len(oldFileID) == 16 && (len(newFileID) != 16 || string(oldFileID) != string(newFileID)) {
		if err := lifecycle.ReconcileFileLifecycle(ctx, oldFileID, actorID); err != nil {
			return err
		}
	}
	return nil
}

func syncAttachmentLifecycleSet(
	ctx context.Context,
	svc filemanager.Service,
	oldAttachmentIDs [][]byte,
	newAttachmentIDs [][]byte,
	actorID []byte,
) error {
	lifecycle, ok := svc.(filemanager.LifecycleManager)
	if !ok {
		return nil
	}
	oldMap := make(map[string][]byte, len(oldAttachmentIDs))
	newMap := make(map[string][]byte, len(newAttachmentIDs))
	for i := range oldAttachmentIDs {
		if len(oldAttachmentIDs[i]) == 16 {
			oldMap[string(oldAttachmentIDs[i])] = oldAttachmentIDs[i]
		}
	}
	for i := range newAttachmentIDs {
		if len(newAttachmentIDs[i]) == 16 {
			newMap[string(newAttachmentIDs[i])] = newAttachmentIDs[i]
		}
	}

	for _, attachmentID := range newMap {
		fileID, err := resolveFileIDFromAttachment(ctx, svc, attachmentID)
		if err != nil {
			return err
		}
		if len(fileID) == 16 {
			if err := lifecycle.MarkFileActive(ctx, fileID, actorID); err != nil {
				return err
			}
		}
	}

	for key, attachmentID := range oldMap {
		if _, keep := newMap[key]; keep {
			continue
		}
		fileID, err := resolveFileIDFromAttachment(ctx, svc, attachmentID)
		if err != nil {
			return err
		}
		if len(fileID) == 16 {
			if err := lifecycle.ReconcileFileLifecycle(ctx, fileID, actorID); err != nil {
				return err
			}
		}
	}
	return nil
}
