using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using SmartAquaViewer.Controls;

namespace SmartAquaViewer.ViewModel
{
    public interface IPager
    {
        int PageSize { get; set; }
        int PageIndex { get; set; }
        int TotalPages { get; }
        string PageStatus { get; }

        ICommand FirstPageCommand { get; }
        ICommand PrevPageCommand { get; }
        ICommand NextPageCommand { get; }
        ICommand LastPageCommand { get; }
    }

    public class PagingViewModelBase<T> : INotifyPropertyChanged, IPager
    {
        public ObservableCollection<T> Items { get; } = new();

        private int _pageSize = 10;
        public int PageSize
        {
            get => _pageSize;
            set
            {
                if (_pageSize != value)
                {
                    _pageSize = value;
                    PageIndex = 0;
                    OnPropertyChanged();
                    RebuildPage();
                }
            }
        }

        private int _pageIndex; // 0-based
        public int PageIndex
        {
            get => _pageIndex;
            set { if (_pageIndex != value) { _pageIndex = Math.Max(0, Math.Min(value, TotalPages - 1)); OnPropertyChanged(nameof(PageIndex)); RebuildPage(); } }
        }

        public int TotalCount => Items.Count;
        public int TotalPages => Math.Max(1, (int)Math.Ceiling(TotalCount / (double)PageSize));

        private readonly ObservableCollection<T> _pagedItems = new();
        public ReadOnlyObservableCollection<T> PagedItems { get; }

        private int _pageGroupSize = 5;
        public int PageGroupSize
        {
            get => _pageGroupSize;
            set
            {
                if (_pageGroupSize != value)
                {
                    _pageGroupSize = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(PageNumbers));
                }
            }
        }

        // 🔹 현재 그룹에 표시할 페이지 인덱스들 (0-based)
        public IEnumerable<int> PageNumbers
        {
            get
            {
                if (TotalPages <= 0) yield break;

                // 현재 그룹: ex) 0~4, 5~9, ...
                var groupIndex = PageIndex / PageGroupSize;
                var start = groupIndex * PageGroupSize;
                var end = Math.Min(start + PageGroupSize - 1, TotalPages - 1);

                for (int i = start; i <= end; i++)
                    yield return i;
            }
        }

        // 보기용 표시: "101–150 / 4,327 (3/87)"
        public string PageStatus
        {
            get
            {
                if (TotalCount == 0) return "0 / 0 (0/0)";
                var start = PageIndex * PageSize + 1;
                var end = Math.Min((PageIndex + 1) * PageSize, TotalCount);
                return $"{start}–{end} / {TotalCount:N0} ({PageIndex + 1}/{TotalPages})";
            }
        }

        public ICommand FirstPageCommand => new RelayCommand(_ => PageIndex = 0, _ => PageIndex > 0);
        public ICommand PrevPageCommand => new RelayCommand(_ => PageIndex--, _ => PageIndex > 0);
        public ICommand NextPageCommand => new RelayCommand(_ => PageIndex++, _ => PageIndex < TotalPages - 1);
        public ICommand LastPageCommand => new RelayCommand(_ => PageIndex = TotalPages - 1, _ => PageIndex < TotalPages - 1);

        public ICommand GoToPageCommand => new RelayCommand(
        p =>
        {
            if (p is int idx)
                PageIndex = idx;
        },
        p =>
        {
            if (p is int idx)
                return idx >= 0 && idx < TotalPages;
            return false;
        });

        public PagingViewModelBase()
        {
            PagedItems = new ReadOnlyObservableCollection<T>(_pagedItems);
            Items.CollectionChanged += (_, __) => RebuildPage(); // 원본이 바뀌면 재구성
            RebuildPage();
        }

        private void RebuildPage()
        {
            // 현재 페이지 구간
            var slice = Items.Skip(PageIndex * PageSize).Take(PageSize).ToList();

            // 🔹 ObservableCollection 동기화 (Clear/Add)
            _pagedItems.Clear();
            foreach (var item in slice) _pagedItems.Add(item);

            // 숫자/상태 텍스트 갱신
            OnPropertyChanged(nameof(TotalCount));
            OnPropertyChanged(nameof(TotalPages));
            OnPropertyChanged(nameof(PageStatus));
            OnPropertyChanged(nameof(PageNumbers));

            // 버튼 CanExecute 즉시 반영
            CommandManager.InvalidateRequerySuggested();
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string? name = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}
