using SharedKernel.Helpers;
using SharedKernel.Extensions;
using Domain.Entities.Wallets.ValueObject;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace Admin.Pages.Member.Wallet.Transactions;

public class IndexModel(IMediator mediator) : PageModel
{
    [BindProperty(SupportsGet = true)]
    public QueryParams Query { get; set; } = new();

    public sealed class QueryParams
    {
        [Range(1, int.MaxValue)]
        [DisplayName("페이지 번호")]
        public int PageNum { get; set; } = 1;

        [Range(1, 100)]
        [DisplayName("페이지 목록 수")]
        public ushort PerPage { get; set; } = 10;

        [DisplayName("검색 조건")]
        [Range(1, 5, ErrorMessage = "{0}이(가) 올바르지 않습니다.")]
        public int? Search { get; set; }

        [DisplayName("검색어")]
        [MaxLength(255, ErrorMessage = "{0}은(는) {1}자 이하로 입력하세요.")]
        public string? Keyword { get; set; }

        [DisplayName("시작일")]
        public string? StartAt { get; set; }

        [DisplayName("종료일")]
        public string? EndAt { get; set; }

        [DisplayName("거래 유형")]
        public WalletTransactionType? Type { get; set; }
    }

    public int Total { get; set; }
    public int TotalCharge { get; set; }
    public int TotalDonationIn { get; set; }
    public int TotalDonationOut { get; set; }
    public int TotalRewardEarned { get; set; }
    public int TotalSpend { get; set; }
    public int TotalRefund { get; set; }
    public int TotalLock { get; set; }
    public int TotalUnlock { get; set; }
    public int TotalAdjusted { get; set; }

    public List<(
        int Num,
        int ID,
        Guid WalletKey,
        int MemberID,
        string MemberEmail,
        string MemberName,
        string TxType,
        string BalanceType,
        string Amount,
        string BalanceAfter,
        string CreatedAt,
        string ViewURL
    )> List { get; set; } = [];

    public Pagination? Pagination { get; set; }

    public async Task OnGetAsync(CancellationToken ct)
    {
        if (!ModelState.IsValid)
        {
            return;
        }

        var result = await mediator.Send(new SearchWalletTransactions.Query(
            Query.PageNum,
            Query.PerPage,
            Query.Search,
            Query.Keyword,
            Query.StartAt,
            Query.EndAt,
            Query.Type
        ), ct);

        Total = result.Total;
        TotalCharge = result.TotalCharge;
        TotalDonationIn = result.TotalDonationIn;
        TotalDonationOut = result.TotalDonationOut;
        TotalRewardEarned = result.TotalRewardEarned;
        TotalSpend = result.TotalSpend;
        TotalRefund = result.TotalRefund;
        TotalLock = result.TotalLock;
        TotalUnlock = result.TotalUnlock;
        TotalAdjusted = result.TotalAdjusted;

        var qs = Request.QueryString.ToString();

        List = [..result.List.Select(c => (
            c.Num,
            c.ID,
            c.WalletKey,
            c.MemberID,
            c.MemberEmail,
            MemberName: c.MemberName ?? "-",
            TxType: GetTxTypeName(c.TxType),
            BalanceType: GetBalanceTypeName(c.BalanceType),
            Amount: c.Amount.ToString("N0"),
            BalanceAfter: c.BalanceAfter.ToString("N0"),
            CreatedAt: c.CreatedAt.GetDateAt(),
            ViewURL: $"/Member/Wallet/Transactions/View/{c.ID}{qs}"
        ))];

        Pagination = new Pagination(result.Total, Query.PageNum, Query.PerPage);
    }

    public async Task<IActionResult> OnPostDeleteAsync(int[] ids, CancellationToken ct)
    {
        try
        {
            if (ids.Length == 0)
            {
                throw new Exception("삭제할 항목을 선택해주세요.");
            }

            await mediator.Send(new DeleteWalletTransaction.Command(ids), ct);

            TempData["SuccessMessage"] = $"{ids.Length}건이 삭제되었습니다.";
        }
        catch (Exception e)
        {
            TempData["ErrorMessages"] = e.Message;
        }

        return RedirectToPage(Query);
    }

    private static string GetTxTypeName(WalletTransactionType type) => type switch
    {
        WalletTransactionType.Charge => "충전",
        WalletTransactionType.DonationIn => "후원 받음",
        WalletTransactionType.DonationOut => "후원 보냄",
        WalletTransactionType.RewardEarned => "보상 적립",
        WalletTransactionType.Spend => "사용",
        WalletTransactionType.Refund => "환불",
        WalletTransactionType.Lock => "잠금",
        WalletTransactionType.Unlock => "잠금 해제",
        WalletTransactionType.Adjusted => "조정",
        _ => type.ToString()
    };

    private static string GetBalanceTypeName(WalletBalanceType type) => type switch
    {
        WalletBalanceType.PgCharged => "PG 충전",
        WalletBalanceType.Deposit => "직접 입금",
        WalletBalanceType.Donation => "후원",
        WalletBalanceType.Reward => "보상",
        WalletBalanceType.Airdrop => "에어드랍",
        WalletBalanceType.Locked => "잠금",
        WalletBalanceType.Adjusted => "조정",
        _ => type.ToString()
    };
}