using System.Collections.ObjectModel;
using System.IO;
using System.Reflection;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using Microsoft.Win32;
using Serilog;
using SharepointToolbox.Core.Models;
using SharepointToolbox.Localization;
using SharepointToolbox.Services;
using SharepointToolbox.Services.Export;

namespace SharepointToolbox.ViewModels.Tabs;

public partial class FolderStructureViewModel : FeatureViewModelBase
{
    private readonly IFolderStructureService _folderService;
    private readonly ICsvValidationService _csvService;
    private readonly ISessionManager _sessionManager;
    private readonly BulkResultCsvExportService _exportService;
    private readonly ILogger<FeatureViewModelBase> _logger;
    private TenantProfile? _currentProfile;
    private List<FolderStructureRow>? _validRows;
    private BulkOperationSummary<string>? _lastResult;

    [ObservableProperty] private string _libraryTitle = string.Empty;
    [ObservableProperty] private string _previewSummary = string.Empty;
    [ObservableProperty] private string _resultSummary = string.Empty;
    [ObservableProperty] private bool _hasFailures;
    [ObservableProperty] private bool _hasPreview;

    private ObservableCollection<CsvValidationRow<FolderStructureRow>> _previewRows = new();
    public ObservableCollection<CsvValidationRow<FolderStructureRow>> PreviewRows
    {
        get => _previewRows;
        private set { _previewRows = value; OnPropertyChanged(); }
    }

    public IRelayCommand ImportCsvCommand { get; }
    public IRelayCommand LoadExampleCommand { get; }
    public IAsyncRelayCommand ExportFailedCommand { get; }

    public Func<string, bool>? ShowConfirmDialog { get; set; }
    public TenantProfile? CurrentProfile => _currentProfile;

    public FolderStructureViewModel(
        IFolderStructureService folderService,
        ICsvValidationService csvService,
        ISessionManager sessionManager,
        BulkResultCsvExportService exportService,
        ILogger<FeatureViewModelBase> logger)
        : base(logger)
    {
        _folderService = folderService;
        _csvService = csvService;
        _sessionManager = sessionManager;
        _exportService = exportService;
        _logger = logger;

        ImportCsvCommand = new RelayCommand(ImportCsv);
        LoadExampleCommand = new RelayCommand(LoadExample);
        ExportFailedCommand = new AsyncRelayCommand(ExportFailedAsync, () => HasFailures);
    }

    private void ImportCsv()
    {
        var dlg = new OpenFileDialog
        {
            Title = TranslationSource.Instance["bulk.csvimport.title"],
            Filter = TranslationSource.Instance["bulk.csvimport.filter"],
        };
        if (dlg.ShowDialog() != true) return;

        using var stream = File.OpenRead(dlg.FileName);
        LoadAndPreview(stream);
    }

    private void LoadExample()
    {
        var assembly = Assembly.GetExecutingAssembly();
        var resourceName = assembly.GetManifestResourceNames()
            .FirstOrDefault(n => n.EndsWith("folder_structure.csv", StringComparison.OrdinalIgnoreCase));
        if (resourceName == null) return;

        using var stream = assembly.GetManifestResourceStream(resourceName);
        if (stream != null) LoadAndPreview(stream);
    }

    private void LoadAndPreview(Stream stream)
    {
        var rows = _csvService.ParseAndValidateFolders(stream);
        PreviewRows = new ObservableCollection<CsvValidationRow<FolderStructureRow>>(rows);
        _validRows = rows.Where(r => r.IsValid && r.Record != null).Select(r => r.Record!).ToList();

        var uniquePaths = FolderStructureService.BuildUniquePaths(_validRows);
        PreviewSummary = string.Format(TranslationSource.Instance["folderstruct.preview"], uniquePaths.Count);
        HasPreview = true;
        ResultSummary = string.Empty;
        HasFailures = false;
    }

    protected override async Task RunOperationAsync(CancellationToken ct, IProgress<OperationProgress> progress)
    {
        var T = TranslationSource.Instance;
        if (_currentProfile == null) throw new InvalidOperationException(T["err.no_tenant"]);
        if (_validRows == null || _validRows.Count == 0)
            throw new InvalidOperationException(T["err.no_valid_rows"]);
        if (string.IsNullOrWhiteSpace(LibraryTitle))
            throw new InvalidOperationException(T["err.library_title_required"]);

        var urls = GlobalSites.Select(s => s.Url).Where(u => !string.IsNullOrWhiteSpace(u)).ToList();
        if (urls.Count == 0)
            throw new InvalidOperationException(T["err.no_sites_selected"]);

        var uniquePaths = FolderStructureService.BuildUniquePaths(_validRows);
        var message = string.Format(TranslationSource.Instance["bulk.confirm.message"],
            $"{uniquePaths.Count} folders will be created in {LibraryTitle} on {urls.Count} site(s)");
        if (ShowConfirmDialog != null && !ShowConfirmDialog(message))
            return;

        var allResults = new List<BulkItemResult<string>>();

        foreach (var url in urls)
        {
            var profile = new TenantProfile
            {
                Name = _currentProfile.Name,
                TenantUrl = url,
                ClientId = _currentProfile.ClientId,
            };
            var ctx = await _sessionManager.GetOrCreateContextAsync(profile, ct);

            var result = await _folderService.CreateFoldersAsync(ctx, LibraryTitle, _validRows, progress, ct);
            allResults.AddRange(result.Results);
        }

        _lastResult = new BulkOperationSummary<string>(allResults);

        await Application.Current.Dispatcher.InvokeAsync(() =>
        {
            HasFailures = _lastResult.HasFailures;
            ExportFailedCommand.NotifyCanExecuteChanged();

            ResultSummary = _lastResult.HasFailures
                ? string.Format(TranslationSource.Instance["bulk.result.success"],
                    _lastResult.SuccessCount, _lastResult.FailedCount)
                : string.Format(TranslationSource.Instance["bulk.result.allsuccess"],
                    _lastResult.TotalCount);
        });
    }

    private async Task ExportFailedAsync()
    {
        if (_lastResult == null || !_lastResult.HasFailures) return;
        var dlg = new SaveFileDialog { Filter = "CSV Files (*.csv)|*.csv", FileName = "failed_folders.csv" };
        if (dlg.ShowDialog() == true)
        {
            await _exportService.WriteFailedItemsCsvAsync(_lastResult.FailedItems.ToList(), dlg.FileName, CancellationToken.None);
        }
    }

    protected override void OnTenantSwitched(TenantProfile profile)
    {
        _currentProfile = profile;
        LibraryTitle = string.Empty;
        PreviewRows = new();
        _validRows = null;
        PreviewSummary = string.Empty;
        ResultSummary = string.Empty;
        HasFailures = false;
        HasPreview = false;
    }
}
