import { apiFetch, apiPath, type ApiSettings, type EffectiveViewProjection } from "@govoplan/core-webui"; export type ViewScopeType = "system" | "tenant"; export type ViewAssignmentScopeType = "system" | "tenant" | "group" | "user"; export type ViewAssignmentMode = "available" | "default" | "required"; export type ViewRevision = { id: string; definition_id: string; revision: number; surface_contract_version: string; visible_surface_ids: string[]; content_hash: string; created_by?: string | null; created_at: string; }; export type ViewDefinition = { id: string; tenant_id?: string | null; scope_type: ViewScopeType; scope_id?: string | null; definition_key: string; name: string; description?: string | null; status: "draft" | "published" | "archived"; current_revision: number; latest_revision: ViewRevision; published_revision?: ViewRevision | null; readonly: boolean; stale_surface_ids: string[]; created_by?: string | null; updated_by?: string | null; created_at: string; updated_at: string; }; export type ViewAssignment = { id: string; tenant_id?: string | null; scope_type: ViewAssignmentScopeType; scope_id?: string | null; definition_id: string; revision_id?: string | null; mode: ViewAssignmentMode; priority: number; is_active: boolean; metadata: Record; created_by?: string | null; updated_by?: string | null; created_at: string; updated_at: string; }; type EffectiveViewApiResponse = { active_view_id?: string | null; active_revision_id?: string | null; active_view_name?: string | null; visible_surface_ids: string[]; locked: boolean; available_views: Array<{ id: string; name: string; description?: string | null; revision_id: string; }>; provenance: Array<{ source: string; scope_type?: string | null; scope_id?: string | null; detail?: string | null; }>; diagnostics?: Array<{ severity: "warning" | "error"; code: string; message: string; surface_ids: string[]; }>; }; function jsonBody(payload: unknown): RequestInit { return { headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }; } function projection(response: EffectiveViewApiResponse): EffectiveViewProjection { return { activeViewId: response.active_view_id ?? null, activeRevisionId: response.active_revision_id ?? null, activeViewName: response.active_view_name ?? null, visibleSurfaceIds: response.visible_surface_ids, locked: response.locked, availableViews: response.available_views.map((view) => ({ id: view.id, name: view.name, description: view.description, revisionId: view.revision_id })), provenance: response.provenance.map((item) => ({ source: item.source, scopeType: item.scope_type, scopeId: item.scope_id, detail: item.detail })), diagnostics: (response.diagnostics ?? []).map((item) => ({ severity: item.severity, code: item.code, message: item.message, surfaceIds: item.surface_ids })) }; } export async function fetchEffectiveView( settings: ApiSettings ): Promise { return projection( await apiFetch( settings, "/api/v1/views/effective", { cache: "no-store" } ) ); } export async function selectEffectiveView( settings: ApiSettings, viewId: string | null ): Promise { return projection( await apiFetch( settings, "/api/v1/views/selection", { method: "PUT", ...jsonBody({ view_id: viewId }) } ) ); } export async function fetchViewDefinitions( settings: ApiSettings, scopeType: ViewScopeType ): Promise { const response = await apiFetch<{ definitions: ViewDefinition[] }>( settings, apiPath("/api/v1/views/definitions", { scope_type: scopeType, include_inherited: scopeType === "tenant" }) ); return response.definitions; } export function createViewDefinition( settings: ApiSettings, payload: { scope_type: ViewScopeType; name: string; description?: string | null; visible_surface_ids: string[]; } ): Promise { return apiFetch(settings, "/api/v1/views/definitions", { method: "POST", ...jsonBody(payload) }); } export function updateViewDefinition( settings: ApiSettings, definitionId: string, payload: { name: string; description?: string | null } ): Promise { return apiFetch(settings, `/api/v1/views/definitions/${definitionId}`, { method: "PATCH", ...jsonBody(payload) }); } export function createViewRevision( settings: ApiSettings, definitionId: string, visibleSurfaceIds: string[] ): Promise { return apiFetch( settings, `/api/v1/views/definitions/${definitionId}/revisions`, { method: "POST", ...jsonBody({ visible_surface_ids: visibleSurfaceIds }) } ); } export function publishViewRevision( settings: ApiSettings, definitionId: string, revisionId: string ): Promise { return apiFetch( settings, `/api/v1/views/definitions/${definitionId}/revisions/${revisionId}/publish`, { method: "POST" } ); } export function archiveViewDefinition( settings: ApiSettings, definitionId: string ): Promise { return apiFetch(settings, `/api/v1/views/definitions/${definitionId}`, { method: "DELETE" }); } export async function fetchViewAssignments( settings: ApiSettings, scopeType: ViewScopeType ): Promise { const response = await apiFetch<{ assignments: ViewAssignment[] }>( settings, apiPath("/api/v1/views/assignments", { scope_type: scopeType, include_inherited: scopeType === "tenant" }) ); return response.assignments; } export function createViewAssignment( settings: ApiSettings, payload: { scope_type: ViewAssignmentScopeType; scope_id?: string | null; definition_id: string; revision_id?: string | null; mode: ViewAssignmentMode; priority: number; is_active: boolean; } ): Promise { return apiFetch(settings, "/api/v1/views/assignments", { method: "POST", ...jsonBody(payload) }); } export function updateViewAssignment( settings: ApiSettings, assignmentId: string, payload: { revision_id?: string | null; mode?: ViewAssignmentMode; priority?: number; is_active?: boolean; } ): Promise { return apiFetch(settings, `/api/v1/views/assignments/${assignmentId}`, { method: "PATCH", ...jsonBody(payload) }); } export function deleteViewAssignment( settings: ApiSettings, assignmentId: string ): Promise { return apiFetch(settings, `/api/v1/views/assignments/${assignmentId}`, { method: "DELETE" }); }