using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using StockFin.Models;
using StockFin.ViewModels;

namespace StockFin.Controllers
{
    public class AccountsController : Controller
    {
        private readonly FinancesContext _context = new FinancesContext();
        private readonly AlphaVantageService _alpha;
        private readonly IFinnhubClient _finnhub;
        private readonly ITwelveDataClient _twelveData;
        private readonly StocksCache _cache;

        public AccountsController(AlphaVantageService alpha, IFinnhubClient finnhub, ITwelveDataClient twelveData, StocksCache cache)
        {
            _alpha = alpha;
            _finnhub = finnhub;
            _twelveData = twelveData;
            _cache = cache;
        }
        public async Task<IActionResult> Index()
        {
            var accounts = await _context.Accounts
                .Include(a => a.Type)
                .Include(a => a.Increase)
                .OrderBy(a => a.Bank)
                .ThenBy(a => a.Title)
                .ToListAsync();

            return View(accounts);
        }

        public async Task<IActionResult> Details(long? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var account = await _context.Accounts
                .Include(a => a.Type)
                .Include(a => a.Increase)
                .FirstOrDefaultAsync(a => a.Id == id.Value);

            if (account == null)
            {
                return NotFound();
            }

            var statements = await _context.Statements
                .Where(s => s.AccountId == account.Id)
                .OrderByDescending(s => s.Date)
                .ToListAsync();

            var transactions = await _context.Transactions
                .Where(t => t.AccountId == account.Id)
                .Include(t => t.Stocks)
                .OrderByDescending(t => t.Date)
                .ToListAsync();

            var patrimonies = await _context.Patrimonies
                .Where(p => p.AccountId == account.Id)
                .OrderByDescending(p => p.BuyingDate)
                .ThenBy(p => p.Title)
                .ToListAsync();

            var model = new AccountDetailsViewModel
            {
                Account = account,
                Statements = statements,
                Transactions = transactions,
                Patrimonies = patrimonies
            };
            ViewData["actuals"] = _cache.actuals;
            return View(model);
        }

        public async Task<IActionResult> Create()
        {
            await PopulateDropDownsAsync();
            return View(new Account());
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("Id,Title,IncreaseId,TypeId,Bank")] Account account)
        {
            if (ModelState.IsValid)
            {
                _context.Add(account);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }

            await PopulateDropDownsAsync(account.TypeId, account.IncreaseId);
            return View(account);
        }

        public async Task<IActionResult> Edit(long? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var account = await _context.Accounts.FindAsync(id.Value);
            if (account == null)
            {
                return NotFound();
            }

            await PopulateDropDownsAsync(account.TypeId, account.IncreaseId);
            return View(account);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(long id, [Bind("Id,Title,IncreaseId,TypeId,Bank")] Account account)
        {
            if (id != account.Id)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(account);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!AccountExists(account.Id))
                    {
                        return NotFound();
                    }

                    throw;
                }

                return RedirectToAction(nameof(Index));
            }

            await PopulateDropDownsAsync(account.TypeId, account.IncreaseId);
            return View(account);
        }

        public async Task<IActionResult> Delete(long? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var account = await _context.Accounts
                .Include(a => a.Type)
                .Include(a => a.Increase)
                .FirstOrDefaultAsync(a => a.Id == id.Value);

            if (account == null)
            {
                return NotFound();
            }

            return View(account);
        }

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(long id)
        {
            var account = await _context.Accounts.FindAsync(id);
            if (account != null)
            {
                _context.Accounts.Remove(account);
                await _context.SaveChangesAsync();
            }

            return RedirectToAction(nameof(Index));
        }

        private bool AccountExists(long id)
        {
            return _context.Accounts.Any(e => e.Id == id);
        }

        private async Task PopulateDropDownsAsync(long? selectedTypeId = null, long? selectedIncreaseId = null)
        {
            var accountTypes = await _context.AccountTypes
                .OrderBy(t => t.Title)
                .ToListAsync();

            var increases = await _context.Increases
                .OrderBy(i => i.Title)
                .Select(i => new
                {
                    i.Id,
                    DisplayTitle = i.Value.HasValue
                        ? $"{i.Title} ({i.Value.Value:N2}%)"
                        : (i.Title ?? "Sans croissance")
                })
                .ToListAsync();

            ViewData["TypeId"] = new SelectList(accountTypes, "Id", "Title", selectedTypeId);
            ViewData["IncreaseId"] = new SelectList(increases, "Id", "DisplayTitle", selectedIncreaseId);
        }
    }
}
