// ==========================================
// Switchboard Core — SDK: API Domain Namespaces
// ==========================================
// Namespaced domain clients wrapping restClient.
// Each domain is a plain object with typed methods.
//
// Factory: createDomains(restClient)
// ==========================================

/**
 * Build query string from an options object. Skips null/undefined values.
 * @param {object} [opts]
 * @returns {string} — '' or '?key=val&...'
 */
function _qs(opts) {
    if (!opts) return '';
    const p = new URLSearchParams();
    for (const [k, v] of Object.entries(opts)) {
        if (v != null) p.set(k, String(v));
    }
    const s = p.toString();
    return s ? '?' + s : '';
}

/**
 * Standard CRUD factory.
 * @param {object} rc — restClient
 * @param {string} base — e.g. '/api/v1/channels'
 * @returns {object} — { list, get, create, update, del }
 */
function crud(rc, base) {
    return {
        list:   (opts) => rc.get(base + _qs(opts)),
        get:    (id)   => rc.get(`${base}/${id}`),
        create: (data) => rc.post(base, data),
        update: (id, data) => rc.put(`${base}/${id}`, data),
        del:    (id)   => rc.del(`${base}/${id}`),
    };
}

/**
 * Create all 18 domain namespaces.
 *
 * @param {object} restClient
 * @returns {object} api — the full sw.api object
 */
