using BoredCareers.Entities;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;

namespace BoredCareers.Services.DatabaseService {
    public partial class DatabaseService {

        public async Task<Resume[]> GetResumes(int AccountID) {
            List<Resume> resumes = new List<Resume>();
            using (MySqlConnection connection = GetConnection()) {
                connection.Open();
                string command = @"
                SELECT *
                FROM Resume
                WHERE AccountID = @AccountID;
                ";

                MySqlCommand cmd = new MySqlCommand(command, connection);
                cmd.Parameters.AddWithValue("@AccountID", AccountID);

                using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
                    while (await reader.ReadAsync()) {
                        if (reader == null) {
                            break;
                        }

                        int _id = reader.GetInt32("ID");
                        int _accountid = reader.GetInt32("AccountID");
                        string _name = reader.GetString("Name");
                        string _field = reader.GetString("Field");
                        string _email = reader.GetString("Email");
                        string _phonenumber = reader.GetString("PhoneNumber");
                        string _postalcode = reader.GetString("PostalCode");
                        string _country = reader.GetString("Country");
                        string _state = reader.GetString("StateOrRegion");
                        string _city = reader.GetString("City");
                        bool _isactive = reader.GetBoolean("IsActive");

                        resumes.Add( new Resume() {
                            ID = _id,
                            AccountID = _accountid,
                            Name = _name,
                            Field = _field,
                            Email = _email,
                            PhoneNumber = _phonenumber,
                            PostalCode = _postalcode,
                            Country = _country,
                            StateOrRegion = _state,
                            City = _city,
                            IsActive = _isactive
                        } );
                    }
                }
            }
            return resumes.ToArray();
        }

