using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;

namespace VRCX;

public partial class AppApi
{
    [GeneratedRegex(@"\\Prints\\|\\Stickers\\|\\Emoji\\", RegexOptions.IgnoreCase, "en-US")]
    private static partial Regex ScreenshotRegex();

    public string GetExtraScreenshotData(string path, bool carouselCache)
    {
        var fileName = Path.GetFileNameWithoutExtension(path);
        var metadata = new JObject();

        if (!File.Exists(path) || !path.EndsWith(".png"))
            return null;

        var files = Directory.GetFiles(Path.GetDirectoryName(path), "*.png");

        // Add previous/next file paths to metadata so the screenshot viewer carousel can request metadata for next/previous images in directory
        if (carouselCache)
        {
            var index = Array.IndexOf(files, path);
            if (index > 0)
            {
                metadata.Add("previousFilePath", files[index - 1]);
            }
            if (index < files.Length - 1)
            {
                metadata.Add("nextFilePath", files[index + 1]);
            }
        }

        using var png = new PNGFile(path, false);
        metadata.Add("fileResolution", PNGHelper.ReadResolution(png));

        var creationDate = File.GetCreationTime(path);
        metadata.Add("creationDate", creationDate.ToString("yyyy-MM-dd HH:mm:ss"));

        var fileSizeBytes = new FileInfo(path).Length;
        metadata.Add("fileSizeBytes", fileSizeBytes.ToString());
        metadata.Add("fileName", fileName);
        metadata.Add("filePath", path);
        metadata.Add("fileSize", $"{(fileSizeBytes / 1024f / 1024f).ToString("0.00")} MB");

        return metadata.ToString(Formatting.Indented);
    }

    public string GetScreenshotMetadata(string path)
    {
        if (string.IsNullOrEmpty(path))
            return null;


        var metadata = ScreenshotHelper.GetScreenshotMetadata(path);

        if (metadata == null)
        {
            var obj = new JObject
            {
                { "sourceFile", path },
                { "error", "Screenshot contains no metadata." }
            };

            return obj.ToString(Formatting.Indented);
        };

        if (metadata.Error != null)
        {
            var obj = new JObject
            {
                { "sourceFile", path },
                { "error", metadata.Error }
            };

            return obj.ToString(Formatting.Indented);
        }

        return JsonConvert.SerializeObject(metadata, Formatting.Indented, new JsonSerializerSettings
        {
            ContractResolver = new DefaultContractResolver
            {
                NamingStrategy = new CamelCaseNamingStrategy() // This'll serialize our .net property names to their camelCase equivalents. Ex; "FileName" -> "fileName"
            }
        });
    }

    public string FindScreenshotsBySearch(string searchQuery, int searchType = 0)
    {
        var stopwatch = new Stopwatch();
        stopwatch.Start();

        var searchPath = GetVRChatPhotosLocation();
        var screenshots = ScreenshotHelper.FindScreenshots(searchQuery, searchPath, (ScreenshotHelper.ScreenshotSearchType)searchType);

        JArray json = new JArray();

        foreach (var screenshot in screenshots)
        {
            json.Add(screenshot.SourceFile);
        }

        stopwatch.Stop();

        logger.Info($"FindScreenshotsBySearch took {stopwatch.ElapsedMilliseconds}ms to complete.");

        return json.ToString();
    }

    public string GetLastScreenshot()
    {
        // Get the last screenshot taken by VRChat
        var path = GetVRChatPhotosLocation();
        if (!Directory.Exists(path))
            return null;
        
        // exclude folder names that contain "Prints", "Stickers" or "Emoji"
        var imageFiles = Directory.GetFiles(path, "*.png", SearchOption.AllDirectories)
            .Where(x => !ScreenshotRegex().IsMatch(x));
        var lastScreenshot = imageFiles.OrderByDescending(Directory.GetCreationTime).FirstOrDefault();

        return lastScreenshot;
    }
    
    public bool DeleteScreenshotMetadata(string path)
    {
        if (string.IsNullOrEmpty(path) || !File.Exists(path) || !path.EndsWith(".png"))
            return false;

        try
        {
            ScreenshotHelper.DeleteTextMetadata(path, true);
            return true;
        }
        catch (Exception ex)
        {
            logger.Error(ex, "Failed to delete screenshot metadata for {0}", path);
            return false;
        }
    }
    
    public void DeleteAllScreenshotMetadata()
    {
        var path = GetVRChatPhotosLocation();
        if (!Directory.Exists(path))
            return;
        
        var imageFiles = Directory.GetFiles(path, "*.png", SearchOption.AllDirectories);
        foreach (var file in imageFiles)
        {
            try
            {
                ScreenshotHelper.DeleteTextMetadata(file, true);
            }
            catch (Exception ex)
            {
                logger.Error(ex, "Failed to delete screenshot metadata for {0}", file);
            }
        }
    }
}