export function createDomains(restClient) {
    const rc = restClient;

    return {
        // ── Escape hatches (raw restClient) ─────
        get:    rc.get.bind(rc),
        post:   rc.post.bind(rc),
        put:    rc.put.bind(rc),
        patch:  rc.patch.bind(rc),
        del:    rc.del.bind(rc),
        stream: rc.stream.bind(rc),
        upload: rc.upload.bind(rc),

        // ── 1. Auth ─────────────────────────────
        auth: {
            login:    (login, password)           => rc.post('/api/v1/auth/login', { login, password }),
            register: (username, email, password)  => rc.post('/api/v1/auth/register', { username, email, password }),
            refresh:  (refreshToken)               => rc.post('/api/v1/auth/refresh', { refresh_token: refreshToken }),
            logout:   (refreshToken)               => rc.post('/api/v1/auth/logout', { refresh_token: refreshToken }),
        },

        // ── 2. Connections ────────────────────
        connections: {
            ...crud(rc, '/api/v1/connections'),
            resolve: (type, name) => rc.get('/api/v1/connections/resolve' + _qs({ type, name })),
        },

        // ── 3. Connection Types ────────────────
        connectionTypes: {
            list: () => rc.get('/api/v1/connection-types'),
        },

        // ── 11. Notifications ──────────────────
        notifications: {
            list:         (opts)       => rc.get('/api/v1/notifications' + _qs(opts)),
            unreadCount:  ()           => rc.get('/api/v1/notifications/unread-count'),
            markRead:     (id)         => rc.patch(`/api/v1/notifications/${id}/read`, {}),
            markAllRead:  ()           => rc.post('/api/v1/notifications/mark-all-read', {}),
            prefs:        ()           => rc.get('/api/v1/notifications/preferences'),
            setPref:      (type, data) => rc.put(`/api/v1/notifications/preferences/${encodeURIComponent(type)}`, data),
            delPref:      (type)       => rc.del(`/api/v1/notifications/preferences/${encodeURIComponent(type)}`),
            del:          (id)         => rc.del(`/api/v1/notifications/${id}`),
        },

        // ── 12. Extensions ─────────────────────
        extensions: {
            list:     (opts) => rc.get('/api/v1/extensions' + _qs(opts)),
            get:      (id)   => rc.get(`/api/v1/extensions/${id}`),
            settings: (id)   => rc.get(`/api/v1/extensions/${id}/settings`),
        },

        // ── 13. Profile ────────────────────────
        profile: {
            get:         ()            => rc.get('/api/v1/profile'),
            update:      (data)        => rc.put('/api/v1/profile', data),
            avatar:      (base64)      => rc.post('/api/v1/profile/avatar', { image: base64 }),
            deleteAvatar:()            => rc.del('/api/v1/profile/avatar'),
            password:    (current, pw) => rc.post('/api/v1/profile/password', { current_password: current, new_password: pw }),
            settings:    ()            => rc.get('/api/v1/settings'),
            updateSettings: (data)     => rc.put('/api/v1/settings', data),
            permissions: ()            => rc.get('/api/v1/profile/permissions'),
        },

        // ── 14. Teams ──────────────────────────
        teams: {
            mine:       ()                      => rc.get('/api/v1/teams/mine'),
            get:        (id)                    => rc.get(`/api/v1/teams/${id}`),
            update:     (id, data)              => rc.put(`/api/v1/teams/${id}`, data),
            members:    (id)                    => rc.get(`/api/v1/teams/${id}/members`),
            addMember:  (id, userId, role)      => rc.post(`/api/v1/teams/${id}/members`, { user_id: userId, role }),
            updateMember:(id, memberId, role)   => rc.put(`/api/v1/teams/${id}/members/${memberId}`, { role }),
            removeMember:(id, memberId)         => rc.del(`/api/v1/teams/${id}/members/${memberId}`),
            groups:     (id)                    => rc.get(`/api/v1/teams/${id}/groups`),
            // Team connections
            connections:      (id)                 => rc.get(`/api/v1/teams/${id}/connections`),
            createConnection: (id, data)           => rc.post(`/api/v1/teams/${id}/connections`, data),
            updateConnection: (id, cid, data)      => rc.put(`/api/v1/teams/${id}/connections/${cid}`, data),
            deleteConnection: (id, cid)            => rc.del(`/api/v1/teams/${id}/connections/${cid}`),
            audit:      (id, opts)              => rc.get(`/api/v1/teams/${id}/audit` + _qs(opts)),
            auditActions:(id)                   => rc.get(`/api/v1/teams/${id}/audit/actions`),
            // Team workflows
            workflows:       (id, opts)         => rc.get(`/api/v1/teams/${id}/workflows` + _qs(opts)),
            createWorkflow:  (id, data)         => rc.post(`/api/v1/teams/${id}/workflows`, data),
            getWorkflow:     (id, wfId)         => rc.get(`/api/v1/teams/${id}/workflows/${wfId}`),
            updateWorkflow:  (id, wfId, data)   => rc.put(`/api/v1/teams/${id}/workflows/${wfId}`, data),
            deleteWorkflow:  (id, wfId)         => rc.del(`/api/v1/teams/${id}/workflows/${wfId}`),
            publishWorkflow: (id, wfId)         => rc.post(`/api/v1/teams/${id}/workflows/${wfId}/publish`, {}),
            // Team workflow stages (v0.37.15 — FE wiring for existing BE routes)
            workflowStages:        (id, wfId)           => rc.get(`/api/v1/teams/${id}/workflows/${wfId}/stages`),
            createWorkflowStage:   (id, wfId, data)     => rc.post(`/api/v1/teams/${id}/workflows/${wfId}/stages`, data),
            updateWorkflowStage:   (id, wfId, sid, data) => rc.put(`/api/v1/teams/${id}/workflows/${wfId}/stages/${sid}`, data),
            deleteWorkflowStage:   (id, wfId, sid)      => rc.del(`/api/v1/teams/${id}/workflows/${wfId}/stages/${sid}`),
            reorderWorkflowStages: (id, wfId, ids)      => rc.patch(`/api/v1/teams/${id}/workflows/${wfId}/stages/reorder`, { ordered_ids: ids }),
            // Adopt global workflows (v0.3.6)
            availableWorkflows:  (id)                 => rc.get(`/api/v1/teams/${id}/workflows/available`),
            adoptWorkflow:       (id, wfId)           => rc.post(`/api/v1/teams/${id}/workflows/${wfId}/adopt`, {}),
        },

        // ── 9. Workflows ───────────────────────
        workflows: {
            ...crud(rc, '/api/v1/workflows'),
            update: (id, data) => rc.patch(`/api/v1/workflows/${id}`, data),
            stages: (id) => rc.get(`/api/v1/workflows/${id}/stages`),
            instances: (id, opts) => rc.get(`/api/v1/workflows/${id}/instances` + _qs(opts)),
            advance:   (id, data) => rc.post(`/api/v1/workflows/${id}/advance`, data),
            reject:    (id, data) => rc.post(`/api/v1/workflows/${id}/reject`, data),
            cancel:    (channelId) => rc.post(`/api/v1/channels/${channelId}/workflow/cancel`, {}),
        },

        // ── 10. Surfaces ──────────────────────
        surfaces: {
            list:    (opts) => rc.get('/api/v1/surfaces' + _qs(opts)),
            get:     (id)   => rc.get(`/api/v1/surfaces/${id}`),
            install: (id)   => rc.post(`/api/v1/surfaces/${id}/install`, {}),
        },

        // ── 18. Admin ──────────────────────────
        admin: {
            stats:     ()     => rc.get('/api/v1/admin/stats'),

            users: {
                list:          (opts)              => rc.get('/api/v1/admin/users' + _qs(opts)),
                create:        (data)              => rc.post('/api/v1/admin/users', data),
                del:           (id)                => rc.del(`/api/v1/admin/users/${id}`),
                resetPassword: (id, pw)            => rc.post(`/api/v1/admin/users/${id}/reset-password`, { password: pw }),
                updateRole:    (id, isAdmin)       => rc.put(`/api/v1/admin/users/${id}/role`, { is_admin: isAdmin }),
                toggleActive:  (id, active, opts)  => rc.put(`/api/v1/admin/users/${id}/active`, { is_active: active, ...opts }),
                permissions:   (id)                => rc.get(`/api/v1/admin/users/${id}/permissions`),
                resetVault:    (id)                => rc.post(`/api/v1/admin/users/${id}/vault/reset`, {}),
            },

            settings: {
                get:    ()         => rc.get('/api/v1/admin/settings'),
                update: (key, val) => rc.put(`/api/v1/admin/settings/${key}`, val),
                public: ()         => rc.get('/api/v1/settings/public'),
            },

            teams: {
                list:         ()                => rc.get('/api/v1/admin/teams'),
                get:          (id)              => rc.get(`/api/v1/admin/teams/${id}`),
                create:       (data)            => rc.post('/api/v1/admin/teams', data),
                update:       (id, data)        => rc.put(`/api/v1/admin/teams/${id}`, data),
                del:          (id)              => rc.del(`/api/v1/admin/teams/${id}`),
                members:      (id)              => rc.get(`/api/v1/admin/teams/${id}/members`),
                addMember:    (id, userId, role) => rc.post(`/api/v1/admin/teams/${id}/members`, { user_id: userId, role }),
                updateMember: (id, mid, role)   => rc.put(`/api/v1/admin/teams/${id}/members/${mid}`, { role }),
                removeMember: (id, mid)         => rc.del(`/api/v1/admin/teams/${id}/members/${mid}`),
            },

            groups: {
                list:         ()              => rc.get('/api/v1/admin/groups'),
                get:          (id)            => rc.get(`/api/v1/admin/groups/${id}`),
                create:       (data)          => rc.post('/api/v1/admin/groups', data),
                update:       (id, data)      => rc.put(`/api/v1/admin/groups/${id}`, data),
                del:          (id)            => rc.del(`/api/v1/admin/groups/${id}`),
                members:      (id)            => rc.get(`/api/v1/admin/groups/${id}/members`),
                addMember:    (id, userId)    => rc.post(`/api/v1/admin/groups/${id}/members`, { user_id: userId }),
                removeMember: (id, userId)    => rc.del(`/api/v1/admin/groups/${id}/members/${userId}`),
            },

            grants: {
                get:  (type, id)                    => rc.get(`/api/v1/admin/grants/${type}/${id}`),
                set:  (type, id, scope, groups)     => rc.put(`/api/v1/admin/grants/${type}/${id}`, { grant_scope: scope, granted_groups: groups || [] }),
                del:  (type, id)                    => rc.del(`/api/v1/admin/grants/${type}/${id}`),
            },

            permissions: {
                list: () => rc.get('/api/v1/admin/permissions'),
            },

            audit: {
                list:    (opts) => rc.get('/api/v1/admin/audit' + _qs(opts)),
                actions: ()     => rc.get('/api/v1/admin/audit/actions'),
            },

            storage: {
                status:      () => rc.get('/api/v1/admin/storage/status'),
            },

            vault: {
                status: () => rc.get('/api/v1/admin/vault/status'),
            },

            notifications: {
                testEmail:  () => rc.post('/api/v1/admin/notifications/test-email', {}),
                broadcast:  (data) => rc.post('/api/v1/admin/notifications/broadcast', data),
            },

            extensions: {
                list:   ()           => rc.get('/api/v1/admin/extensions'),
                create: (data)       => rc.post('/api/v1/admin/extensions', data),
                update: (id, data)   => rc.put(`/api/v1/admin/extensions/${id}`, data),
                del:    (id)         => rc.del(`/api/v1/admin/extensions/${id}`),
            },

            // v0.38.1: Global connections
            connections: crud(rc, '/api/v1/admin/connections'),

            packages: {
                list:            (opts)     => rc.get('/api/v1/admin/packages' + _qs(opts)),
                get:             (id)       => rc.get(`/api/v1/admin/packages/${id}`),
                install:         (file)     => rc.upload('/api/v1/admin/packages/install', file),
                enable:          (id)       => rc.put(`/api/v1/admin/packages/${id}/enable`, {}),
                disable:         (id)       => rc.put(`/api/v1/admin/packages/${id}/disable`, {}),
                del:             (id)       => rc.del(`/api/v1/admin/packages/${id}`),
                settings:        (id)       => rc.get(`/api/v1/admin/packages/${id}/settings`),
                updateSettings:  (id, data) => rc.put(`/api/v1/admin/packages/${id}/settings`, data),
                dependencies:    (id)       => rc.get(`/api/v1/admin/packages/${id}/dependencies`),  // v0.38.2
                consumers:       (id)       => rc.get(`/api/v1/admin/packages/${id}/consumers`),     // v0.38.2
                registry:        ()         => rc.get('/api/v1/admin/packages/registry'),
                registryInstall: (url)      => rc.post('/api/v1/admin/packages/registry/install', { url }),
            },

            // v0.38.2: Full dependency graph
            dependencies: {
                list: () => rc.get('/api/v1/admin/dependencies'),
            },

            surfaces: {
                list:    ()    => rc.get('/api/v1/admin/surfaces'),
                get:     (id)  => rc.get(`/api/v1/admin/surfaces/${id}`),
                install: (file) => rc.upload('/api/v1/admin/surfaces/install', file),
                enable:  (id)  => rc.put(`/api/v1/admin/surfaces/${id}/enable`, {}),
                disable: (id)  => rc.put(`/api/v1/admin/surfaces/${id}/disable`, {}),
                del:     (id)  => rc.del(`/api/v1/admin/surfaces/${id}`),
            },
        },

        // ── Users ──────────────────────────────
        users: {
            search: (q) => rc.get('/api/v1/users/search' + _qs({ q })),
        },

        presence: {
            heartbeat: () => rc.post('/api/v1/presence/heartbeat', {}),
        },

        groups: {
            mine: () => rc.get('/api/v1/groups/mine'),
        },

        health: () => rc.get('/api/v1/health'),

        // ── Extension-scoped client ──────────
        /**
         * Scoped API client for an extension's surface routes.
         * @param {string} packageId — package slug (e.g. 'tasks')
         * @returns {object} — { get, post, put, del, upload }
         */
        ext(packageId) {
            const base = '/s/' + packageId + '/api';
            return {
                get:    (path, opts) => rc.get(base + path + _qs(opts)),
                post:   (path, data) => rc.post(base + path, data),
                put:    (path, data) => rc.put(base + path, data),
                del:    (path)       => rc.del(base + path),
                upload: (path, file) => rc.upload(base + path, file),
            };
        },
    };
}
