using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Threading.Tasks;
using Moq;
using Newtonsoft.Json.Linq;
using Should;
using WebApiBook.IssueTrackerApi.Models;
using Xbehave;

namespace WebApiBook.IssueTrackerApp.AcceptanceTests.Features
{
    public class UpdatingIssues : IssuesFeature
    {
        private readonly Uri _uriIssue1 = new Uri("http://localhost/issue/1");

        [Scenario]
        public void UpdatingAnIssue(Issue fakeIssue, string title)
        {
            "Mając istniejące zgłoszenie błędu".
                f(() =>
                {
                    fakeIssue = FakeIssues.FirstOrDefault();
                    title = fakeIssue.Title;
                    MockIssueStore.Setup(i => i.FindAsync("1")).Returns(Task.FromResult(fakeIssue));
                    MockIssueStore.Setup(i => i.UpdateAsync(It.IsAny<Issue>())).Returns(Task.FromResult(""));
                });
            "Kiedy żądanie PATCH zostanie wykonane".
                f(() =>
                {
                    dynamic issue = new JObject();
                    issue.description = "Updated description";
                    Request.Method = new HttpMethod("PATCH");
                    Request.RequestUri = _uriIssue1;
                    Request.Content = new ObjectContent<dynamic>(issue, new JsonMediaTypeFormatter());
                    Response = Client.SendAsync(Request).Result;
                });
            "Wtedy będzie zwrócony kod stanu '200 OK'".
                f(() => Response.StatusCode.ShouldEqual(HttpStatusCode.OK));
            "Wtedy zgłoszenie błędu powinno być uaktualnione".
                f(() => MockIssueStore.Verify(i => i.UpdateAsync(It.IsAny<Issue>())));
            "Wtedy opis powinien być uaktualniony".
                f(() => fakeIssue.Description.ShouldEqual("Updated description"));
            "Wtedy tytuł nie powinien ulec zmianie".
                f(() => fakeIssue.Title.ShouldEqual(title));
        }

        [Scenario]
        public void UpdatingAnIssueThatDoesNotExist()
        {
            "Mając nieistniejące zgłoszenie błędu".
                f(() => MockIssueStore.Setup(i => i.FindAsync("1")).Returns(Task.FromResult((Issue)null)));
            "Kiedy żądanie PATCH zostanie wykonane".
                f(() =>
                {
                    Request.Method = new HttpMethod("PATCH");
                    Request.RequestUri = _uriIssue1;
                    Request.Content = new ObjectContent<dynamic>(new JObject(), new JsonMediaTypeFormatter());
                    Response = Client.SendAsync(Request).Result;
                });
            "Wtedy będzie zwrócony kod stanu '404 Not Found'".
                f(() => Response.StatusCode.ShouldEqual(HttpStatusCode.NotFound));
        }
    }
}
