using AccountTracking.Api.Data;
using AccountTracking.Api.Models.Dtos;
using AccountTracking.Api.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace AccountTracking.Api.Controllers;

[ApiController]
[Route("api/transactions")]
[Authorize]
public class TransactionsController : ControllerBase
{
    private readonly AppDbContext _db;
    private readonly CsvImportService _importService;

    public TransactionsController(AppDbContext db, CsvImportService importService)
    {
        _db = db;
        _importService = importService;
    }

    [HttpPost("import")]
    public async Task<IActionResult> Import(IFormFile file)
    {
        if (file == null || file.Length == 0)
            return BadRequest(new ErrorResult("Nebyl vybrán žádný soubor."));

        string content;
        using (var reader = new StreamReader(file.OpenReadStream(), System.Text.Encoding.UTF8))
            content = await reader.ReadToEndAsync();

        var result = await _importService.ImportAsync(content, file.FileName);

        if (!result.IsSuccess)
            return BadRequest(new ErrorResult(result.Error!));

        return Ok(result.Value);
    }

    [HttpGet]
    public async Task<IActionResult> List(
        [FromQuery] int year,
        [FromQuery] int? month,
        [FromQuery] string? category,
        [FromQuery] string? search,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 50)
    {
        pageSize = Math.Clamp(pageSize, 1, 200);
        page = Math.Max(1, page);

        var query = _db.Transactions.AsQueryable();

        query = query.Where(t => t.BookingDate.Year == year);
        if (month.HasValue)
            query = query.Where(t => t.BookingDate.Month == month.Value);
        if (!string.IsNullOrWhiteSpace(category))
            query = query.Where(t => t.Category == category);
        if (!string.IsNullOrWhiteSpace(search))
            query = query.Where(t =>
                (t.CounterPartyName != null && EF.Functions.Like(t.CounterPartyName, $"%{search}%")) ||
                (t.Message != null && EF.Functions.Like(t.Message, $"%{search}%")));

        var total = await query.CountAsync();
        var items = await query
            .OrderByDescending(t => t.BookingDate)
            .ThenByDescending(t => t.Id)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Select(t => new TransactionDto(
                t.Id, t.BookingDate, t.CounterPartyName,
                t.Category, t.Amount, t.Balance, t.Message))
            .ToListAsync();

        return Ok(new TransactionListResponse(items, total, page, pageSize));
    }

    [HttpGet("categories")]
    public async Task<IActionResult> Categories()
    {
        var cats = await _db.Transactions
            .Where(t => t.Category != null)
            .Select(t => t.Category!)
            .Distinct()
            .OrderBy(c => c)
            .ToListAsync();

        return Ok(cats);
    }
}
