using Knoks.Api.Controllers.Base;
using Knoks.Api.Entities;
using Knoks.Api.Filters;
using Knoks.Core.Data.Interfaces;
using Knoks.Core.Entities;
using Knoks.Core.Entities.Args;
using Knoks.Core.Logic.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
using System.Threading.Tasks;

namespace Knoks.Api.Controllers
{
    [Route("v1/[controller]")]
    public class KnokController : UserController
    {
        #region Fields
        private readonly IKnokManager _knokManager;
        private readonly IAccountTransactionManager _accountTransManager;
        private readonly IUserManager _userManager;
        private readonly IAccountDao _accountDao;
        private readonly IKnokSettings _settings;
        private readonly IExchangeManager _exchangeManager;
        private readonly IKnokPricelManager _knokPriceManager;
        #endregion

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="knokManager"></param>
        /// <param name="accountTransManager"></param>
        /// <param name="userManager"></param>
        /// <param name="accountDao"></param>
        /// <param name="generalManager"></param>
        /// <param name="exchangeManager"></param>
        /// <param name="settings"></param>
        public KnokController(IKnokManager knokManager, IAccountTransactionManager accountTransManager, IUserManager userManager,
            IAccountDao accountDao, IExchangeManager exchangeManager, IKnokSettings settings, IKnokPricelManager knokPriceManager)
        {
            _knokManager = knokManager;
            _accountTransManager = accountTransManager;
            _userManager = userManager;
            _accountDao = accountDao;
            _exchangeManager = exchangeManager;
            _knokPriceManager = knokPriceManager;
            _settings = settings;
        }

        [HttpPost("GetKnokPrice")]
        [ApiValidation]
        public async Task<decimal> KnokPriceCalc([FromBody]CreateKnokArgs args)
        {
            return await _knokPriceManager.TotalPrice(args, UserId);
        }

        [HttpPost("CreateKnok")]
        [ApiValidation]
        public async Task<Knok> CreateKnok([FromBody]CreateKnokArgs args)
        {
            //Get choosen pair rate and save it to live chart data for the initial rate chart drawing
            var tickerData = await this._exchangeManager.GetTickerData(args.ExchangeId, args.Currency1, args.Currency2);
            var currentPrice = tickerData?.Close ?? 0;
            //Create knok
            var knokRate = _knokManager.KnokRatingCalc(args);
            args.Rate = knokRate.Total;
            args.PotentialProfitValue = knokRate.PotentialProfitValue / 100;
            args.PotentialProfit = knokRate.PotentialProfit;
            var result = await _knokManager.Process(args, currentPrice);
            //Publish knok
            var userAccounts = await _accountDao.GetUserAccounts(UserId);
            return await _knokManager.PublishKnok(result.KnokId.Value, userAccounts.User, userAccounts.Accounts.FirstOrDefault(), knokRate.Price, args);
        }

        [HttpPost("ValidateKnok")]
        public async Task<ApiObject<bool>> ValidateKnok([FromBody]CreateKnokArgs args)
        {
            return new ApiObject<bool>(await _knokManager.Validate(args));
        }

        [HttpPost("RateKnok")]
        public ApiObject<KnokRate> RateKnok([FromBody]CreateKnokArgs args)
        {
            return new ApiObject<KnokRate>(_knokManager.KnokRatingCalc(args));
        }

        [HttpGet("{knokId}")]
        public Task<Knok> GetKnok([FromRoute]int knokId)
        {
            return _knokManager.GetKnok(knokId, ContextUserId);
        }

        [HttpGet("GetKnok/{knokId}")]
        public async Task<KnokFullData> GetKnokFull([FromRoute]int knokId, [FromQuery] int userId)
        {
            return await _knokManager.GetKnokFull(knokId, userId);
        }

        [HttpGet("{knokId:int}/files/{*fileName}")]
        [AllowAnonymous]
        public FileStreamResult GetFiles([FromRoute]int knokId, [FromRoute] string fileName)
        {
            var result = _knokManager.GetFile(knokId, fileName);
            if (result.ContentType == null)
            {
                if (new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider().TryGetContentType(fileName, out var temp))
                {
                    result.ContentType = temp;
                }
            }
            return File(result.File, result.ContentType, /*result.FileDownloadName, */result.LastModified, null);// "image/png");
            //return File(result.File, result.ContentType, result.FileDownloadName, result.LastModified, null);// "image/png");
            //TODO: check that content type is not added twice
        }

        [HttpGet("feed")]
        public async Task<ApiArray<KnokFeed>> GetPublicKnoks()
        {
            return await GetPublicKnoksPost(new KnokFeedArgs() { UserId = this.ContextUserId.Value });
        }

        [HttpPost("track")]
        public async Task<ApiArray<KnokOngoing>> GetOngoingKnoks([FromBody] KnokOngoingArgs args)
        {
            return new ApiArray<KnokOngoing>(await _knokManager.GetAliveKnoks(args));
        }

        [HttpPost("currentlypublished")]
        public async Task<ApiArray<KnokOngoing>> GetCurrentlyPublishedKnoks([FromBody] KnokCurrentlyPublishedArgs args)
        {
            return new ApiArray<KnokOngoing>(await _knokManager.GetCurrentlyPublishedKnoks(args, UserId));
        }

        [HttpPost("feed")]
        public async Task<ApiArray<KnokFeed>> GetPublicKnoksPost([FromBody] KnokFeedArgs args)
        {
            return ApiArray<KnokFeed>(await _knokManager.GetPublicKnoks(args));
        }

        [HttpGet("ownfeed")]
        public async Task<KnokOwnData> GetOwnKnokData()
        {
            return await _knokManager.GetOwnData(this.UserId);
        }

        [HttpPost("purchase/{knokId}")]
        public async Task<ApiObject<bool>> PurchaseKnok([FromRoute]int knokId)
        {
            var userAccounts = await _accountDao.GetUserAccounts(UserId);
            await _knokManager.PurchaseKnok(knokId, userAccounts.User, userAccounts.Accounts.FirstOrDefault());
            return new ApiObject<bool>(true);
        }

        [HttpGet("knokser/{knokserId}")]
        public async Task<KnokserProfile> GetKnokserProfile([FromRoute]long knokserId)
        {
            return await _knokManager.GetKnokserProfile(knokserId);
        }

        [HttpPost("ended")]
        public async Task<ApiArray<KnokEnded>> GetEndedKnoks([FromBody] KnokEndedArgs args)
        {
            return new ApiArray<KnokEnded>(await _knokManager.GetEndedKnoks(args));
        }

        [HttpPost("pastpublished")]
        public async Task<ApiArray<KnokEnded>> GetPastPublishedKnoks([FromBody] KnokPastPublishedArgs args)
        {
            return new ApiArray<KnokEnded>(await _knokManager.GetPastPublishedKnoks(args, UserId));
        }
    }
}
