using ExtensiblePortfolioSite.SDK;
using ExtensiblePortfolioSite.SDK.Git;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace GithubPlugin
{
    [Serializable]
    public class GithubRepo : IRepository
    {
        [JsonInclude]
        [JsonPropertyName("name")]
        public string Name { get; init; }

        [JsonInclude]
        [JsonPropertyName("description")]
        public string Description { get; init; }

        [JsonInclude]
        [JsonPropertyName("owner")]
        public GithubUser Owner { get; internal set; }

        [JsonIgnore]
        public GithubProvider Provider { get; internal set; }

        [JsonIgnore]
        IGitProvider IGitObject.Provider => this.Provider;

        [JsonIgnore]
        IUser IRepository.Owner => this.Owner;

        public ICommit? GetCommit(uint HeadOffset = 0)
        {
            var response = Provider.GetAPIResource($"repos/{Owner.Name}/{Name}/commits");
            if (response.IsSuccessStatusCode)
                return GetCommitByRef(JsonDocument.Parse(response.Content.ReadAsStream()).RootElement.EnumerateArray().Skip((int)HeadOffset).First().GetProperty("sha").GetString());
            else
                return null;
        }

        public ICommit? GetCommitByRef(string reference)
        {
            var response = Provider.GetAPIResource($"repos/{Owner.Name}/{Name}/commits/{reference}");
            if (response.IsSuccessStatusCode)
            {
                JsonDocument json = JsonDocument.Parse(response.Content.ReadAsStream());
                JsonElement commitObject = json.RootElement;
                GithubCommit commit = Json.Deserialize<GithubCommit>(commitObject.GetProperty("commit"))!;
                commit.AuthorAvatarUrl = commitObject.GetProperty("author").GetProperty("avatar_url").GetString();
                commit.Provider = Provider;
                commit.Repository = this;
                List<string> tempFiles = new();
                JsonElement files = commitObject.GetProperty("files");
                foreach (JsonElement file in files.EnumerateArray())
                {
                    tempFiles.Add(file.GetProperty("filename").GetString()!);
                }
                commit.ModifiedFiles = tempFiles;
                return commit;
            }
            else
            {
                return null;
            }
        }

        public GitReference GetReference() => new(GitReferenceKind.Repository, $"{Owner}/{Name}");
        

        public bool TryGetCommit(uint HeadOffset, out ICommit? Commit)
        {
            var commit = GetCommit(HeadOffset);
            if (commit != null)
            {
                Commit = commit;
                return true;
            }

            Commit = null;
            return false;
        }

        public bool TryGetCommitByRef(string Reference, out ICommit? Commit)
        {
            var commit = GetCommitByRef(Reference);
            if (commit != null)
            {
                Commit = commit;
                return true;
            }

            Commit = null;
            return false;
        }
    }
}
