using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using LSFE.MobApp.Contracts;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Input;
using System.Net.NetworkInformation;

namespace LSFE.MobApp.ViewModels.Utility
{
    public partial class UtilitiesVM : ObservableObject
    {
        private readonly ISyncService _syncService;
        private readonly IRepository<Entities.Planning.MRRawPlan> _mrRawPlanRepository;
        private CancellationTokenSource _networkCheckCts;

        [ObservableProperty]
        private bool _isSyncing;

        [ObservableProperty]
        private string _syncStatus = "Ready to sync";

        [ObservableProperty]
        private DateTime _lastSyncTime;

        // Network status properties
        [ObservableProperty]
        private bool _isConnected;

        [ObservableProperty]
        private string _networkStatusText = "Checking...";

        [ObservableProperty]
        private Color _networkStatusColor = Color.FromArgb("#6B7280");

        [ObservableProperty]
        private string _networkIcon = "📶";

        [ObservableProperty]
        private long _latencyMs = -1;

        [ObservableProperty]
        private bool _isCheckingNetwork;

        public ICommand ViewCrashLogCommand { get; }

        public ObservableCollection<SyncItem> SyncItems { get; } = new ObservableCollection<SyncItem>();

        public UtilitiesVM(
            ISyncService syncService,
            IRepository<Entities.Planning.MRRawPlan> mrRawPlanRepository)
        {
            _syncService = syncService;
            _mrRawPlanRepository = mrRawPlanRepository;
            ViewCrashLogCommand = new Command<UtilitiesVM>(async (doctor) => await ViewCrashLogAsync());
            InitializeSyncItems();
            StartNetworkMonitoring();
        }

        private void InitializeSyncItems()
        {
            SyncItems.Clear();

            SyncItems.Add(new SyncItem
            {
                Title = "Attendance logs",
                Description = "Sync attendance records",
                Icon = "clock_outline.png",
                IconColor = Color.FromArgb("#6366F1"),
                SyncAction = SyncAttendanceAsync
            });

            SyncItems.Add(new SyncItem
            {
                Title = "Coverage Plan",
                Description = "Sync today's coverage plans",
                Icon = "calendar_outline.png",
                IconColor = Color.FromArgb("#10B981"),
                SyncAction = SyncCoveragePlanAsync
            });

            SyncItems.Add(new SyncItem
            {
                Title = "Actual Coverage",
                Description = "Sync doctor coverage data",
                Icon = "doctor_outline.png",
                IconColor = Color.FromArgb("#8B5CF6"),
                SyncAction = SyncActualCoverageAsync
            });

            Debug.WriteLine($"[ViewModel] Initialized {SyncItems.Count} sync items");
        }

        #region Network Monitoring

        private void StartNetworkMonitoring()
        {
            Connectivity.Current.ConnectivityChanged += OnConnectivityChanged;
            CheckNetworkStatus();
        }

        private void OnConnectivityChanged(object sender, ConnectivityChangedEventArgs e)
        {
            CheckNetworkStatus();
        }

        [RelayCommand]
        private void RefreshNetwork()
        {
            CheckNetworkStatus();
        }

        private async void CheckNetworkStatus()
        {
            // Cancel any previous check
            _networkCheckCts?.Cancel();
            _networkCheckCts = new CancellationTokenSource();

            IsCheckingNetwork = true;

            try
            {
                var access = Connectivity.Current.NetworkAccess;

                if (access != NetworkAccess.Internet)
                {
                    IsConnected = false;
                    NetworkStatusText = "No Internet";
                    NetworkStatusColor = Color.FromArgb("#EF4444");
                    NetworkIcon = "📵";
                    LatencyMs = -1;
                    return;
                }

                IsConnected = true;

                // Measure latency by pinging Google's DNS
                var latency = await MeasureLatencyAsync(_networkCheckCts.Token);

                if (_networkCheckCts.Token.IsCancellationRequested) return;

                LatencyMs = latency;
                UpdateNetworkIndicator(latency);
            }
            catch (OperationCanceledException)
            {
                // Cancelled, ignore
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"[Network] Check failed: {ex.Message}");
                IsConnected = false;
                NetworkStatusText = "Check failed";
                NetworkStatusColor = Color.FromArgb("#EF4444");
                NetworkIcon = "⚠️";
            }
            finally
            {
                IsCheckingNetwork = false;
            }
        }

