using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Schokotaler.Api.Common;
using Schokotaler.Api.Models;
using Schokotaler.Api.Models.Controllers.Accounts;
using Schokotaler.Api.Producers;
using Schokotaler.Api.Repository;

namespace Schokotaler.Api.Controllers {
    [Route("/v1/accounts/{aid}/credit_cards")]
    public class CreditCardsController : Controller {
        private readonly ICreditCardRepository _ccRepo;
        private readonly CreditCardProducer _ccProd;
        private readonly IAccountRepository _accRepo;
        private readonly ILogger _logger;

        public CreditCardsController(ICreditCardRepository ccRepo, CreditCardProducer ccProd, IAccountRepository accRepo, ILogger<CreditCardsController> logger) {
            _ccRepo = ccRepo;
            _ccProd = ccProd;
            _accRepo = accRepo;
            _logger = logger;
        }

        [Authorize(Roles = "user")]
        [HttpPost]
        public IActionResult Create(long aid, [FromBody] CreditCardPatch model) {
            if (!(bool)HttpContext.Items["Active"]) {
                _logger.LogError(LoggingEvents.CreateItemError, "Unauthorized.");
                return Unauthorized();
            }
            long uid = (long)HttpContext.Items["UID"];
            if (!model.IsValid()) return BadRequest();

            if (!_accRepo.UserOwnsAccount(aid, uid)) return NotFound();

            CreditCard cc = _ccProd.Create(model, aid);
            try {
                _ccRepo.Add(cc);
            } catch (DbUpdateException e) {
                _logger.LogError(LoggingEvents.CreateItemError, e, "Error creating credit card");
            }
            return Created("GetCreditCard", new { Id = cc.Id });
        }

        [Authorize(Roles = "user")]
        [HttpGet("{id}", Name = "GetCreditCard")]
        public IActionResult Get(long aid, long id) {
            if (!(bool)HttpContext.Items["Active"]) {
                _logger.LogError(LoggingEvents.GetItemError, "Unauthorized.");
                return Unauthorized();
            }
            long uid = (long)HttpContext.Items["UID"];

            if (!_accRepo.UserOwnsAccount(aid, uid)) {
                _logger.LogError(LoggingEvents.GetItemError, "Account {aid} either not owned by user {uid} or doesn't exist at all.", aid, uid);
                return NotFound();
            }

            CreditCard cc = _ccRepo.GetWithUserId(id, uid);
            if (cc == null) {
                _logger.LogError(LoggingEvents.GetItemError, "Error getting cc {id}.", id);
                return Forbid();
            }

            return Ok(new {
                Id = cc.Id,
                Limit = cc.Limit,
                PayDay = cc.PayDay,
                PayLimit = cc.PayLimit
            });
        }

        [Authorize(Roles = "user")]
        [HttpPut("{id}")]
        public IActionResult Patch(long aid, long id, [FromBody] CreditCardPatch patch) {
            if (!(bool)HttpContext.Items["Active"]) {
                _logger.LogError(LoggingEvents.UpdateItemError, "Unauthorized.");
                return Unauthorized();
            }
            long uid = (long)HttpContext.Items["UID"];

            if (!patch.IsValid()) return BadRequest();

            if (!_accRepo.UserOwnsAccount(aid, uid)) {
                _logger.LogError(LoggingEvents.UpdateItemError, "Account {aid} either not owned by {uid} or doesn't exist at all.", aid, uid);
                return NotFound();
            }

            CreditCard cc = _ccRepo.GetWithUserId(id, uid);
            if (cc == null) {
                _logger.LogError(LoggingEvents.UpdateItemError, "Error getting cc {id}.", id);
                return Forbid();
            }

            _ccProd.Patch(cc, patch);
            _ccRepo.Save();

            return Ok();
        }
    }
}