📄 src/Activities/FolderPickerActivity.cs
using Android.Content;
using Android.Views;
using AndroidX.AppCompat.App;
using AndroidX.RecyclerView.Widget;
using Google.Android.Material.ProgressIndicator;
using NotesApp.Adapters;
using NotesApp.Auth;
using NotesApp.Graph;
using NotesApp.Models;
using NotesApp.Views;
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;

namespace NotesApp.Activities;

[Activity(Label = "@string/choose_folder_title", Exported = false)]
public class FolderPickerActivity : AppCompatActivity
{
    private const int SelectFolderRequestCode = 100;
    public const string ExtraFolderId = "folder_id";
    public const string ExtraFolderPath = "folder_path";

    private LinearProgressIndicator _progressBar = null!;
    private FolderListAdapter _adapter = null!;
    private GraphService _graphService = null!;

    private string? _folderId;
    private string _folderPath = "/";

    protected override void OnCreate(Bundle? savedInstanceState)
    {
        AndroidX.Activity.EdgeToEdge.Enable(this);
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.activity_folder_picker);

        EdgeToEdgeHelper.Apply(FindViewById(Resource.Id.folder_picker_root)!);

        _folderId = Intent?.GetStringExtra(ExtraFolderId);
        _folderPath = Intent?.GetStringExtra(ExtraFolderPath) ?? "/";

        var toolbar = FindViewById<Toolbar>(Resource.Id.folder_picker_toolbar)!;
        toolbar.Title = _folderPath;
        SetSupportActionBar(toolbar);
        SupportActionBar?.SetDisplayHomeAsUpEnabled(true);

        _progressBar = FindViewById<LinearProgressIndicator>(Resource.Id.folder_progress)!;

        var recyclerView = FindViewById<RecyclerView>(Resource.Id.folder_recycler_view)!;
        recyclerView.SetLayoutManager(new LinearLayoutManager(this));

        _adapter = new FolderListAdapter(OnFolderTapped);
        recyclerView.SetAdapter(_adapter);

        FindViewById<Button>(Resource.Id.select_folder_button)!.Click += (_, _) =>
            SelectThisFolder();

        _graphService = new GraphService(this);

        _ = LoadFoldersAsync();
    }

    public override bool OnSupportNavigateUp()
    {
        Finish();
        return true;
    }

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent? data)
    {
        base.OnActivityResult(requestCode, resultCode, data);
        AuthService.HandleActivityResult(requestCode, resultCode, data);

        if (requestCode == SelectFolderRequestCode && resultCode == Result.Ok && data != null)
        {
            // A nested picker (a subfolder browsed into) selected a folder; forward the
            // result up the recursive chain and close this level too.
            SetResult(Result.Ok, data);
            Finish();
        }
    }

    private async Task LoadFoldersAsync()
    {
        var folderKey = _folderId ?? "root";

        // Render instantly from a prior visit or a parent-level prefetch if we have one;
        // otherwise fall back to the normal network fetch with a spinner.
        if (FolderChildrenCache.TryGet(folderKey, out var cached))
        {
            _adapter.SetItems(cached);
            PrefetchChildrenOf(cached);
            return;
        }

        _progressBar.Visibility = ViewStates.Visible;
        try
        {
            var folders = await _graphService.ListChildFoldersAsync(_folderId);
            FolderChildrenCache.Set(folderKey, folders);
            _adapter.SetItems(folders);
            PrefetchChildrenOf(folders);
        }
        catch (Exception ex)
        {
            Toast.MakeText(this, ex.Message, ToastLength.Long)?.Show();
        }
        finally
        {
            _progressBar.Visibility = ViewStates.Invisible;
        }
    }

    // Warms the cache one level ahead so tapping into a folder shown here is usually instant
    // instead of waiting on a network round trip. Fire-and-forget: a normal fetch still runs
    // (with its own spinner/error handling) if the user navigates in before this finishes.
    private void PrefetchChildrenOf(List<DriveFolderItem> folders)
    {
        foreach (var folder in folders)
        {
            if (FolderChildrenCache.TryGet(folder.Id, out _))
                continue;

            _ = PrefetchOneAsync(folder.Id);
        }
    }

    private async Task PrefetchOneAsync(string folderId)
    {
        try
        {
            var children = await _graphService.ListChildFoldersAsync(folderId);
            FolderChildrenCache.Set(folderId, children);
        }
        catch
        {
            // Best-effort warm-up; a real fetch with error handling runs if the user
            // navigates in before this succeeds.
        }
    }

    private void OnFolderTapped(DriveFolderItem folder)
    {
        var intent = new Intent(this, typeof(FolderPickerActivity));
        intent.PutExtra(ExtraFolderId, folder.Id);
        intent.PutExtra(ExtraFolderPath, _folderPath.TrimEnd('/') + "/" + folder.Name);
        StartActivityForResult(intent, SelectFolderRequestCode);
    }

    private void SelectThisFolder()
    {
        var data = new Intent();
        data.PutExtra(ExtraFolderId, _folderId ?? "root");
        data.PutExtra(ExtraFolderPath, _folderPath);
        SetResult(Result.Ok, data);
        Finish();
    }
}