using System.Collections.ObjectModel;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform;
using OF_DL.Gui.Helpers;
using OF_DL.Helpers;
using Serilog;

namespace OF_DL.Gui.Views;

public class FaqLink(string label, string url)
{
    public string Label { get; } = label;

    public string Url { get; } = url;
}

public class FaqEntry
{
    public FaqEntry(
        string question,
        IEnumerable<string> paragraphs,
        IEnumerable<FaqLink>? links = null,
        string? codeSnippet = null)
    {
        Question = question;
        Paragraphs = paragraphs.ToList();
        Links = links?.ToList() ?? [];
        CodeSnippet = codeSnippet;
    }

    public string Question { get; }

    public IReadOnlyList<string> Paragraphs { get; }

    public IReadOnlyList<FaqLink> Links { get; }

    public bool HasLinks => Links.Count > 0;

    public string? CodeSnippet { get; }

    public bool HasCodeSnippet => !string.IsNullOrWhiteSpace(CodeSnippet);
}

public partial class FaqWindow : Window
{
    private const string DockerRunCommand =
        "docker run --rm -it -v $HOME/ofdl/data/:/data -v $HOME/ofdl/config/:/config -p 8080:8080 git.ofdl.tools/sim0n00ps/of-dl:latest";

    public FaqWindow()
    {
        InitializeComponent();
        Icon = new WindowIcon(AssetLoader.Open(new Uri("avares://OF DL.Gui/Assets/icon.ico")));
        BuildEntries();
        DataContext = this;
    }

    public ObservableCollection<FaqEntry> Entries { get; } = [];

    private void BuildEntries()
    {
        Entries.Clear();

        bool isDocker = EnvironmentHelper.IsRunningInDocker();
        bool isWindows = EnvironmentHelper.IsRunningOnWindows();

        Entries.Add(new FaqEntry(
            "Why are some users missing from the users list?",
            [
                "Users may be missing from the users list if those subscriptions have expired or are restricted. You can enable expired subscriptions and restricted subscriptions from the \"Subscriptions\" section in \"Configuration\" (accessible from the Edit menu)."
            ]));

        if (!isDocker)
        {
            Entries.Add(new FaqEntry(
                "Where are the downloads saved?",
                [
                    "Content is downloaded to the configured download directory. You can view or change the download directory from the \"Download Behavior\" section in \"Configuration\" (accessible from the Edit menu)."
                ]));
        }
        else
        {
            Entries.Add(new FaqEntry(
                "Where are the downloads saved?",
                [
                    "Your docker run command specifies the directory that content will be downloaded to. For instance, given the following docker run command, content will be downloaded to the $HOME/ofdl/data/ directory.",
                    "Do not change the download directory from the \"Download Behavior\" section in \"Configuration\" (accessible from the Edit menu) unless you know what you are doing. If the download directory is set to a value other than /data, content will not be downloaded where you expect and may not be accessible to you."
                ],
                null,
                DockerRunCommand));
        }

        Entries.Add(new FaqEntry(
            "Why am I seeing a warning about CDM keys for DRM videos?",
            [
                "If you don't have your own CDM keys, a service will be used to download DRM videos. However, it is recommended that you use your own CDM keys for more reliable and faster downloads. The process is very easy if you use the bot on our Discord server.",
                "See the documentation on CDM keys for more information:"
            ],
            [
                new FaqLink("https://docs.ofdl.tools/config/cdm/#discord-method",
                    "https://docs.ofdl.tools/config/cdm/#discord-method")
            ]));

        if (isDocker)
        {
            Entries.Add(new FaqEntry(
                "Why am I seeing a FFmpeg or FFprobe is missing error?",
                [
                    "FFmpeg and FFprobe are required for OF DL to function. Both programs are included in the Docker image.",
                    "If you are seeing this error, the most likely cause is that you have manually defined a FFmpeg Path and/or FFprobe Path in your configuration. To fix this, erase the configured paths in the \"External\" section in \"Configuration\" (accessible from the Edit menu). Once you save the changes, OF DL will automatically detect the correct paths."
                ]));
        }
        else if (isWindows)
        {
            Entries.Add(new FaqEntry(
                "Why am I seeing a FFmpeg or FFprobe is missing error?",
                [
                    "FFmpeg and FFprobe are required for OF DL to function. Both programs are included with OF DL in the release .zip file. Make sure both files (ffmpeg.exe and ffprobe.exe) are in the same directory as OF DL.exe.",
                    "If you have already done this and still see an error, the most likely cause is that you have manually defined a FFmpeg Path and/or FFprobe Path in your configuration. To fix this, erase the configured paths in the \"External\" section in \"Configuration\" (accessible from the Edit menu). Once you save the changes, OF DL will automatically detect the correct paths."
                ]));
        }
        else
        {
            Entries.Add(new FaqEntry(
                "Why am I seeing a FFmpeg or FFprobe is missing error?",
                [
                    "FFmpeg and FFprobe are required for OF DL to function. Install both programs.",
                    "If the FFmpeg and FFprobe paths are not manually defined in the \"External\" section in \"Configuration\" (accessible from the Edit menu), OF DL searches for programs named ffmpeg and ffprobe in the same directory as OF DL and in the directories defined in the PATH environment variable."
                ]));
        }
    }

    private async void OnLinkClick(object? sender, RoutedEventArgs e)
    {
        try
        {
            if (sender is not Button { CommandParameter: string url } || string.IsNullOrWhiteSpace(url))
            {
                return;
            }

            await WebLinkHelper.OpenOrCopyAsync(this, url, sender as Control);
        }
        catch (Exception exception)
        {
            Log.Error(exception, "Failed to handle link click event. {ErrorMessage}", exception.Message);
        }
    }
}