        private async Task<long> MeasureLatencyAsync(CancellationToken ct)
        {
            try
            {
                var ping = new Ping();
                // Ping Google DNS - reliable and fast
                var reply = await ping.SendPingAsync("8.8.8.8", 5000);

                if (ct.IsCancellationRequested) return -1;

                if (reply.Status == IPStatus.Success)
                {
                    return reply.RoundtripTime;
                }

                return -1; // Ping failed
            }
            catch
            {
                return -1;
            }
        }

        private void UpdateNetworkIndicator(long latencyMs)
        {
            if (latencyMs < 0)
            {
                // Ping failed but internet access exists
                NetworkStatusText = "Connected";
                NetworkStatusColor = Color.FromArgb("#F59E0B");
                NetworkIcon = "📶";
                return;
            }

            if (latencyMs <= 50)
            {
                // Excellent: 0-50ms
                NetworkStatusText = $"Excellent ({latencyMs}ms)";
                NetworkStatusColor = Color.FromArgb("#10B981"); // Green
                NetworkIcon = "📶";
            }
            else if (latencyMs <= 150)
            {
                // Good: 51-150ms
                NetworkStatusText = $"Good ({latencyMs}ms)";
                NetworkStatusColor = Color.FromArgb("#10B981"); // Green
                NetworkIcon = "📶";
            }
            else if (latencyMs <= 300)
            {
                // Fair: 151-300ms
                NetworkStatusText = $"Fair ({latencyMs}ms)";
                NetworkStatusColor = Color.FromArgb("#F59E0B"); // Amber
                NetworkIcon = "📶";
            }
            else
            {
                // Poor: 300ms+
                NetworkStatusText = $"Poor ({latencyMs}ms)";
                NetworkStatusColor = Color.FromArgb("#EF4444"); // Red
                NetworkIcon = "📶";
            }
        }

        #endregion

        #region Crash Log

        private async Task ViewCrashLogAsync()
        {
            try
            {
                var logPath = Path.Combine(FileSystem.AppDataDirectory, "crash_log.txt");

                if (File.Exists(logPath))
                {
                    var content = await File.ReadAllTextAsync(logPath);
                    await Application.Current.MainPage.DisplayAlert("Crash Log", content, "OK");

                    await Share.RequestAsync(new ShareFileRequest
                    {
                        Title = "Share Crash Log",
                        File = new ShareFile(logPath)
                    });
                }
                else
                {
                    await Application.Current.MainPage.DisplayAlert("Info", "No crash log found", "OK");
                }
            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("Error", ex.Message, "OK");
            }
        }

        #endregion

        #region Sync Commands

        [RelayCommand]
        private async Task SyncAllAsync()
        {
            if (IsSyncing) return;
            if (!IsConnected)
            {
                await Application.Current.MainPage.DisplayAlert(
                    "No Connection",
                    "Please check your internet connection before syncing.",
                    "OK");
                return;
            }

            IsSyncing = true;
            SyncStatus = "Syncing all data...";

            try
            {
                int successCount = 0;
                int failCount = 0;

                foreach (var item in SyncItems)
                {
                    var result = await ExecuteSyncItem(item);
                    if (result)
                        successCount++;
                    else
                        failCount++;
                }

                LastSyncTime = DateTime.Now;

                if (failCount == 0)
                    SyncStatus = $"✓ All {successCount} items synced successfully!";
                else if (successCount > 0)
                    SyncStatus = $"⚠ {successCount} succeeded, {failCount} failed";
                else
                    SyncStatus = "✗ Sync failed. Please try again.";

                await Task.Delay(3000);
                if (!IsSyncing)
                    SyncStatus = "Ready to sync";
            }
            catch (Exception ex)
            {
                SyncStatus = $"Error: {ex.Message}";
                Debug.WriteLine($"Sync All error: {ex}");

                await Task.Delay(3000);
                SyncStatus = "Ready to sync";
            }
            finally
            {
                IsSyncing = false;
            }
        }

