using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using RecruitmentTesting.Api.Models;

namespace RecruitmentTesting.Api.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                RunAsync().Wait();
            }
            catch (AggregateException ex)
            {
                Console.WriteLine("An exception happened:");
                Console.WriteLine(ex.InnerException);
            }

            Console.WriteLine("End");
            Console.ReadLine();
        }

        private static async Task RunAsync()
        {
            using (ApiWrapper wrapper = new ApiWrapper())
            {
                await Authenticate(wrapper);

                IEnumerable<Test> tests = await GetAllTests(wrapper);

                Test test = ChooseTest(tests);
                if (test == null)
                    return;

                await GetCandidatesForTest(wrapper, test);

                string[] candidateEmails = ChooseCandidatesForInviting(test);
                if (candidateEmails == null)
                    return;

                await InviteCandidates(wrapper, test, candidateEmails);
            }
        }

        private static async Task Authenticate(ApiWrapper wrapper)
        {
            Console.WriteLine("Enter user email:");
            string email = Console.ReadLine();
            Console.WriteLine("Enter api password:");
            string apiPassword = Console.ReadLine();

            await wrapper.Authenticate(email, apiPassword);
        }

        private static async Task<IEnumerable<Test>> GetAllTests(ApiWrapper wrapper)
        {
            IEnumerable<Test> tests = await wrapper.GetTestsAsync();

            Console.WriteLine("User has the following tests:");
            foreach (var t in tests)
            {
                Console.WriteLine($"Test: Id: {t.Id}, Name: {t.Name}");
            }

            return tests;
        }

        private static Test ChooseTest(IEnumerable<Test> tests)
        {
            Console.WriteLine("Enter test id to get candidates for a test or empty line to finish:");
            string testIdLine = Console.ReadLine();
            if (String.IsNullOrEmpty(testIdLine))
                return null;

            int testId = int.Parse(testIdLine);
            return tests.Single(x => x.Id == testId);
        }

        private static async Task GetCandidatesForTest(ApiWrapper wrapper, Test test)
        {
            IEnumerable<Candidate> candidates = await wrapper.GetCandidatesAsync(test.Id);
            Console.WriteLine($"Test '{test.Name}' has the following candidates:");
            foreach (Candidate candidate in candidates)
            {
                Console.WriteLine($"Candidate: Id: {candidate.Id}, Email: {candidate.Email}, Report: {candidate.ReportUrl}");
            }
        }

        private static string[] ChooseCandidatesForInviting(Test test)
        {
            Console.WriteLine($"Enter candidate emails (comma/semicolon separated list) to invite to the test {test.Name} or empty line to finish:");
            string candidateEmailsLine = Console.ReadLine();
            if (String.IsNullOrEmpty(candidateEmailsLine))
                return null;

            return candidateEmailsLine.Split(',', ';');
        }

        private static async Task InviteCandidates(ApiWrapper wrapper, Test test, string[] candidateEmails)
        {
            InviteCandidatesResult result = await wrapper.InviteCandidate(test.Id, candidateEmails);

            if (result.Successful != null)
            {
                Console.WriteLine("Successful invitations: ");
                foreach (string successful in result.Successful)
                {
                    Console.WriteLine(successful);
                }
            }

            if (result.Unsuccessful != null)
            {
                Console.WriteLine("Unsuccessful invitations: ");
                foreach (string unsuccessful in result.Unsuccessful)
                {
                    Console.WriteLine(unsuccessful);
                }
            }
        }
    }
}
