using Seenginx.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Seenginx.Services
{
	public class FileManager : IFileManager
	{
		public async Task<Result<ConfigFile>> SaveUpdateFileAsync(ConfigFile configFile)
		{
			var result = new Result<ConfigFile>(configFile);
			try
			{
				var validationResult = ValidForUpdate(configFile);
				if (!validationResult.AllOk)
					return result.Invalidate($"Failed validation for: {validationResult.ErrorMessage}");

				await File.WriteAllTextAsync(configFile.FullPath, configFile.Body);

				return result;
			}
			catch (Exception ex)
			{
				return result.Invalidate($"Exception at {nameof(SaveUpdateFileAsync)}(), with {nameof(ConfigFile.Name)}=[{nameof(configFile.Name)}]", ex);
			}
		}

		public async Task<Result<ConfigFile>> SaveUpdateDraftFileAsync(ConfigFile configFile)
		{
			var result = new Result<ConfigFile>(configFile);
			try
			{
				var validationResult = ValidForUpdate(configFile);
				if (!validationResult.AllOk)
					return result.Invalidate($"Failed validation for: {validationResult.ErrorMessage}");

				await File.WriteAllTextAsync($"{configFile.FullPath}.draft", configFile.DraftBody);

				return result;
			}
			catch (Exception ex)
			{
				return result.Invalidate($"Exception at {nameof(SaveUpdateDraftFileAsync)}(), with {nameof(ConfigFile.Name)}=[{nameof(configFile.Name)}]", ex);
			}
		}

		public Result<bool> DeleteFile(ConfigFile configFile)
		{
			var result = new Result<bool>();
			try
			{
				var validationResult = ValidForUpdate(configFile);

				if (!validationResult.AllOk)
					return result.Invalidate($"Failed validation for: {validationResult.ErrorMessage}");

				File.Delete(configFile.FullPath);
				if (File.Exists($"{configFile.FullPath}.draft"))
					File.Delete($"{configFile.FullPath}.draft");

				return result;
			}
			catch (Exception ex)
			{
				return result.Invalidate($"Exception at {nameof(DeleteFile)}(), with {nameof(ConfigFile.Name)}=[{nameof(configFile.Name)}]", ex);
			}
		}

		private Result<string> ValidForUpdate(ConfigFile configFile)
		{
			var result = new Result<string>();
			if (!Directory.Exists(Directory.GetDirectoryRoot(configFile.FullPath)))
				return result.Invalidate($"Directory '{Directory.GetDirectoryRoot(configFile.FullPath)}' doesn't exist.");
			if (!File.Exists(configFile.FullPath))
				return result.Invalidate($"File '{configFile.FullPath}' doesn't exist.");
			return result;
		}

	}
}
