﻿using System;
using System.Linq;
using Cresce.Datasources.Sql;
using Cresce.Models;
using NUnit.Framework;

namespace Cresce.Business.Tests.Integration.Sql
{
    [TestFixture]
    internal class InvoiceRepositoryTests : SqlTests
    {
        private SqlInvoiceRepository _repository;
        private Patient _patient;

        public InvoiceRepositoryTests()
        {
            _repository = new SqlInvoiceRepository(this);
        }

        [SetUp]
        public void CreateResources()
        {
            _patient = Utils.SavePatient();
        }
        
        [Test]
        public void When_deleting_an_invoice_it_should_be_removed_from_the_database()
        {
            // Arrange
            var invoice = Utils.SaveInvoice(_patient);

            // Act
            _repository.Delete(invoice.Id);


            // Assert
            var invoiceById = _repository.GetById(invoice.Id);
            Assert.That(invoiceById, Is.Null);
        }

        [Test]
        public void When_deleting_an_invoice_linked_with_an_appointment_it_should_be_removed_from_the_database()
        {
            // Arrange
            var invoice = Utils.SaveInvoice(_patient);
            Utils.SaveAppointment(Utils.SaveUser(), _patient, Utils.SaveService(), new DateTime(), invoiceId: invoice.Id);   

            // Act
            _repository.Delete(invoice.Id);


            // Assert
            var invoiceById = _repository.GetById(invoice.Id);
            Assert.That(invoiceById, Is.Null);
        }

        [Test]
        public void When_getting_an_invoice_by_id_it_should_return_the_previously_saved_invoice()
        {
            // Arrange
            var invoice = Utils.SaveInvoice(_patient);

            // Act
            var result = _repository.GetById(invoice.Id);

            // Assert
            Assert.That(result, Is.Not.Null);
        }

        [Test]
        public void When_getting_an_invoice_by_id_it_should_return_specific_information()
        {
            // Arrange
            var invoice = Utils.SaveInvoice(
                _patient,
                date: new DateTime(2017, 10, 23)
            );

            // Act
            var result = _repository.GetById(invoice.Id);

            // Assert
            Assert.That(result, Is.Not.Null);
            Assert.That(result.PatientId, Is.EqualTo(_patient.Id));
            Assert.That(result.Date, Is.EqualTo(new DateTime(2017, 10, 23)));
            Assert.That(result.Description, Is.EqualTo("some description"));
            Assert.That(result.Value, Is.EqualTo(23.4));
        }

        [Test]
        public void When_getting_a_non_existing_invoice_by_id_it_should_return_null()
        {
            // Arrange
            var invoiceId = "-1";

            // Act
            var result = _repository.GetById(invoiceId);

            // Assert
            Assert.That(result, Is.Null);
        }

        [Test]
        public void When_getting_an_invoices_for_patient_id_it_should_return_only_invoices_of_that_patient()
        {
            // Arrange
            Utils.SaveInvoice(_patient, date: new DateTime(2017, 10, 23));
            Utils.SaveInvoice(Utils.SavePatient("2"), date: new DateTime(2017, 10, 23));
            
            // Act
            var result = _repository.GetInvoices(_patient.Id).ToList();

            // Assert
            Assert.That(result.Count, Is.EqualTo(1));
        }

        [Test]
        public void When_getting_all_invoices_it_should_return_all_persisted_invoices()
        {
            // Arrange
            Utils.SaveInvoice(_patient, date: new DateTime(2017, 10, 23));
            Utils.SaveInvoice(Utils.SavePatient("2"), date: new DateTime(2017, 10, 23));
            
            // Act
            var result = _repository.GetInvoices().ToList();

            // Assert
            Assert.That(result.Count, Is.EqualTo(2));
        }
    }
}
