using System.Text.Json;
using System.Text.Json.Serialization;
using View_by_Distance.Shared.Models.Stateless;

namespace View_by_Distance.Shared.Models;

public record FilePath(long CreationTicks,
                       string DirectoryFullPath,
                       string ExtensionLowered,
                       string FileNameFirstSegment,
                       string FullName,
                       int? Id,
                       bool? HasIgnoreKeyword,
                       bool? HasDateTimeOriginal,
                       bool IsIntelligentIdFormat,
                       long LastWriteTicks,
                       long Length,
                       string Name,
                       string NameWithoutExtension,
                       int? SortOrder)
{

    public override string ToString()
    {
        string result = JsonSerializer.Serialize(this, FilePathSourceGenerationContext.Default.FilePath);
        return result;
    }

    public static FilePath Get(ResultSettings resultSettings, MetadataSettings metadataSettings, FileHolder fileHolder, int? index)
    {
        if (fileHolder.CreationTime is null)
            fileHolder = FileHolder.Get(fileHolder);
        if (fileHolder.CreationTime is null)
            throw new NullReferenceException(nameof(fileHolder.CreationTime));
        if (fileHolder.LastWriteTime is null)
            throw new NullReferenceException(nameof(fileHolder.LastWriteTime));
        if (fileHolder.Length is null)
            throw new NullReferenceException(nameof(fileHolder.Length));
        FilePath result;
        int? id;
        int? sortOrder;
        string fileNameFirstSegment = fileHolder.Name.Split('.')[0];
        int sortOrderOnlyLengthIndex = metadataSettings.Offset.ToString().Length;
        string fileDirectoryFullPath = fileHolder.DirectoryFullPath ?? throw new NullReferenceException();
        bool isIntelligentIdFormat = IId.NameWithoutExtensionIsIntelligentIdFormat(metadataSettings, fileNameFirstSegment);
        bool isPaddedIntelligentIdFormat = IId.NameWithoutExtensionIsPaddedIntelligentIdFormat(metadataSettings, sortOrderOnlyLengthIndex, fileNameFirstSegment);
        bool fileNameFirstSegmentIsIdFormat = !isPaddedIntelligentIdFormat && !isIntelligentIdFormat && IId.NameWithoutExtensionIsIdFormat(metadataSettings, fileHolder);
        bool? hasIgnoreKeyword = !isIntelligentIdFormat && !isPaddedIntelligentIdFormat ? null : fileNameFirstSegment[^1] is '2' or '8';
        bool? hasDateTimeOriginal = !isIntelligentIdFormat && !isPaddedIntelligentIdFormat ? null : fileNameFirstSegment[^1] is '1' or '9';
        if (!fileNameFirstSegmentIsIdFormat && !isIntelligentIdFormat && !isPaddedIntelligentIdFormat)
            (id, sortOrder) = (null, null);
        else if (isIntelligentIdFormat)
            (id, sortOrder) = (IId.GetId(resultSettings, metadataSettings, fileNameFirstSegment), null);
        else if (isPaddedIntelligentIdFormat)
        {
            if (!int.TryParse(fileNameFirstSegment[..sortOrderOnlyLengthIndex], out int absoluteValueOfSortOrder))
                (id, sortOrder) = (null, null);
            else
                (id, sortOrder) = (IId.GetId(resultSettings, metadataSettings, fileNameFirstSegment[sortOrderOnlyLengthIndex..]), absoluteValueOfSortOrder);
        }
        else if (fileNameFirstSegmentIsIdFormat)
        {
            if (index is null)
                throw new NullReferenceException(nameof(index));
            if (!int.TryParse(fileNameFirstSegment, out int valueOfFileNameFirstSegment))
                throw new NotSupportedException();
            (id, sortOrder) = (valueOfFileNameFirstSegment, metadataSettings.Offset + index);
        }
        else
            throw new NotSupportedException();
        result = new(fileHolder.CreationTime.Value.Ticks,
                     fileDirectoryFullPath,
                     fileHolder.ExtensionLowered,
                     fileNameFirstSegment,
                     fileHolder.FullName,
                     id,
                     hasIgnoreKeyword,
                     hasDateTimeOriginal,
                     isIntelligentIdFormat,
                     fileHolder.LastWriteTime.Value.Ticks,
                     fileHolder.Length.Value,
                     fileHolder.Name,
                     fileHolder.NameWithoutExtension,
                     sortOrder);
        return result;
    }

    public static FilePath Get(FilePath filePath, DeterministicHashCode deterministicHashCode) =>
        new(filePath.CreationTicks,
            filePath.DirectoryFullPath,
            filePath.ExtensionLowered,
            filePath.FileNameFirstSegment,
            filePath.FullName,
            deterministicHashCode.Id ?? filePath.Id,
            filePath.HasIgnoreKeyword,
            filePath.HasDateTimeOriginal,
            filePath.IsIntelligentIdFormat,
            filePath.LastWriteTicks,
            filePath.Length,
            filePath.Name,
            filePath.NameWithoutExtension,
            filePath.SortOrder);

}

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(FilePath))]
public partial class FilePathSourceGenerationContext : JsonSerializerContext
{
}