import type { Block, SdkCustomBlock, SdkCustomBlockInput, SiteFont, Theme } from "@riverbankcms/blocks";
import type { CamelizeKeys, DbRow } from "@riverbankcms/db";
import type { ContentTypeRoutingInfo, PublicContentTypeMeta } from "./contentTypes";
import type { SiteRuntimePrivacyPolicy } from "./privacyPolicy";
import type { SitePagePayload } from "./sitePages";
import type { RiverbankSiteConfig } from "./sdkContracts";
import type { SiteAnalyticsSettingsPayload } from "./siteAnalytics";
import type { SiteLayoutResolvedPayload } from "./siteSettings";
/**
 * Content Runtime Contracts
 *
 * These types capture the page/content runtime shapes that need to round-trip through
 * the API package: routes, page records, SDK runtime payloads, and editor-facing
 * content entry details.
 *
 * Note: Do NOT use these API types as validation schemas. They document wire shapes
 * and helper payloads, while dashboard services still own validation and hydration.
 */
export type ContentRouteRecord = {
    id: string;
    draftTitle: string;
    draftPath: string;
    draftSlug: string | null;
    draftStatus: "draft" | "scheduled" | "published" | "archived";
    draftMetaTitle?: string | null;
    draftMetaDescription?: string | null;
    draftUpdatedAt?: string | null;
    publishedTitle?: string | null;
    publishedPath?: string | null;
    publishedSlug?: string | null;
    publishedMetaTitle?: string | null;
    publishedMetaDescription?: string | null;
    publishedAt?: string | null;
    scheduledPublishAt?: string | null;
    scheduledPublishFailedAt?: string | null;
    scheduledPublishLastError?: string | null;
    status?: "draft" | "scheduled" | "published" | "archived";
    ogImageId?: string | null;
};
export type ContentEntryStatus = "draft" | "scheduled" | "published" | "archived";
export type ContentEntryRecord = {
    id: string;
    siteId: string;
    contentTypeId: string;
    routeId: string | null;
    draftVersionId: string | null;
    publishedVersionId: string | null;
    createdAt: string;
    updatedAt: string;
    createdBy: string | null;
    updatedBy: string | null;
};
export type ContentEntrySummary = {
    id: string;
    identifier: string | null;
    title: string;
    status: ContentEntryStatus;
    slug: string | null;
    publishAt: string | null;
    scheduledPublishFailedAt?: string | null;
    scheduledPublishLastError?: string | null;
    updatedAt: string;
    draftTitle: string;
    draftPath: string;
    routeId: string | null;
};
export type FormSummary = {
    id: string;
    name: string;
    slug: string;
    updatedAt: string | null;
};
export type FormRecord = CamelizeKeys<DbRow<"forms">>;
export type PublicFormRecord = Pick<FormRecord, "id" | "siteId" | "name" | "slug" | "schemaJson" | "settingsJson" | "createdAt" | "updatedAt">;
export type FormSubmissionRecord = CamelizeKeys<DbRow<"form_submissions">>;
export type FormSubmissionRectificationAnnotationRecord = CamelizeKeys<DbRow<"form_submission_rectification_annotations">>;
export type FormSubmissionRectificationAnnotation = Pick<FormSubmissionRectificationAnnotationRecord, "id" | "formSubmissionId" | "fieldId" | "fieldLabel" | "originalValueSummary" | "correctedValue" | "note" | "actorUserId" | "supersedesAnnotationId" | "createdAt">;
export type FormSubmissionWithRectificationAnnotations = FormSubmissionRecord & Readonly<{
    rectificationAnnotations: FormSubmissionRectificationAnnotation[];
}>;
export type CreateFormSubmissionRectificationAnnotationRequest = {
    fieldId: string;
    correctedValue: string;
    note: string;
};
export type CreateFormSubmissionRectificationAnnotationResponse = {
    annotation: FormSubmissionRectificationAnnotation;
};
export type ExportFormSubmissionsCsvQuery = {
    since?: string;
    until?: string;
    fields?: string;
    limit?: number;
};
export type ExportFormSubmissionsCsvResponse = Blob;
export type ThemePreferencesRecord = CamelizeKeys<DbRow<"site_theme_preferences">>;
export type ThemeRow = CamelizeKeys<DbRow<"themes">>;
export type ThemeGenerationTurn = {
    message: string;
    themes: Theme[];
};
export type ContentEntryDetail<TContent> = {
    entry: ContentEntryRecord;
    route: ContentRouteRecord | null;
    draftContent: TContent;
    publishedContent: TContent | null;
};
export type ContentEntryDetailResponse<TContent = Record<string, unknown>> = {
    entry: ContentEntryDetail<TContent>;
};
export type RunSdkWorkflowResponse<TContent = Record<string, unknown>> = {
    workflow: {
        runId: string;
        id: string;
        status: "running" | "succeeded";
        summary?: string | null;
    };
    entry: WorkflowTargetEntrySnapshot<TContent>;
};
export type WorkflowTargetEntrySnapshot<TContent = Record<string, unknown>> = WorkflowContentEntryTargetSnapshot<TContent> | WorkflowPageTargetSnapshot;
export type WorkflowContentEntryTargetSnapshot<TContent = Record<string, unknown>> = {
    id: string;
    kind: "content-entry";
    routeId: string | null;
    draftContent: TContent;
    publishedContent: TContent | null;
};
export type WorkflowPageStatus = "draft" | "scheduled" | "published" | "archived";
export type WorkflowPageDraftContent = {
    draftTitle: string;
    draftSlug: string | null;
    draftStatus: WorkflowPageStatus;
    scheduledPublishAt: string | null;
    draftMetaTitle: string | null;
    draftMetaDescription: string | null;
    canonicalUrl: string | null;
    ogImageId: string | null;
};
export type WorkflowPagePublishedContent = {
    title: string;
    slug: string | null;
    status: WorkflowPageStatus;
    publishedAt: string | null;
    metaTitle: string | null;
    metaDescription: string | null;
    canonicalUrl: string | null;
    ogImageId: string | null;
};
export type WorkflowPageTargetSnapshot = {
    id: string;
    kind: "page";
    routeId: string;
    draftContent: WorkflowPageDraftContent;
    publishedContent: WorkflowPagePublishedContent | null;
};
export type WorkflowRunStatusResponse = {
    run: {
        id: string;
        workflowId: string;
        status: "created" | "running" | "succeeded" | "failed" | "cancelled";
        summary: string | null;
        error: string | null;
        externalJobId: string | null;
        updatedAt: string;
    };
};
export type SdkWorkflowRunStatusCallbackRequest = {
    status: "running" | "succeeded" | "failed" | "cancelled";
    summary?: string | null;
    error?: string | null;
    externalJobId?: string | null;
    draftContentPatch?: Record<string, unknown>;
};
export type SdkWorkflowRunStatusCallbackResponse = WorkflowRunStatusResponse;
export type BookingsEventSeriesContentEditorResponse = {
    contentType: {
        id: string;
        key: string;
        name: string;
        parsedSchema: unknown;
    };
    initialDetail: ContentEntryDetail<Record<string, unknown>>;
    site: {
        slug: string | null;
        title: string | null;
    };
    theme: Theme | null;
    paletteTokens?: Record<string, string>;
    referenceContentTypeKeys: readonly string[];
    entryTitle: string;
};
export type CustomBlockListItem = {
    id: string;
    blockId: string;
    title: string;
    category: string;
    description: string | null;
    icon: string | null;
    tags: string[];
    version: number;
    isEnabled: boolean;
    hasLayout: boolean;
    createdAt: string;
    updatedAt: string;
};
export type CustomBlockDetail = {
    id: string;
    blockId: string;
    manifest: SdkCustomBlock;
    title: string;
    category: string;
    description: string | null;
    icon: string | null;
    tags: string[];
    version: number;
    isEnabled: boolean;
    sdkSyncedAt: string | null;
    createdAt: string;
    updatedAt: string;
};
export type ListCustomBlocksResponse = {
    blocks: CustomBlockListItem[];
};
export type CreateCustomBlockRequest = {
    manifest: SdkCustomBlockInput;
};
export type CreateCustomBlockResponse = {
    block: CustomBlockListItem;
};
export type GetCustomBlockResponse = {
    block: CustomBlockDetail;
};
export type UpdateCustomBlockRequest = {
    manifest: SdkCustomBlockInput;
};
export type UpdateCustomBlockResponse = {
    block: CustomBlockDetail;
};
export type DeleteCustomBlockResponse = {
    deleted: true;
};
export type PageRouteRecord = ContentRouteRecord & {
    canonicalUrl?: string | null;
    draftUpdatedAt?: string | null;
    createdAt?: string | null;
    createdBy?: string | null;
    updatedAt?: string | null;
    updatedBy?: string | null;
};
export type PageRecord = {
    id: string;
    siteId: string;
    routeId: string;
    purpose: string;
    title: string;
    draftTitle: string;
    path: string;
    draftPath: string;
    slug: string | null;
    draftSlug: string | null;
    status: ContentEntryStatus;
    draftStatus: ContentEntryStatus;
    publishedAt: string | null;
    scheduledPublishAt?: string | null;
    scheduledPublishFailedAt?: string | null;
    scheduledPublishLastError?: string | null;
    draftUpdatedAt: string | null;
    draftMetaTitle: string | null;
    draftMetaDescription: string | null;
    publishedMetaTitle: string | null;
    publishedMetaDescription: string | null;
    ogImageId: string | null;
    createdAt: string;
    updatedAt: string;
    deletedAt: string | null;
    route: PageRouteRecord | null;
};
/**
 * Page record shape used by dashboard page editor mutations (publish/discard).
 *
 * Note: This mirrors the runtime shape returned by `apps/dashboard` page helpers,
 * where routing metadata lives on site_routes and is flattened onto the page record.
 */
