using File_Folder_Helper.Helpers;
using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace File_Folder_Helper.ADO2024.PI1;

internal static partial class Helper20240427
{

    private record Asset( // cSpell:disable
        [property: JsonPropertyName("id")] string? Id,
        [property: JsonPropertyName("deviceAssetId")] string? DeviceAssetId,
        [property: JsonPropertyName("ownerId")] string? OwnerId,
        [property: JsonPropertyName("deviceId")] string? DeviceId,
        [property: JsonPropertyName("type")] string? Type,
        [property: JsonPropertyName("originalPath")] string? OriginalPath,
        [property: JsonPropertyName("previewPath")] string? PreviewPath,
        [property: JsonPropertyName("fileCreatedAt")] DateTime? FileCreatedAt,
        [property: JsonPropertyName("fileModifiedAt")] DateTime? FileModifiedAt,
        [property: JsonPropertyName("isFavorite")] bool? IsFavorite,
        [property: JsonPropertyName("duration")] object? Duration,
        [property: JsonPropertyName("thumbnailPath")] string? ThumbnailPath,
        [property: JsonPropertyName("encodedVideoPath")] string? EncodedVideoPath,
        [property: JsonPropertyName("checksum")] string? Checksum,
        [property: JsonPropertyName("isVisible")] bool? IsVisible,
        [property: JsonPropertyName("livePhotoVideoId")] object? LivePhotoVideoId,
        [property: JsonPropertyName("updatedAt")] DateTime? UpdatedAt,
        [property: JsonPropertyName("createdAt")] DateTime? CreatedAt,
        [property: JsonPropertyName("isArchived")] bool? IsArchived,
        [property: JsonPropertyName("originalFileName")] string? OriginalFileName,
        [property: JsonPropertyName("sidecarPath")] string? SidecarPath,
        [property: JsonPropertyName("isReadOnly")] bool? IsReadOnly,
        [property: JsonPropertyName("thumbhash")] string? Thumbhash,
        [property: JsonPropertyName("isOffline")] bool? IsOffline,
        [property: JsonPropertyName("libraryId")] string? LibraryId,
        [property: JsonPropertyName("isExternal")] bool? IsExternal,
        [property: JsonPropertyName("deletedAt")] DateTime? DeletedAt,
        [property: JsonPropertyName("localDateTime")] DateTime? LocalDateTime,
        [property: JsonPropertyName("stackId")] object? StackId); // cSpell:restore

    [JsonSourceGenerationOptions(WriteIndented = true, AllowTrailingCommas = true)]
    [JsonSerializable(typeof(List<Asset>))]
    private partial class AssetCollectionSourceGenerationContext : JsonSerializerContext
    {
    }

    private static string? MoveAsset(string home, string originalFileName, string lastVarDirectoryName, string path)
    {
        string? result;
        string checkFile;
        string sourceFile;
        int? match = null;
        string checkDirectory = home;
        string sourceDirectory = home;
        string originalFileNameWithoutExtension = Path.GetFileNameWithoutExtension(originalFileName);
        ReadOnlyCollection<string> directoryNames = HelperDirectory.GetDirectoryNames(path);
        for (int i = 0; i < directoryNames.Count; i++)
        {
            if (directoryNames[i] != lastVarDirectoryName)
                continue;
            match = i;
            break;
        }
        if (match is null)
            result = null;
        else
        {
            string[] fileNameSegments = directoryNames[^1].Split('-');
            foreach (string directory in directoryNames.Skip(match.Value + 1).Take(directoryNames.Count - match.Value - 2))
                sourceDirectory = Path.Combine(sourceDirectory, directory);
            if (!Directory.Exists(sourceDirectory))
                result = null;
            else
            {
                sourceFile = Path.Combine(sourceDirectory, directoryNames[^1]);
                if (!File.Exists(sourceFile))
                    result = null;
                else
                {
                    foreach (string directory in directoryNames.Skip(match.Value + 1).Take(directoryNames.Count - match.Value - 2))
                        checkDirectory = Path.Combine(checkDirectory, directory);
                    if (!Directory.Exists(checkDirectory))
                        _ = Directory.CreateDirectory(checkDirectory);
                    checkFile = Path.Combine(checkDirectory, $"{originalFileNameWithoutExtension}{fileNameSegments[^1]}");
                    if (File.Exists(checkFile))
                        result = null;
                    else
                    {
                        File.Move(sourceFile, checkFile);
                        result = checkFile;
                    }
                }
            }
        }
        return result;
    }

    private static void MoveAssets(ILogger<Worker> logger, string var, string home, string pictures, List<Asset> assets)
    {
        string? checkFile;
        ReadOnlyCollection<string> directoryNames = HelperDirectory.GetDirectoryNames(home);
        string lastDirectoryName = directoryNames[^1];
        foreach (Asset asset in assets)
        {
            if (asset.OriginalFileName is null)
                continue;
            if (asset.Type is null or not "IMAGE")
                continue;
            if (asset.PreviewPath is null || !asset.PreviewPath.StartsWith(var))
                continue;
            if (asset.ThumbnailPath is null || !asset.ThumbnailPath.StartsWith(var))
                continue;
            if (asset.OriginalPath is null || !asset.OriginalPath.StartsWith(pictures))
                continue;
            checkFile = MoveAsset(home, asset.OriginalFileName, lastDirectoryName, asset.PreviewPath);
            if (checkFile is null)
                continue;
            checkFile = MoveAsset(home, asset.OriginalFileName, lastDirectoryName, asset.ThumbnailPath);
            if (checkFile is null)
                continue;
            logger.LogDebug("<{OriginalFileName}> moved.", asset.OriginalFileName);
        }
    }

#pragma warning restore IDE0055, IDE0059, IDE0060, IDE2000, CS0168

    internal static void Immich(Models.AppSettings appSettings, ILogger<Worker> logger, List<string> args)
    {
        string var = args[5];
        string home = args[6];
        string query = args[3];
        string jsonFile = args[4];
        string pictures = args[7];
        string directory = args[0];
        logger.LogInformation(query);
        string databasePassword = args[2];
        string json = File.ReadAllText(Path.Combine(directory, jsonFile));
        List<Asset> assets = JsonSerializer.Deserialize(json, AssetCollectionSourceGenerationContext.Default.ListAsset) ?? throw new NullReferenceException();
        string encryptedPassword = RijndaelEncryption.Encrypt(databasePassword, appSettings.Company);
        MoveAssets(logger, var, home, pictures, assets);
        logger.LogInformation("Encrypted Password: [{EncryptedPassword}]", encryptedPassword);
    }

}