using IWS5.Importer.Abstractions.Interfaces;
using Serilog.Context;
using ILogger = Serilog.ILogger;

namespace IWS5.Importer.Worker.FileSystem;

public class FolderMover(ILogger logger, IGeneralImportSettingsProvider settingsProvider, IFileHelper fileHelper) : IFolderMover
{
    private readonly string _importDir = settingsProvider.Settings.ImportDirs;
    private readonly string _errorDir = settingsProvider.Settings.CopyErrorLocation;
    private readonly IFileHelper _fileHelper = fileHelper;

    public void MoveInvalidFolderToError(string folderPath, string? errorLocation = null)
    {
        var targetLocation = errorLocation ?? _errorDir;
        if (string.IsNullOrWhiteSpace(folderPath) || !Directory.Exists(folderPath))
        {
            using (LogContext.PushProperty("LogContext", nameof(FolderMover)))
                logger.Warning("Invalid or non-existent folder path: {FolderPath}", folderPath);
            return;
        }

        try
        {
            string destination = BuildUniqueDestinationPath(folderPath, targetLocation);

            Directory.Move(folderPath, destination);
            using (LogContext.PushProperty("LogContext", nameof(FolderMover)))
                logger.Warning("Moved unsupported folder {FolderPath} to error location: {Destination}", folderPath, destination);
        }
        catch (IOException ioEx)
        {
            LogMoveError(ioEx, folderPath, "Error Folder (IO Error)");
        }
        catch (UnauthorizedAccessException authEx)
        {
            LogMoveError(authEx, folderPath, "Error Folder (Permission Denied)");
        }
        catch (Exception ex)
        {
            LogMoveError(ex, folderPath, "Error Folder (General)");
        }
    }

    public void MoveProcessedFolder(string folderPath, string backupLocation)
    {
        if (string.IsNullOrWhiteSpace(folderPath) || !Directory.Exists(folderPath))
        {
            logger.Warning("Invalid or non-existent folder path: {FolderPath}", folderPath);
            return;
        }

        try
        {
            string destinationPath = BuildUniqueDestinationPath(folderPath, backupLocation);

            Directory.Move(folderPath, destinationPath);
            using (LogContext.PushProperty("LogContext", nameof(FolderMover)))
                logger.Information("Moved processed folder {FolderPath} to backup location: {DestinationPath}", folderPath, destinationPath);
        }
        catch (IOException ioEx)
        {
            LogMoveError(ioEx, folderPath, "Processed Folder (IO Error)");
        }
        catch (UnauthorizedAccessException authEx)
        {
            LogMoveError(authEx, folderPath, "Processed Folder (Permission Denied)");
        }
        catch (Exception ex)
        {
            LogMoveError(ex, folderPath, "Processed Folder (General Error)");
        }
    }

    private string BuildUniqueDestinationPath(string sourceFolderPath, string targetBasePath)
    {
        string relativePath = Path.GetRelativePath(_importDir, sourceFolderPath);
        string structuredDestinationPath = Path.Combine(targetBasePath, relativePath);

        return _fileHelper.GetUniqueDestinationPath(structuredDestinationPath);
    }

    private void LogMoveError(Exception ex, string folderPath, string context)
    {
        using (LogContext.PushProperty("LogContext", nameof(FolderMover)))
            logger.Error(ex, "Failed moving folder {FolderPath} - {Context}", folderPath, context);
    }
}
