import { z } from 'zod';

/**
 * Configuration for a content type defined by the developer.
 *
 * Field types are now specified directly in the Zod schema via .meta():
 * @example
 * ```typescript
 * const ProductSchema = z.object({
 *   description: z.string().meta({ fieldType: "textarea" }),
 *   image: z.string().optional().meta({ fieldType: "file" }),
 * });
 * ```
 */
interface ContentTypeConfig {
    /** Display name for the content type (e.g., "Product", "Testimonial") */
    name: string;
    /** URL-friendly slug (e.g., "product", "testimonial") */
    slug: string;
    /** Optional description shown in the admin UI */
    description?: string;
    /** Zod schema defining the content type's fields. Use .meta({ fieldType: "..." }) for field type overrides. */
    schema: z.ZodObject<z.ZodRawShape>;
}
/**
 * Content type stored in the database
 */
type ContentType = {
    id: string;
    /** Display name */
    name: string;
    /** URL-friendly slug - unique identifier */
    slug: string;
    /** Optional description */
    description?: string;
    /** JSON Schema representation of the Zod schema (stringified) */
    jsonSchema: string;
    /** @deprecated Legacy field config - now embedded in jsonSchema. Kept for backwards compat. */
    fieldConfig?: string;
    /** AutoForm schema version. 1 = legacy (separate fieldConfig), 2 = unified (fieldType in jsonSchema) */
    autoFormVersion?: number;
    createdAt: Date;
    updatedAt: Date;
};
/**
 * Content item stored in the database
 */
type ContentItem = {
    id: string;
    /** Reference to the content type */
    contentTypeId: string;
    /** URL-friendly slug - unique within content type */
    slug: string;
    /** JSON data matching the content type's schema (stringified) */
    data: string;
    /** Optional author ID for tracking who created/modified */
    authorId?: string;
    createdAt: Date;
    updatedAt: Date;
};
/**
 * Content item with its content type joined
 */
type ContentItemWithType = ContentItem & {
    contentType?: ContentType;
};
/**
 * Represents an inverse relation (content types that reference this type via belongsTo)
 */
interface InverseRelation {
    /** The content type slug that has the belongsTo relation */
    sourceType: string;
    /** Display name of the source content type */
    sourceTypeName: string;
    /** The field name that contains the belongsTo relation */
    fieldName: string;
    /** Count of items with this relation (when itemId is provided) */
    count: number;
}
/**
 * Serialized content type for API responses (dates as strings)
 */
interface SerializedContentType extends Omit<ContentType, "createdAt" | "updatedAt"> {
    createdAt: string;
    updatedAt: string;
}
/**
 * Serialized content item for API responses (dates as strings)
 */
interface SerializedContentItem extends Omit<ContentItem, "createdAt" | "updatedAt"> {
    createdAt: string;
    updatedAt: string;
}
/**
 * Serialized content item with parsed data and joined content type
 * @template TData - The type of the parsed data (defaults to Record<string, unknown>)
 */
interface SerializedContentItemWithType<TData = Record<string, unknown>> extends SerializedContentItem {
    /** Parsed data object (JSON.parse of data field). */
    parsedData: TData;
    /** Joined content type */
    contentType?: SerializedContentType;
    /**
     * Populated relation data (only present when using populated endpoints/hooks).
     * Keys are field names, values are arrays of related content items.
     */
    _relations?: Record<string, SerializedContentItemWithType[]>;
}
/**
 * Paginated list response for content items
 * @template TData - The type of the parsed data (defaults to Record<string, unknown>)
 */
interface PaginatedContentItems<TData = Record<string, unknown>> {
    items: SerializedContentItemWithType<TData>[];
    total: number;
    limit: number;
    offset: number;
}
/**
 * Context passed to CMS backend hooks
 */
interface CMSHookContext {
    /** Content type slug */
    typeSlug: string;
    /** User ID if authenticated */
    userId?: string;
    /** Request headers */
    headers?: Headers;
}
/**
 * Hooks for customizing CMS backend behavior
 *
 * Note: Before hooks deny operations by throwing an error.
 * They cannot modify the data being saved. This ensures consistency
 * between the stored content item data and relation junction tables.
 */
interface CMSBackendHooks {
    /** Called before creating a content item. Throw an error to deny the operation. */
    onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<void> | void;
    /** Called after creating a content item */
    onAfterCreate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
    /** Called before updating a content item. Throw an error to deny the operation. */
    onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<void> | void;
    /** Called after updating a content item */
    onAfterUpdate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
    /** Called before deleting a content item. Throw an error to deny the operation. */
    onBeforeDelete?: (id: string, context: CMSHookContext) => Promise<void> | void;
    /** Called after deleting a content item */
    onAfterDelete?: (id: string, context: CMSHookContext) => Promise<void> | void;
    /** Called on any CMS error */
    onError?: (error: Error, operation: "create" | "update" | "delete" | "list" | "get", context: CMSHookContext) => Promise<void> | void;
}
/**
 * Configuration for the CMS backend plugin
 */
interface CMSBackendConfig {
    /** Content types defined by the developer */
    contentTypes: ContentTypeConfig[];
    /** Optional hooks for customizing behavior */
    hooks?: CMSBackendHooks;
}

export type { ContentTypeConfig as C, InverseRelation as I, PaginatedContentItems as P, SerializedContentType as S, SerializedContentItemWithType as a, ContentType as b, ContentItem as c, SerializedContentItem as d, ContentItemWithType as e, CMSBackendConfig as f };
