using System.Collections.ObjectModel;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Logging;
using SharepointToolbox.Core.Messages;
using SharepointToolbox.Core.Models;
using SharepointToolbox.Services;

namespace SharepointToolbox.ViewModels;

public partial class MainWindowViewModel : ObservableRecipient
{
    private readonly ProfileService _profileService;
    private readonly SessionManager _sessionManager;
    private readonly ILogger<MainWindowViewModel> _logger;

    // Set by the view layer (MainWindow.xaml.cs) to open the dialog using DI
    public Func<Window>? OpenProfileManagementDialog { get; set; }

    [ObservableProperty]
    private TenantProfile? _selectedProfile;

    [ObservableProperty]
    private string _connectionStatus = "Not connected";

    [ObservableProperty]
    private string _progressStatus = string.Empty;

    [ObservableProperty]
    private int _progressPercentage;

    public ObservableCollection<TenantProfile> TenantProfiles { get; } = new();

    public IAsyncRelayCommand ConnectCommand { get; }
    public IAsyncRelayCommand ClearSessionCommand { get; }
    public RelayCommand ManageProfilesCommand { get; }

    public MainWindowViewModel(
        ProfileService profileService,
        SessionManager sessionManager,
        ILogger<MainWindowViewModel> logger)
    {
        _profileService = profileService;
        _sessionManager = sessionManager;
        _logger = logger;

        ConnectCommand = new AsyncRelayCommand(ConnectAsync, () => SelectedProfile != null);
        ClearSessionCommand = new AsyncRelayCommand(ClearSessionAsync, () => SelectedProfile != null);
        ManageProfilesCommand = new RelayCommand(OpenProfileManagement);

        IsActive = true;
    }

    protected override void OnActivated()
    {
        base.OnActivated();
        Messenger.Register<ProgressUpdatedMessage>(this, (r, m) =>
        {
            var vm = (MainWindowViewModel)r;
            vm.ProgressStatus = m.Value.Message;
            vm.ProgressPercentage = m.Value.Total > 0
                ? (int)(100.0 * m.Value.Current / m.Value.Total)
                : 0;
        });
    }

    partial void OnSelectedProfileChanged(TenantProfile? value)
    {
        if (value != null)
        {
            WeakReferenceMessenger.Default.Send(new TenantSwitchedMessage(value));
        }
        ConnectCommand.NotifyCanExecuteChanged();
        ClearSessionCommand.NotifyCanExecuteChanged();
    }

    public async Task LoadProfilesAsync()
    {
        try
        {
            var profiles = await _profileService.GetProfilesAsync();
            TenantProfiles.Clear();
            foreach (var profile in profiles)
                TenantProfiles.Add(profile);

            if (TenantProfiles.Count > 0)
                SelectedProfile = TenantProfiles[0];
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to load tenant profiles.");
        }
    }

    private async Task ConnectAsync()
    {
        if (SelectedProfile == null) return;
        try
        {
            ConnectionStatus = "Connecting...";
            await _sessionManager.GetOrCreateContextAsync(SelectedProfile, CancellationToken.None);
            ConnectionStatus = SelectedProfile.Name;
        }
        catch (Exception ex)
        {
            ConnectionStatus = "Connection failed";
            _logger.LogError(ex, "Failed to connect to tenant {TenantUrl}.", SelectedProfile.TenantUrl);
        }
    }

    private async Task ClearSessionAsync()
    {
        if (SelectedProfile == null) return;
        try
        {
            await _sessionManager.ClearSessionAsync(SelectedProfile.TenantUrl);
            ConnectionStatus = "Not connected";
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to clear session for {TenantUrl}.", SelectedProfile.TenantUrl);
        }
    }

    private void OpenProfileManagement()
    {
        if (OpenProfileManagementDialog == null) return;
        var dialog = OpenProfileManagementDialog();
        dialog.Owner = Application.Current.MainWindow;
        dialog.ShowDialog();

        // Reload profiles after dialog closes (modal — ShowDialog blocks until closed)
        _ = LoadProfilesAsync();
    }
}