export type PageDraftRecord = {
    id: string;
    siteId: string;
    userId: string;
    purpose: string;
    routeId: string;
    identifier: string | null;
    createdAt: string;
    updatedAt: string;
    deletedAt: string | null;
    deletedBy: string | null;
    status: ContentEntryStatus;
    draftStatus: ContentEntryStatus;
    publishedPath: string;
    draftPath: string;
    publishedTitle: string;
    draftTitle: string;
    publishedSlug: string | null;
    draftSlug: string | null;
    publishedAt: string | null;
    scheduledPublishAt: string | null;
    scheduledPublishFailedAt?: string | null;
    scheduledPublishLastError?: string | null;
    draftUpdatedAt: string | null;
    publishedMetaTitle: string | null;
    draftMetaTitle: string | null;
    publishedMetaDescription: string | null;
    draftMetaDescription: string | null;
    ogImageId: string | null;
    canonicalUrl: string | null;
    path: string;
    title: string;
    slug: string | null;
};
export type NavigationMenuRecord = CamelizeKeys<DbRow<"navigation_menus">>;
export type NavigationItemRecord = CamelizeKeys<DbRow<"navigation_items">>;
export type NavigationMenuWithItems = NavigationMenuRecord & {
    items: NavigationItemRecord[];
};
export type SiteBySlugResponse = {
    site: {
        id: string;
        title: string;
        slug: string;
        created_at: string;
        updated_at: string;
        launched_at: string | null;
        maintenance_mode_enabled?: boolean | undefined;
        maintenance_mode_message?: unknown | null | undefined;
        deployment_mode?: "managed" | "headless_cms" | "headless_full" | null | undefined;
        is_sdk_site?: boolean | null | undefined;
    };
    favicon?: {
        assetId: string;
        url: string;
        mimeType: string;
    } | null;
    theme: Theme;
    themeId?: string | null;
    selectionId?: string | null;
    /**
     * Persisted Style configurator selections (Phase C). Optional so legacy
     * site_theme_selections rows (pre-migration) still satisfy the response
     * type — consumers fall back to the site style's defaults when null.
     */
    selectionButtonPersonalityId?: string | null;
    selectionPaletteVariantId?: string | null;
    selectionPaletteOverrides?: Record<string, string> | null;
    navigation: NavigationMenuWithItems[];
    /** Whether portal navigation links should be rendered for this site. */
    portalEnabled?: boolean;
    /** Whether cart navigation links should render for this site. */
    commerceEnabled?: boolean;
    /** Site-level analytics settings used by frontend consent/runtime behavior. */
    analytics?: SiteAnalyticsSettingsPayload;
    /** Managed privacy policy data for frontend runtime rendering. */
    privacyPolicy?: SiteRuntimePrivacyPolicy;
    routes: Record<string, {
        path: string;
        draftPath: string | null;
        status: string | null;
        draftStatus?: string | null;
        publishedAt?: string | null;
    }>;
    layout: SiteLayoutResolvedPayload;
    customDomain: string | null;
    sdkConfig?: RiverbankSiteConfig | null;
    /** Custom blocks stored in DB (declarative manifests, enabled only) */
    customBlocks?: SdkCustomBlock[];
    /** SDK-managed footer blocks list (single global list for layout rendering) */
    footerBlocks?: Block[];
    /** Supabase storage URL for direct image access (SDK sites use this instead of env var) */
    supabaseUrl?: string;
    /** Content types for routing decisions (SDK uses this to detect event occurrences, etc.) */
    contentTypes?: ContentTypeRoutingInfo[];
    /**
     * Page identifier to routeId lookup for CTA link resolution.
     * Used by SDK to resolve { kind: 'page', identifier } links at render time.
     */
    pagesByIdentifier?: Record<string, string>;
    /**
     * Entry identifier to routeId lookup for CTA link resolution.
     * Maps `contentTypeKey` -> `identifier` -> `routeId`.
     * Used by SDK to resolve { kind: 'entry', contentType, identifier } links at render time.
     */
    entriesByIdentifier?: Record<string, Record<string, string>>;
    /** True if site has uploaded custom fonts */
    hasCustomFonts?: boolean;
    /** Custom fonts uploaded for this site (for use with ThemeFontLoader) */
    fonts?: SiteFont[];
    /** Pending Google Search Console verification token (for meta tag injection on homepage) */
    googleSiteVerificationToken?: string | null;
};
export type BlockListItem = {
    id: string;
    kind: string;
    purpose?: string | null;
    orderIndex?: number | null;
    content?: Record<string, unknown> | null;
    draftContent?: Record<string, unknown> | null;
    publishedContent?: Record<string, unknown> | null;
};
export type PublishedBlockBaseline = {
    id: string;
    kind: string;
    publishedContent: Record<string, unknown> | null;
};
export type ContentEntryOrPageResponse<TContent = Record<string, unknown>> = ContentEntryDetailResponse<TContent> | {
    entry: PageRecord;
};
export type ScheduledContentEntryOrPageResponse<TContent = Record<string, unknown>> = ({
    kind: "content";
} & ContentEntryDetailResponse<TContent>) | {
    kind: "page";
    entry: PageRecord;
};
export type PublishedContentEntryOrPageResponse<TContent = Record<string, unknown>> = ContentEntryDetailResponse<TContent> | {
    entry: PageRecord;
    publishedBlocks?: PublishedBlockBaseline[];
};
export type PublishedContentEntryPreview = {
    id: string;
    title: string;
    slug: string;
    path: string;
    excerpt: string;
    publishedAt: string | null;
    image: {
        url?: string | null;
        alt?: string | null;
    } | null;
};
export type PublishedContentEntryPreviewResponse = {
    data: PublishedContentEntryPreview | null;
};
export type PublishedPostPreview = PublishedContentEntryPreview;
export type PublishedPostPreviewResponse = PublishedContentEntryPreviewResponse;
export type ContentEntryListStage = "published" | "preview";
/**
 * Normalized media shape for entry images in API responses.
 * Contains only the essential fields needed for display.
 */
