using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media.Imaging;

namespace ClaudeDo.Ui.Views.Controls;

/// <summary>
/// Owns the lifecycle of the translucent follower window used by the custom task-row drag.
/// Snapshots the dragged control to a bitmap, shows a borderless topmost click-through window
/// that tracks the screen cursor across every top-level window, and tears it down on release.
/// </summary>
internal sealed class TaskDragController
{
    // Slack around the snapshot so the tilted card isn't clipped by the window's own bounds.
    private const double Pad = 36;

    private DragGhostWindow? _ghost;
    private PixelPoint _grabOffset; // physical px from the ghost window's top-left to the cursor

    public bool IsActive => _ghost is not null;

    /// <summary>
    /// Begin the ghost. <paramref name="grabPointInSource"/> is the cursor position inside
    /// <paramref name="source"/> (logical px) at grab time so the snapshot stays under the cursor.
    /// </summary>
    public void Begin(Control source, Point grabPointInSource, double scaling)
    {
        End();

        var size = source.Bounds.Size;
        if (size.Width < 1 || size.Height < 1) return;

        var bitmap = Snapshot(source, scaling);
        if (bitmap is null) return;

        _ghost = new DragGhostWindow();
        _ghost.SetImage(bitmap, size.Width, size.Height, Pad);

        _grabOffset = new PixelPoint(
            (int)Math.Round((grabPointInSource.X + Pad) * scaling),
            (int)Math.Round((grabPointInSource.Y + Pad) * scaling));

        _ghost.Show();
    }

    public void MoveTo(PixelPoint screenCursor)
    {
        if (_ghost is null) return;
        _ghost.Position = new PixelPoint(screenCursor.X - _grabOffset.X, screenCursor.Y - _grabOffset.Y);
    }

    public void End()
    {
        _ghost?.Close();
        _ghost = null;
    }

    private static RenderTargetBitmap? Snapshot(Control source, double scaling)
    {
        var size = source.Bounds.Size;
        var pixelSize = new PixelSize(
            Math.Max(1, (int)Math.Ceiling(size.Width * scaling)),
            Math.Max(1, (int)Math.Ceiling(size.Height * scaling)));
        var rtb = new RenderTargetBitmap(pixelSize, new Vector(96 * scaling, 96 * scaling));
        rtb.Render(source);
        return rtb;
    }
}
