﻿using System.Collections.Generic;
using System.Linq;
using Business.Logic.Exceptions;
using Business.Logic.Objects;
using Business.Logic.Queries;
using Business.Logic.Repositories;
using FakeItEasy;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace DFWOutdoorsTests.Queries
{
    [TestClass]
    public class GetAllCampsiteLocationsTests
    {
        private IRepository fakeRepository;
        private const string FakeUrl = "Test";

        [TestMethod]
        public void Execute_ShouldCallGetAll()
        {
            var sut = CreateGetAllCampsites();

            sut.Url = FakeUrl;

            sut.Execute();

            A.CallTo(() => fakeRepository.GetAll<CampSiteLocations>(A<string>._)).MustHaveHappened(Repeated.Exactly.Once);
        }

        [TestMethod]
        public void Execute_ShouldReturnAnEmtptyCampsiteLocationListIfNoneAreProvided()
        {
            var sut = CreateGetAllCampsites();

            sut.Url = FakeUrl;

            var result = sut.Execute().OfType<CampSiteLocation>().ToList();;

            A.CallTo(() => fakeRepository.GetAll<CampSiteLocations>(A<string>._)).Returns(new List<CampSiteLocations>());

            result.Count.Should().Be(0);
        }

        [TestMethod]
        public void Execute_ShouldReturnEmptyArrayIfDataIsCorruptAndParametersAreNull()
        {
            var fakeContainer = new List<CampSiteLocations> {new CampSiteLocations()};

            var sut = CreateGetAllCampsites();

            sut.Url = FakeUrl;

            A.CallTo(() => fakeRepository.GetAll<CampSiteLocations>(A<string>._)).Returns(fakeContainer);

            var result = sut.Execute().OfType<CampSiteLocation>().ToList();

            result.Count.Should().Be(0);
        }

        [TestMethod]
        public void Execute_ShouldReturnValidListIfAvailable()
        {
            var fakeContainer = new List<CampSiteLocations>();
            var fakeData = new[]{new CampSiteLocation(), new CampSiteLocation(), new CampSiteLocation()};

            fakeContainer.Add(new CampSiteLocations());

            fakeContainer[0].CampSiteLocation = fakeData;

            var sut = CreateGetAllCampsites();

            sut.Url = FakeUrl;

            A.CallTo(() => fakeRepository.GetAll<CampSiteLocations>(A<string>._)).Returns(fakeContainer);

            var result = sut.Execute().OfType<CampSiteLocation>().ToList(); 

            result.Count.Should().Be(3);
        }

        [TestMethod]
        [ExpectedException(typeof(ParameterNotFoundException))]
        public void Execute_ShouldThrowParameterNotFoundExceptionWhenParametersHaveNotBeenSet()
        {
            var sut = CreateGetAllCampsites();

            sut.Execute();
        }

        private GetAllCampsiteLocations CreateGetAllCampsites()
        {
            fakeRepository = A.Fake<IRepository>();

            var campsiteQuery = new GetAllCampsiteLocations { GetRepository = () => fakeRepository };

            return campsiteQuery;
        }
    }
}