        public async Task<Resume?> GetResume(int ResumeID) {
            // Open connections for multi-threaded request
            MySqlConnection resumeConnection = GetConnection();
            MySqlConnection ResumeExperienceConnection = GetConnection();
            MySqlConnection ResumeExperienceBulletConnection = GetConnection();
            MySqlConnection ResumeMilitaryConnection = GetConnection();
            MySqlConnection ResumeMilitaryBulletConnection = GetConnection();
            MySqlConnection ResumeEducationConnection = GetConnection();
            MySqlConnection ResumeSkillConnection = GetConnection();
            MySqlConnection ResumeLanguageConnection = GetConnection();
            MySqlConnection ResumeCertificationConnection = GetConnection();
            MySqlConnection ResumeProjectConnection = GetConnection();

            // Open the connections
            Task resumeopen = resumeConnection.OpenAsync();
            Task resumeexperienceopen = ResumeExperienceConnection.OpenAsync();
            Task resumeexperiencebulletopen = ResumeExperienceBulletConnection.OpenAsync();
            Task resumemilitaryopen = ResumeMilitaryConnection.OpenAsync();
            Task resumemilitarybulletopen = ResumeMilitaryBulletConnection.OpenAsync();
            Task resumeeducationopen = ResumeEducationConnection.OpenAsync();
            Task resumeskillopen = ResumeSkillConnection.OpenAsync();
            Task resumelanguageopen = ResumeLanguageConnection.OpenAsync();
            Task resumecertifcationopen = ResumeCertificationConnection.OpenAsync();
            Task resumeprojectopen = ResumeProjectConnection.OpenAsync();

            // Wait for all the connections to open
            await Task.WhenAll(resumeopen, resumeexperienceopen, resumeexperiencebulletopen, resumemilitaryopen, resumemilitarybulletopen,
                resumeeducationopen, resumeskillopen, resumelanguageopen, resumecertifcationopen, resumeprojectopen);

            // Setup the commands for the connections
            MySqlCommand resumeCommand = new MySqlCommand("SELECT * FROM Resume WHERE ID = @ResumeID;", resumeConnection);
            MySqlCommand ResumeExperienceCommand = new MySqlCommand("SELECT * FROM ResumeExperience WHERE ResumeID = @ResumeID;", ResumeExperienceConnection);
            MySqlCommand ResumeExperienceBulletCommand = new MySqlCommand("SELECT * FROM ResumeExperienceBullet WHERE ResumeID = @ResumeID;", ResumeExperienceBulletConnection);
            MySqlCommand ResumeMilitaryCommand = new MySqlCommand("SELECT * FROM ResumeMilitary WHERE ResumeID = @ResumeID;", ResumeMilitaryConnection);
            MySqlCommand ResumeMilitaryBulletCommand = new MySqlCommand("SELECT * FROM ResumeMilitaryBullet WHERE ResumeID = @ResumeID", ResumeMilitaryBulletConnection);
            MySqlCommand ResumeEducationCommand = new MySqlCommand("SELECT * FROM ResumeEducation WHERE ResumeID = @ResumeID;", ResumeEducationConnection);
            MySqlCommand ResumeSkillCommand = new MySqlCommand("SELECT * FROM ResumeSkill WHERE ResumeID = @ResumeID;", ResumeSkillConnection);
            MySqlCommand ResumeLanguageCommand = new MySqlCommand("SELECT * FROM ResumeLanguage WHERE ResumeID = @ResumeID;", ResumeLanguageConnection);
            MySqlCommand ResumeCertificationCommand = new MySqlCommand("SELECT * FROM ResumeCertification WHERE ResumeID = @ResumeID;", ResumeCertificationConnection);
            MySqlCommand ResumeProjectCommand = new MySqlCommand("SELECT * FROM ResumeProject WHERE ResumeID = @ResumeID;", ResumeProjectConnection);

            // Add parameters to the commands
            resumeCommand.Parameters.AddWithValue("@ResumeID", ResumeID);
            ResumeExperienceCommand.Parameters.AddWithValue("@ResumeID", ResumeID);
            ResumeExperienceBulletCommand.Parameters.AddWithValue("@ResumeID", ResumeID);
            ResumeMilitaryCommand.Parameters.AddWithValue("@ResumeID", ResumeID);
            ResumeMilitaryBulletCommand.Parameters.AddWithValue("@ResumeID", ResumeID);
            ResumeEducationCommand.Parameters.AddWithValue("@ResumeID", ResumeID);
            ResumeSkillCommand.Parameters.AddWithValue("@ResumeID", ResumeID);
            ResumeLanguageCommand.Parameters.AddWithValue("@ResumeID", ResumeID);
            ResumeCertificationCommand.Parameters.AddWithValue("@ResumeID", ResumeID);
            ResumeProjectCommand.Parameters.AddWithValue("@ResumeID", ResumeID);

            // Run the commands
            Task<DbDataReader> ResumeReader = resumeCommand.ExecuteReaderAsync();
            Task<DbDataReader> ResumeExperienceReader = ResumeExperienceCommand.ExecuteReaderAsync();
            Task<DbDataReader> ResumeExperienceBulletReader = ResumeExperienceBulletCommand.ExecuteReaderAsync();
            Task<DbDataReader> ResumeMilitaryReader = ResumeMilitaryCommand.ExecuteReaderAsync();
            Task<DbDataReader> ResumeMilitaryBulletReader = ResumeMilitaryBulletCommand.ExecuteReaderAsync();
            Task<DbDataReader> ResumeEducationReader = ResumeEducationCommand.ExecuteReaderAsync();
            Task<DbDataReader> ResumeSkillReader = ResumeSkillCommand.ExecuteReaderAsync();
            Task<DbDataReader> ResumeLanguageReader = ResumeLanguageCommand.ExecuteReaderAsync();
            Task<DbDataReader> ResumeCertificationReader = ResumeCertificationCommand.ExecuteReaderAsync();
            Task<DbDataReader> ResumeProjectReader = ResumeProjectCommand.ExecuteReaderAsync();

            // Wait for all the commands to process
            await Task.WhenAll(ResumeReader, ResumeExperienceReader, ResumeExperienceBulletReader, ResumeMilitaryReader, ResumeMilitaryBulletReader,
                ResumeEducationReader, ResumeSkillReader, ResumeLanguageReader, ResumeCertificationReader, ResumeProjectReader);

            // Get Resume
            Resume? resume = await GetResume( await ResumeReader );
            if (resume != null) {

                // Get Resume Parts
                ResumeExperience[] experience = await GetResumeExperience(await ResumeExperienceReader);
                ResumeExperienceBullet[] experienceBullets = await GetResumeExperienceBullets(await ResumeExperienceBulletReader);
                ResumeMilitary? military = await GetResumeMilitary(await ResumeMilitaryReader);
                ResumeMilitaryBullet[] militaryBullets = await GetResumeMilitaryBullets(await ResumeMilitaryBulletReader);
                ResumeEducation[] education = await GetResumeEducation(await ResumeEducationReader);
                ResumeSkill[] skills = await GetResumeSkills(await ResumeSkillReader);
                ResumeLanguage[] languages = await GetResumeLanguages(await ResumeLanguageReader);
                ResumeCertification[] certs = await GetResumeCertification(await ResumeCertificationReader);
                ResumeProject[] projects = await GetResumeProjects(await ResumeProjectReader);

                // Split into grouped lists and add to experience
                Dictionary<int, ResumeExperienceBullet[]> groupedExperienceBullets = experienceBullets.GroupBy(b => b.ResumeExperienceID).ToDictionary(g => g.Key, g => g.ToArray());
                foreach (ResumeExperience cur in experience) {
                    cur.ExperienceBullets = groupedExperienceBullets[cur.ID];
                }

                // Add the parts to the resume
                if (military != null) {
                    military.MillitaryBullets = militaryBullets;
                    resume.Millitary = military;
                }
                resume.Experience = experience;
                resume.Educations = education;
                resume.Skills = skills;
                resume.Languages = languages;
                resume.Certification = certs;
                resume.Projects = projects;

                return resume;
            }
            return null;
        }

