using Refit;

namespace OTSSignsOrchestrator.Server.Clients;

// ── Request DTOs ────────────────────────────────────────────────────────────
public record CreateUserRequest(
    string UserName,
    string Email,
    string Password,
    int UserTypeId,
    int HomePageId);

public record UpdateUserRequest(
    string? UserName,
    string? Email,
    string? Password,
    int? UserTypeId,
    int? HomePageId,
    int? Retired);

public record CreateGroupRequest(string Group, string? Description);

public record AssignMemberRequest(int[] UserId);

public record SetAclRequest(string[] ObjectId, string[] PermissionsId);

public record CreateApplicationRequest(string Name);

public record UpdateSettingsRequest(Dictionary<string, string> Settings);

public record CreateDisplayRequest(string Display, string? Description);

// ── Xibo CMS Refit Interface ────────────────────────────────────────────────
// CRITICAL: GET /api/application is BLOCKED — only POST and DELETE exist.
// All group endpoints use /api/group, NOT /api/usergroup.
// Feature assignment is POST /api/group/{id}/acl, NOT /features.
// Xibo paginates at 10 items by default — always pass start + length params.
[Headers("Authorization: Bearer")]
public interface IXiboApiClient
{
    // ── About ───────────────────────────────────────────────────────────────
    [Get("/about")]
    Task<ApiResponse<object>> GetAboutAsync();

    // ── Users ───────────────────────────────────────────────────────────────
    [Get("/user")]
    Task<List<Dictionary<string, object>>> GetUsersAsync(
        [AliasAs("start")] int? start = 0,
        [AliasAs("length")] int? length = 200);

    [Post("/user")]
    Task<ApiResponse<Dictionary<string, object>>> CreateUserAsync(
        [Body(BodySerializationMethod.UrlEncoded)] CreateUserRequest body);

    [Put("/user/{userId}")]
    Task<ApiResponse<Dictionary<string, object>>> UpdateUserAsync(
        int userId,
        [Body(BodySerializationMethod.UrlEncoded)] UpdateUserRequest body);

    [Delete("/user/{userId}")]
    Task DeleteUserAsync(int userId);

    // ── Groups (NOT /usergroup) ─────────────────────────────────────────────
    [Get("/group")]
    Task<List<Dictionary<string, object>>> GetGroupsAsync(
        [AliasAs("start")] int? start = 0,
        [AliasAs("length")] int? length = 200);

    [Post("/group")]
    Task<ApiResponse<Dictionary<string, object>>> CreateGroupAsync(
        [Body(BodySerializationMethod.UrlEncoded)] CreateGroupRequest body);

    [Delete("/group/{groupId}")]
    Task DeleteGroupAsync(int groupId);

    [Post("/group/members/assign/{groupId}")]
    Task<ApiResponse<object>> AssignUserToGroupAsync(
        int groupId,
        [Body(BodySerializationMethod.UrlEncoded)] AssignMemberRequest body);

    // ACL — NOT /features
    [Post("/group/{groupId}/acl")]
    Task<ApiResponse<object>> SetGroupAclAsync(
        int groupId,
        [Body(BodySerializationMethod.UrlEncoded)] SetAclRequest body);

    // ── Displays ────────────────────────────────────────────────────────────
    [Get("/display")]
    Task<List<Dictionary<string, object>>> GetDisplaysAsync(
        [AliasAs("start")] int? start = 0,
        [AliasAs("length")] int? length = 200,
        [AliasAs("authorised")] int? authorised = null);

    // ── Applications (POST + DELETE only — GET is BLOCKED) ──────────────────
    [Post("/application")]
    Task<ApiResponse<Dictionary<string, object>>> CreateApplicationAsync(
        [Body(BodySerializationMethod.UrlEncoded)] CreateApplicationRequest body);

    [Delete("/application/{key}")]
    Task DeleteApplicationAsync(string key);

    // ── Settings ────────────────────────────────────────────────────────────
    [Get("/settings")]
    Task<ApiResponse<object>> GetSettingsAsync();

    [Put("/settings")]
    Task<ApiResponse<object>> UpdateSettingsAsync(
        [Body(BodySerializationMethod.UrlEncoded)] UpdateSettingsRequest body);
}

// ── Pagination helper ───────────────────────────────────────────────────────
public static class XiboApiClientExtensions
{
    /// <summary>
    /// Pages through a Xibo list endpoint until a page returns fewer items than pageSize.
    /// </summary>
    public static async Task<List<T>> GetAllPagesAsync<T>(
        this IXiboApiClient client,
        Func<int, int, Task<List<T>>> listMethod,
        int pageSize = 200)
    {
        var all = new List<T>();
        var start = 0;

        while (true)
        {
            var page = await listMethod(start, pageSize);
            all.AddRange(page);

            if (page.Count < pageSize)
                break;

            start += pageSize;
        }

        return all;
    }
}
