using System.Collections.ObjectModel;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using Serilog;
using SharepointToolbox.Core.Models;
using SharepointToolbox.Infrastructure.Persistence;
using SharepointToolbox.Services;

namespace SharepointToolbox.ViewModels.Tabs;

public partial class TemplatesViewModel : FeatureViewModelBase
{
    private readonly ITemplateService _templateService;
    private readonly TemplateRepository _templateRepo;
    private readonly ISessionManager _sessionManager;
    private readonly ILogger<FeatureViewModelBase> _logger;
    private TenantProfile? _currentProfile;

    // Template list
    private ObservableCollection<SiteTemplate> _templates = new();
    public ObservableCollection<SiteTemplate> Templates
    {
        get => _templates;
        private set { _templates = value; OnPropertyChanged(); }
    }

    [ObservableProperty] private SiteTemplate? _selectedTemplate;

    // Capture options
    [ObservableProperty] private string _templateName = string.Empty;
    [ObservableProperty] private bool _captureLibraries = true;
    [ObservableProperty] private bool _captureFolders = true;
    [ObservableProperty] private bool _capturePermissions = true;
    [ObservableProperty] private bool _captureLogo = true;
    [ObservableProperty] private bool _captureSettings = true;

    // Apply options
    [ObservableProperty] private string _newSiteTitle = string.Empty;
    [ObservableProperty] private string _newSiteAlias = string.Empty;

    public IAsyncRelayCommand CaptureCommand { get; }
    public IAsyncRelayCommand ApplyCommand { get; }
    public IAsyncRelayCommand RenameCommand { get; }
    public IAsyncRelayCommand DeleteCommand { get; }
    public IAsyncRelayCommand RefreshCommand { get; }

    public TenantProfile? CurrentProfile => _currentProfile;

    // Factory for rename dialog — set by View code-behind
    public Func<string, string?>? RenameDialogFactory { get; set; }

    public TemplatesViewModel(
        ITemplateService templateService,
        TemplateRepository templateRepo,
        ISessionManager sessionManager,
        ILogger<FeatureViewModelBase> logger)
        : base(logger)
    {
        _templateService = templateService;
        _templateRepo = templateRepo;
        _sessionManager = sessionManager;
        _logger = logger;

        CaptureCommand = new AsyncRelayCommand(CaptureAsync, () => !IsRunning);
        ApplyCommand = new AsyncRelayCommand(ApplyAsync, () => !IsRunning && SelectedTemplate != null);
        RenameCommand = new AsyncRelayCommand(RenameAsync, () => SelectedTemplate != null);
        DeleteCommand = new AsyncRelayCommand(DeleteAsync, () => SelectedTemplate != null);
        RefreshCommand = new AsyncRelayCommand(RefreshListAsync);
    }

    protected override async Task RunOperationAsync(CancellationToken ct, IProgress<OperationProgress> progress)
    {
        // Not used directly — Capture and Apply have their own async commands
        await Task.CompletedTask;
    }

    private async Task CaptureAsync()
    {
        if (_currentProfile == null)
            throw new InvalidOperationException("No tenant connected.");
        if (string.IsNullOrWhiteSpace(TemplateName))
            throw new InvalidOperationException("Template name is required.");

        var captureSiteUrl = GlobalSites.Select(s => s.Url).FirstOrDefault(u => !string.IsNullOrWhiteSpace(u));
        if (string.IsNullOrWhiteSpace(captureSiteUrl))
            throw new InvalidOperationException("Select at least one site from the toolbar.");

        try
        {
            IsRunning = true;
            StatusMessage = "Capturing template...";

            var profile = new TenantProfile
            {
                Name = _currentProfile.Name,
                TenantUrl = captureSiteUrl,
                ClientId = _currentProfile.ClientId,
            };
            var ctx = await _sessionManager.GetOrCreateContextAsync(profile, CancellationToken.None);

            var options = new SiteTemplateOptions
            {
                CaptureLibraries = CaptureLibraries,
                CaptureFolders = CaptureFolders,
                CapturePermissionGroups = CapturePermissions,
                CaptureLogo = CaptureLogo,
                CaptureSettings = CaptureSettings,
            };

            var progress = new Progress<OperationProgress>(p => StatusMessage = p.Message);
            var template = await _templateService.CaptureTemplateAsync(ctx, options, progress, CancellationToken.None);
            template.Name = TemplateName;

            await _templateRepo.SaveAsync(template);
            Log.Information("Template captured: {Name} from {Url}", template.Name, captureSiteUrl);

            await RefreshListAsync();
            StatusMessage = $"Template captured successfully.";
        }
        catch (Exception ex)
        {
            StatusMessage = $"Capture failed: {ex.Message}";
            Log.Error(ex, "Template capture failed");
        }
        finally
        {
            IsRunning = false;
        }
    }

    private async Task ApplyAsync()
    {
        if (_currentProfile == null || SelectedTemplate == null) return;
        if (string.IsNullOrWhiteSpace(NewSiteTitle))
            throw new InvalidOperationException("New site title is required.");
        if (string.IsNullOrWhiteSpace(NewSiteAlias))
            throw new InvalidOperationException("New site alias is required.");

        try
        {
            IsRunning = true;
            StatusMessage = $"Applying template...";

            var ctx = await _sessionManager.GetOrCreateContextAsync(_currentProfile, CancellationToken.None);
            var progress = new Progress<OperationProgress>(p => StatusMessage = p.Message);

            var siteUrl = await _templateService.ApplyTemplateAsync(
                ctx, SelectedTemplate, NewSiteTitle, NewSiteAlias,
                progress, CancellationToken.None);

            StatusMessage = $"Template applied. Site created at: {siteUrl}";
            Log.Information("Template applied. New site: {Url}", siteUrl);
        }
        catch (Exception ex)
        {
            StatusMessage = $"Apply failed: {ex.Message}";
            Log.Error(ex, "Template apply failed");
        }
        finally
        {
            IsRunning = false;
        }
    }

    private async Task RenameAsync()
    {
        if (SelectedTemplate == null) return;

        if (RenameDialogFactory != null)
        {
            var newName = RenameDialogFactory(SelectedTemplate.Name);
            if (!string.IsNullOrWhiteSpace(newName))
            {
                await _templateRepo.RenameAsync(SelectedTemplate.Id, newName);
                await RefreshListAsync();
                Log.Information("Template renamed.");
            }
        }
    }

    private async Task DeleteAsync()
    {
        if (SelectedTemplate == null) return;

        await _templateRepo.DeleteAsync(SelectedTemplate.Id);
        await RefreshListAsync();
        Log.Information("Template deleted.");
    }

    private async Task RefreshListAsync()
    {
        var templates = await _templateRepo.GetAllAsync();
        await Application.Current.Dispatcher.InvokeAsync(() =>
        {
            Templates = new ObservableCollection<SiteTemplate>(templates);
        });
    }

    protected override void OnTenantSwitched(TenantProfile profile)
    {
        _currentProfile = profile;
        TemplateName = string.Empty;
        NewSiteTitle = string.Empty;
        NewSiteAlias = string.Empty;
        StatusMessage = string.Empty;

        _ = RefreshListAsync();
    }

    partial void OnSelectedTemplateChanged(SiteTemplate? value)
    {
        ApplyCommand.NotifyCanExecuteChanged();
        RenameCommand.NotifyCanExecuteChanged();
        DeleteCommand.NotifyCanExecuteChanged();
    }
}