        [RelayCommand]
        private async Task SyncItemAsync(SyncItem item)
        {
            if (IsSyncing || item.IsSyncing) return;
            if (!IsConnected)
            {
                await Application.Current.MainPage.DisplayAlert(
                    "No Connection",
                    "Please check your internet connection before syncing.",
                    "OK");
                return;
            }

            IsSyncing = true;
            SyncStatus = $"Syncing {item.Title}...";

            try
            {
                await ExecuteSyncItem(item);
                LastSyncTime = DateTime.Now;

                await Task.Delay(1000);
                SyncStatus = "Ready to sync";
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Sync item error: {ex}");
                SyncStatus = "Ready to sync";
            }
            finally
            {
                IsSyncing = false;
            }
        }

        private async Task<bool> ExecuteSyncItem(SyncItem item)
        {
            item.IsSyncing = true;
            item.Status = "Syncing...";

            try
            {
                var result = await item.SyncAction();
                item.Status = result ? "✓ Synced" : "✗ Failed";
                item.LastSynced = DateTime.Now;

                await Task.Delay(1500);
                item.Status = "";

                return result;
            }
            catch (Exception ex)
            {
                item.Status = "✗ Error";
                Debug.WriteLine($"Sync error for {item.Title}: {ex.Message}");

                await Task.Delay(1500);
                item.Status = "";

                return false;
            }
            finally
            {
                item.IsSyncing = false;
            }
        }

        #endregion

        #region Sync Methods

        private async Task<bool> SyncAttendanceAsync()
        {
            try
            {
                await _syncService.SyncPostAttendanceAsync();
                Debug.WriteLine("Attendance sync completed successfully");
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Attendance sync failed: {ex.Message}");
                return false;
            }
        }

        private async Task<bool> SyncActualCoverageAsync()
        {
            try
            {
                var localActualCoveragePlan = await _mrRawPlanRepository.GetAllAsync();
                var unsyncedPlans = localActualCoveragePlan
                    .Where(p => p.IsSync == false && p.Status == 2)
                    .ToList();

                if (unsyncedPlans == null || !unsyncedPlans.Any())
                {
                    Debug.WriteLine("No unsynced actual coverage plans found");
                    return true;
                }

                int successCount = 0;
                int totalCount = unsyncedPlans.Count;

                foreach (var coverage in unsyncedPlans)
                {
                    var result = await _syncService.SyncPostCoverageTodayAsync(coverage.MRRawPlanId);
                    if (result)
                        successCount++;
                }

                Debug.WriteLine($"Actual coverage sync: {successCount}/{totalCount} succeeded");
                return successCount == totalCount;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Actual coverage sync failed: {ex.Message}");
                return false;
            }
        }

        private async Task<bool> SyncCoveragePlanAsync()
        {
            try
            {
                await _syncService.SyncPullCoveragePlanTodayAsync();
                Debug.WriteLine("Coverage plan sync completed successfully");
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Coverage plan sync failed: {ex.Message}");
                return false;
            }
        }

        #endregion
    }

    public partial class SyncItem : ObservableObject
    {
        [ObservableProperty]
        private string _title = string.Empty;

        [ObservableProperty]
        private string _description = string.Empty;

        [ObservableProperty]
        private string _icon = string.Empty;

        [ObservableProperty]
        private Color _iconColor = Colors.Gray;

        [ObservableProperty]
        private bool _isSyncing;

        [ObservableProperty]
        private string _status = string.Empty;

        [ObservableProperty]
        private DateTime? _lastSynced;

        public Func<Task<bool>> SyncAction { get; set; } = () => Task.FromResult(false);
    }
}