        public async Task SetResume(Resume resume) {

            // Open connections for multi-threaded request
            MySqlConnection resumeConnection = GetConnection();
            MySqlConnection ResumeExperienceConnection = GetConnection();
            MySqlConnection ResumeExperienceBulletConnection = GetConnection();
            MySqlConnection ResumeMilitaryConnection = GetConnection();
            MySqlConnection ResumeMilitaryBulletConnection = GetConnection();
            MySqlConnection ResumeEducationConnection = GetConnection();
            MySqlConnection ResumeSkillConnection = GetConnection();
            MySqlConnection ResumeLanguageConnection = GetConnection();
            MySqlConnection ResumeCertificationConnection = GetConnection();
            MySqlConnection ResumeProjectConnection = GetConnection();

            // Open the connections
            Task resumeopen = resumeConnection.OpenAsync();
            Task resumeexperienceopen = ResumeExperienceConnection.OpenAsync();
            Task resumeexperiencebulletopen = ResumeExperienceBulletConnection.OpenAsync();
            Task resumemilitaryopen = ResumeMilitaryConnection.OpenAsync();
            Task resumemilitarybulletopen = ResumeMilitaryBulletConnection.OpenAsync();
            Task resumeeducationopen = ResumeEducationConnection.OpenAsync();
            Task resumeskillopen = ResumeSkillConnection.OpenAsync();
            Task resumelanguageopen = ResumeLanguageConnection.OpenAsync();
            Task resumecertifcationopen = ResumeCertificationConnection.OpenAsync();
            Task resumeprojectopen = ResumeProjectConnection.OpenAsync();

            // Wait for all the connections to open
            await Task.WhenAll(resumeopen, resumeexperienceopen, resumeexperiencebulletopen, resumemilitaryopen, resumemilitarybulletopen,
                resumeeducationopen, resumeskillopen, resumelanguageopen, resumecertifcationopen, resumeprojectopen);

            // Get all the experience bullets and run all the updates
            List<ResumeExperienceBullet> bullets = new List<ResumeExperienceBullet>();
            foreach (ResumeExperience cur in resume.Experience) {
                foreach (ResumeExperienceBullet bullet in cur.ExperienceBullets) {
                    bullets.Add(bullet);
                }
            }
            Task ResumeExperienceBulletTask = SetResumeExperienceBullets(ResumeExperienceBulletConnection, bullets.ToArray());
            Task ResumeTask = SetResume(resumeConnection, resume);
            Task ResumeExperienceTask = SetResumeExperience(ResumeExperienceConnection, resume.Experience);
            Task ResumeMilitaryTask = SetResumeMilitary(ResumeMilitaryConnection, resume.Millitary);
            Task ResumeMilitaryBulletTask = SetResumeMilitaryBullets(ResumeMilitaryBulletConnection, resume.Millitary.MillitaryBullets);
            Task ResumeEducationTask = SetResumeEducation(ResumeEducationConnection, resume.Educations);
            Task ResumeSkllTask = SetResumeSkills(ResumeSkillConnection, resume.Skills);
            Task ResumeLanguageTask = SetResumeLanguages(ResumeLanguageConnection, resume.Languages);
            Task ResumeCertTask = SetResumeCertification(ResumeCertificationConnection, resume.Certification);
            Task ResumeProjectTask = SetResumeProjects(ResumeProjectConnection, resume.Projects);

            // Allow update to finish before closing process
            await Task.WhenAll(ResumeTask, ResumeExperienceTask, ResumeExperienceBulletTask, ResumeMilitaryTask, ResumeMilitaryBulletTask,
                ResumeEducationTask, ResumeSkllTask, ResumeLanguageTask, ResumeCertTask, ResumeProjectTask);            

        }

        public async Task DeleteResume( int ResumeID ) {
            using( MySqlConnection connection = GetConnection() ) {
                MySqlCommand cmd;
                connection.Open();

                string command = @"
                DELETE FROM Resume WHERE ID = @ID;
                ";
                cmd = new MySqlCommand( command, connection );
                cmd.Parameters.AddWithValue("@ID", ResumeID);

                await cmd.ExecuteNonQueryAsync();
            }
        }

    }
}
