using JobsJobsJobs.Server.Data;
using JobsJobsJobs.Shared;
using JobsJobsJobs.Shared.Api;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using NodaTime;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace JobsJobsJobs.Server.Areas.Api.Controllers
{
    /// <summary>
    /// API controller for employment profile information
    /// </summary>
    [Route("api/[controller]")]
    [Authorize]
    [ApiController]
    public class ProfileController : ControllerBase
    {
        /// <summary>
        /// The database connection
        /// </summary>
        private readonly NpgsqlConnection _db;

        /// <summary>
        /// The NodaTime clock instance
        /// </summary>
        private readonly IClock _clock;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="db">The database connection to use for this request</param>
        public ProfileController(NpgsqlConnection db, IClock clock)
        {
            _db = db;
            _clock = clock;
        }

        /// <summary>
        /// The current citizen ID
        /// </summary>
        private CitizenId CurrentCitizenId => CitizenId.Parse(User.FindFirst(ClaimTypes.NameIdentifier)!.Value);

        [HttpGet("")]
        public async Task<IActionResult> Get()
        {
            await _db.OpenAsync();
            var profile = await _db.FindProfileByCitizen(CurrentCitizenId);
            return profile == null ? NoContent() : Ok(profile);
        }

        [HttpPost("save")]
        public async Task<IActionResult> Save(ProfileForm form)
        {
            await _db.OpenAsync();
            var txn = await _db.BeginTransactionAsync();

            // Profile
            var existing = await _db.FindProfileByCitizen(CurrentCitizenId);
            var profile = existing == null
                ? new Profile(CurrentCitizenId, form.IsSeekingEmployment, form.IsPublic,
                    ContinentId.Parse(form.ContinentId), form.Region, form.RemoteWork, form.FullTime,
                    new MarkdownString(form.Biography), _clock.GetCurrentInstant(),
                    string.IsNullOrEmpty(form.Experience) ? null : new MarkdownString(form.Experience))
                : existing with
                {
                    SeekingEmployment = form.IsSeekingEmployment,
                    IsPublic = form.IsPublic,
                    ContinentId = ContinentId.Parse(form.ContinentId),
                    Region = form.Region,
                    RemoteWork = form.RemoteWork,
                    FullTime = form.FullTime,
                    Biography = new MarkdownString(form.Biography),
                    LastUpdatedOn = _clock.GetCurrentInstant(),
                    Experience = string.IsNullOrEmpty(form.Experience) ? null : new MarkdownString(form.Experience)
                };
            await _db.SaveProfile(profile);

            // Skills
            var skills = new List<Skill>();
            foreach (var skill in form.Skills) {
                skills.Add(new Skill(skill.Id.StartsWith("new") ? await SkillId.Create() : SkillId.Parse(skill.Id),
                    CurrentCitizenId, skill.Description, string.IsNullOrEmpty(skill.Notes) ? null : skill.Notes));
            }
            
            foreach (var skill in skills) await _db.SaveSkill(skill);
            await _db.DeleteMissingSkills(CurrentCitizenId, skills.Select(s => s.Id));

            await txn.CommitAsync();
            return Ok();
        }

        [HttpGet("skills")]
        public async Task<IActionResult> GetSkills()
        {
            await _db.OpenAsync();
            return Ok(await _db.FindSkillsByCitizen(CurrentCitizenId));
        }
    }
}