export type EntryImage = {
    url?: string | null;
    alt?: string | null;
} | null;
export type ContentEntryListItem<TContent = Record<string, unknown>> = {
    id: string;
    slug: string | null;
    path: string;
    title: string;
    status: ContentEntryStatus;
    publishedAt: string | null;
    content: TContent;
    excerpt: string;
    image: EntryImage;
    routeId: string | null;
};
export type ListPublishedEntriesMeta = {
    total: number;
    limit: number;
    offset: number;
    hasMore: boolean;
};
export type ListPublishedEntriesResponse<TContent = Record<string, unknown>> = {
    entries: ContentEntryListItem<TContent>[];
    meta?: ListPublishedEntriesMeta;
    contentType?: PublicContentTypeMeta | null;
};
/**
 * Block content as returned by SDK page/entry loaders.
 *
 * Note: draft/published content can contain hydrated structures; treat as `unknown` at the API layer
 * unless/until we formalize the hydrated content schema.
 */
export type SdkBlockContent = {
    id: string;
    blockId: string;
    pageId: string;
    kind: string;
    purpose: string;
    orderIndex: number;
    content: Record<string, unknown>;
    draftContent: unknown | null;
    publishedContent: unknown | null;
    draftContentId: string | null;
    publishedContentId: string | null;
};
export type SdkTemplateAddon = {
    addonKey: string;
    enabled: boolean;
    metadata: Record<string, unknown> | null;
};
export type SdkTemplateBlock = {
    id: string;
    orderIndex: number;
    blockKind: string;
    scope: "template" | "entry";
    content: Record<string, unknown> | null;
    bindings: Record<string, unknown> | null;
    dataDependencies: Record<string, unknown> | null;
};
export type SdkTemplate = {
    id: string;
    contentTypeId: string;
    contentTypeKey: string | null;
    templateKey: string;
    name: string;
    description: string | null;
    isDefault: boolean;
    metadata: Record<string, unknown> | null;
    addons: SdkTemplateAddon[];
    blocks: SdkTemplateBlock[];
};
export type SdkRuntimePage = {
    id: string;
    purpose: string;
    createdAt: string;
    updatedAt: string;
    name: string;
    path: string;
    status: string;
    draftStatus: string;
    publishedAt: string | null;
    draftUpdatedAt: string | null;
    draftTitle: string;
    draftPath: string;
    draftMetaTitle: string | null;
    draftMetaDescription: string | null;
    publishedMetaTitle: string | null;
    publishedMetaDescription: string | null;
    ogImageId: string | null;
    ogImageUrl: string | null;
    canonicalUrl: string | null;
    routeId: string | null;
    blocks: SdkBlockContent[];
};
export type SdkRuntimeMediaAsset = {
    id: string;
    identifier: string | null;
    storageBucket: string;
    storagePath: string;
    width: number | null;
    height: number | null;
    mimeType: string;
};
export type SdkRuntimePageResponse = {
    page: SdkRuntimePage;
    templates?: SdkTemplate[];
    mediaAssets?: SdkRuntimeMediaAsset[];
};
export type SdkRuntimeEntry = {
    id: string;
    routeId: string | null;
    type: string | null;
    title: string;
    slug: string | null;
    status: string;
    publishAt: string | null;
    path: string | null;
    draftPath: string | null;
    content: Record<string, unknown>;
    draftContent: Record<string, unknown> | null;
    publishedContent: Record<string, unknown> | null;
    metaTitle: string | null;
    draftMetaTitle: string | null;
    metaDescription: string | null;
    draftMetaDescription: string | null;
    ogImageId: string | null;
    ogImageUrl: string | null;
    canonicalUrl: string | null;
    createdAt: string;
    updatedAt: string;
};
export type SdkRuntimeEntryResponse = {
    entry: SdkRuntimeEntry;
    templates: SdkTemplate[];
    contentTypeSchema: Record<string, unknown> | null;
    mediaAssets?: SdkRuntimeMediaAsset[];
};
export type SdkRuntimeContentByPathResponse = (SdkRuntimePageResponse & {
    type?: "page";
}) | (SdkRuntimeEntryResponse & {
    type: "entry";
});
export type BlockWithContentResponse = {
    id: string;
    kind: string;
    siteId: string;
    pageId: string | null;
    draftContentId: string | null;
    publishedContentId: string | null;
    draftContent: Record<string, unknown> | null;
    publishedContent: Record<string, unknown> | null;
};
export type ContentDataResponse = {
    page: SitePagePayload;
    type?: never;
} | {
    type: "entry";
    entry: ContentEntryRecord & {
        title: string;
        slug: string | null;
        path: string | null;
        status: ContentEntryStatus;
        publishAt?: string | null;
        publish_at?: string | null;
        content: Record<string, unknown> | null;
        type?: string | null;
        contentTypeKey?: string | null;
        content_type_key?: string | null;
    };
    templates: Array<{
        id: string;
        contentTypeKey?: string;
        content_type_key?: string;
        isDefault?: boolean;
        is_default?: boolean;
        blocks: Array<{
            id: string;
            blockKind: string;
            block_kind?: string;
            content: Record<string, unknown> | null;
            bindings: Record<string, unknown> | null;
        }>;
    }>;
};
