using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using SmartAquaViewer.ViewModel;

namespace SmartAquaViewer.Helper
{
    public static class DataGridAutoPageSizeBehavior
    {
        public static readonly DependencyProperty EnableProperty =
            DependencyProperty.RegisterAttached(
                "Enable", typeof(bool), typeof(DataGridAutoPageSizeBehavior),
                new PropertyMetadata(false, OnEnableChanged));

        public static void SetEnable(DependencyObject d, bool v) => d.SetValue(EnableProperty, v);
        public static bool GetEnable(DependencyObject d) => (bool)d.GetValue(EnableProperty);

        public static readonly DependencyProperty SuspendProperty =
        DependencyProperty.RegisterAttached("Suspend", typeof(bool), typeof(DataGridAutoPageSizeBehavior),
            new PropertyMetadata(false));

        public static void SetSuspend(DependencyObject d, bool v) => d.SetValue(SuspendProperty, v);
        public static bool GetSuspend(DependencyObject d) => (bool)d.GetValue(SuspendProperty);

        // 🔹 여기! 어느 페이저를 갱신할지 바인딩으로 지정
        public static readonly DependencyProperty PagerProperty =
            DependencyProperty.RegisterAttached(
                "Pager", typeof(IPager), typeof(DataGridAutoPageSizeBehavior),
                new PropertyMetadata(null));

        public static void SetPager(DependencyObject d, IPager? v) => d.SetValue(PagerProperty, v);
        public static IPager? GetPager(DependencyObject d) => (IPager?)d.GetValue(PagerProperty);

        public static readonly DependencyProperty ThrottleMsProperty =
        DependencyProperty.RegisterAttached("ThrottleMs", typeof(int), typeof(DataGridAutoPageSizeBehavior),
            new PropertyMetadata(120));
        public static void SetThrottleMs(DependencyObject d, int v) => d.SetValue(ThrottleMsProperty, v);
        public static int GetThrottleMs(DependencyObject d) => (int)d.GetValue(ThrottleMsProperty);

        private static readonly ConditionalWeakTable<DataGrid, DispatcherTimer> _timers = new();

        private static void OnEnableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is not DataGrid dg) return;
            if ((bool)e.NewValue)
            {
                dg.SizeChanged += DataGrid_SizeChanged;
                EnsureTimer(dg);
            }
            else
            {
                dg.SizeChanged -= DataGrid_SizeChanged;
                if (_timers.TryGetValue(dg, out var t))
                {
                    t.Stop();
                    _timers.Remove(dg);
                }
            }
        }

        private static void EnsureTimer(DataGrid dg)
        {
            if (_timers.TryGetValue(dg, out _)) return;
            var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(GetThrottleMs(dg)) };
            timer.Tick += (_, __) =>
            {
                timer.Stop();
                ApplyAutoPageSize(dg);
            };
            _timers.Add(dg, timer);
        }

        private static void DataGrid_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (sender is not DataGrid dg) return;

            // 1) 우선 명시된 Pager를 사용
            var pager = GetPager(dg);

            // 2) 없으면 DataContext에서 찾아봄 (메인 페이저 케이스)
            pager ??= dg.DataContext as IPager;

            if (pager == null || dg.RowHeight <= 0 || dg.ActualHeight <= 0) return;

            double header = dg.ColumnHeaderHeight > 0 ? dg.ColumnHeaderHeight : 45;
            double available = Math.Max(0, dg.ActualHeight - header);
            int rows = Math.Max(1, (int)(available / dg.RowHeight));

            if (pager.PageSize != rows)
                pager.PageSize = rows; // 페이저 쪽에서 RebuildPage() 호출됨
        }

        private static void ApplyAutoPageSize(DataGrid dg)
        {
            if (GetSuspend(dg)) return;              // 여기도 방어
            if (dg.RowHeight <= 0 || dg.ActualHeight <= 0) return;

            double header = dg.ColumnHeaderHeight > 0 ? dg.ColumnHeaderHeight : 30;
            double available = Math.Max(0, dg.ActualHeight - header - 2);
            int rows = Math.Max(1, (int)(available / dg.RowHeight));

            IPager? pager = GetPager(dg) ?? dg.DataContext as IPager;
            if (pager is null) return;

            if (pager.PageSize != rows)
                pager.PageSize = rows;               // 내부에서 RebuildPage() 호출
        }
    }
}
