﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VagueBook.Infrastructure;

namespace VagueBook.Application.Domain.Person
{
    public class PersonLogic
    {
        public PersonEntity Create(
            Guid personId,
            string firstName, 
            string lastName, 
            string emailOrMobile, 
            string password, 
            int year,
            int month,
            int day,
            string gender)
        {
            // Throw an exception if the first name is invalid.
            if (string.IsNullOrEmpty(firstName) || firstName.Length > 100)
            {
                throw new DomainException(DomainExceptionType.BadRequest, Constants.InvalidFirstName);
            }

            // Throw an exception if the last name is invalid.
            if (string.IsNullOrEmpty(lastName) || lastName.Length > 100)
            {
                throw new DomainException(DomainExceptionType.BadRequest, Constants.InvalidLastName);
            }
            
            string email = null;
            string mobile = null;
            if (emailOrMobile != null)
            {
                // Is it all digits?
                if (emailOrMobile.All(c => char.IsDigit(c)))
                {
                    // If so, assume it's a phone.
                    mobile = emailOrMobile;
                    if (mobile.Length != 10)
                    {
                        throw new DomainException(DomainExceptionType.BadRequest, Constants.InvalidMobile);
                    }
                }
                else if (emailOrMobile.Contains("@"))
                {
                    email = emailOrMobile;
                    // Throw an exception if the email is invalid.
                    if (email.Length > 100)
                    {
                        throw new DomainException(DomainExceptionType.BadRequest, Constants.InvalidEmailOrMobile);
                    }
                }
            }

            // Throw an exception if the emailOrMobile is neither an email nor a mobile.
            if (email == null && mobile == null)
            {
                throw new DomainException(DomainExceptionType.BadRequest, Constants.InvalidEmailOrMobile);
            }

            // Throw an exception if the birthday is invalid.
            var validBirthday = false;
            var birthdayString = $"{year.ToString("D4")}-{month.ToString("D2")}-{day.ToString("D2")}";
            DateTime birthday;
            if (DateTime.TryParse(birthdayString, out birthday))
            {
                birthday = DateTime.SpecifyKind(birthday, DateTimeKind.Utc);
                if (birthday <= DateTime.UtcNow.Date &&
                    birthday.Subtract(birthday.Date) == new TimeSpan(0))
                {
                    validBirthday = true;
                }
            }
            if (!validBirthday)
            {
                throw new DomainException(DomainExceptionType.BadRequest, Constants.InvalidBirthday);
            }

            // Throw an exception if the password is invalid.
            if (string.IsNullOrEmpty(password) || password.Length > 16)
            {
                throw new DomainException(DomainExceptionType.BadRequest, Constants.InvalidPassword);
            }

            // Throw an exception if the password is invalid.
            var validGenders = new[] { "Male", "Female" };
            if (!validGenders.Contains(gender))
            {
                throw new DomainException(DomainExceptionType.BadRequest, Constants.InvalidGender);
            }

            var person = new PersonEntity();

            person.PersonId = personId;
            person.FirstName = firstName;
            person.LastName = lastName;
            person.Email = email;
            person.Mobile = mobile;
            person.Birthday = birthday;
            person.Gender = gender;

            return person;
        }
    }
}
