"use strict";
/**
 * Relationship Resolver
 *
 * Resolves JSON relationship definitions to frontend representations
 * including form fields, imports, and service methods.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.FOUNDATION_CORE_PACKAGE = exports.FOUNDATION_COMPONENTS_PACKAGE = void 0;
exports.isFoundationImport = isFoundationImport;
exports.resolveRelationship = resolveRelationship;
exports.resolveRelationships = resolveRelationships;
exports.mapDirectoryToWebPath = mapDirectoryToWebPath;
exports.generateServiceMethods = generateServiceMethods;
exports.getSelectorImports = getSelectorImports;
exports.getRelationshipFormJsx = getRelationshipFormJsx;
exports.getDefaultValueExpression = getDefaultValueExpression;
exports.getPayloadMapping = getPayloadMapping;
const field_mapping_types_1 = require("../types/field-mapping.types");
const name_transformer_1 = require("./name-transformer");
const field_mapper_1 = require("./field-mapper");
/**
 * Foundation package constants for web imports
 * Components (selectors) come from /components
 * Data (interfaces, services) come from /core
 */
exports.FOUNDATION_COMPONENTS_PACKAGE = "@carlonicora/nextjs-jsonapi/components";
exports.FOUNDATION_CORE_PACKAGE = "@carlonicora/nextjs-jsonapi/core";
/**
 * Check if a directory represents a foundation import (from the package)
 *
 * @param directory - The directory string from relationship definition
 * @returns True if this should import from the foundation package
 */
function isFoundationImport(directory) {
    return directory === "@foundation" || directory.startsWith("@foundation/");
}
/**
 * Resolve a JSON relationship to frontend representation
 *
 * @param rel - JSON relationship definition
 * @returns Frontend relationship representation
 */
function resolveRelationship(rel) {
    const isAuthor = rel.variant === field_mapping_types_1.AUTHOR_VARIANT;
    const effectiveName = rel.variant || rel.name;
    const effectiveNameLower = (0, name_transformer_1.toCamelCase)(effectiveName);
    const modelKebab = (0, name_transformer_1.toKebabCase)(rel.name);
    // Form field ID
    const formFieldId = effectiveNameLower;
    const formFieldIdPlural = (0, name_transformer_1.pluralize)(effectiveNameLower);
    // Payload field ID for API calls
    let payloadFieldId;
    if (rel.single) {
        payloadFieldId = `${effectiveNameLower}Id`;
    }
    else {
        payloadFieldId = `${(0, name_transformer_1.toCamelCase)(rel.name)}Ids`;
    }
    // Selector component name
    // Foundation components use MultiSelect, generated modules use MultiSelector
    let selectorComponent;
    if (rel.single) {
        selectorComponent = `${rel.name}Selector`;
    }
    else {
        selectorComponent = isFoundationImport(rel.directory)
            ? `${rel.name}MultiSelect`
            : `${rel.name}MultiSelector`;
    }
    // Zod schema
    let zodSchema;
    if (isAuthor) {
        zodSchema = rel.nullable
            ? `${field_mapping_types_1.AUTHOR_ZOD_SCHEMA}.optional()`
            : `${field_mapping_types_1.AUTHOR_ZOD_SCHEMA}.refine((data) => data.id && data.id.length > 0, { message: t(\`generic.relationships.author.error\`) })`;
    }
    else if (rel.single) {
        zodSchema = rel.nullable
            ? `${field_mapping_types_1.ENTITY_ZOD_SCHEMA}.optional()`
            : `${field_mapping_types_1.ENTITY_ZOD_SCHEMA}.refine((data) => data.id && data.id.length > 0, { message: t(\`generic.relationships.${effectiveNameLower}.error\`) })`;
    }
    else {
        zodSchema = rel.nullable ? `z.array(${field_mapping_types_1.ENTITY_ZOD_SCHEMA}).optional()` : `z.array(${field_mapping_types_1.ENTITY_ZOD_SCHEMA})`;
    }
    // Import paths - check for foundation imports
    let importPath;
    let interfaceImportPath;
    let serviceImportPath;
    if (isFoundationImport(rel.directory)) {
        // Foundation entities import from the package
        importPath = exports.FOUNDATION_COMPONENTS_PACKAGE; // Selectors from /components
        interfaceImportPath = exports.FOUNDATION_CORE_PACKAGE; // Interfaces from /core
        serviceImportPath = exports.FOUNDATION_CORE_PACKAGE; // Services from /core
    }
    else {
        // Feature entities use local paths
        const webDirectory = mapDirectoryToWebPath(rel.directory);
        importPath = `@/features/${webDirectory}/${modelKebab}/components/forms/${selectorComponent}`;
        interfaceImportPath = `@/features/${webDirectory}/${modelKebab}/data/${rel.name}Interface`;
        serviceImportPath = `@/features/${webDirectory}/${modelKebab}/data/${rel.name}Service`;
    }
    // Map relationship fields (only for single relationships)
    let fields;
    if (rel.single && rel.fields && rel.fields.length > 0) {
        fields = (0, field_mapper_1.mapFields)(rel.fields, (0, name_transformer_1.toCamelCase)(rel.name));
    }
    return {
        name: rel.name,
        variant: rel.variant,
        directory: rel.directory,
        single: rel.single,
        nullable: rel.nullable,
        isFoundation: isFoundationImport(rel.directory),
        formFieldId,
        formFieldIdPlural,
        payloadFieldId,
        selectorComponent,
        zodSchema,
        importPath,
        interfaceImportPath,
        serviceImportPath,
        interfaceName: `${rel.name}Interface`,
        modelKebab,
        fields,
    };
}
/**
 * Resolve all relationships from JSON schema
 *
 * @param relationships - Array of JSON relationship definitions
 * @returns Array of frontend relationship representations
 */
function resolveRelationships(relationships) {
    return relationships.map(resolveRelationship);
}
/**
 * Map directory value to web path
 * Strips the leading "features/" or "foundations/" prefix since @/features/ already includes it
 *
 * @param directory - Directory value from JSON (e.g., "features/expertise")
 * @returns Web path segment without the base prefix (e.g., "expertise")
 */
function mapDirectoryToWebPath(directory) {
    const segments = directory.split("/");
    // Remove "features" or "foundations" prefix since @/features/ already includes it
    if (segments[0] === "features" || segments[0] === "foundations") {
        return segments.slice(1).join("/");
    }
    return directory;
}
/**
 * Generate service method definitions for relationships
 *
 * @param relationships - Array of frontend relationships
 * @returns Array of service method definitions
 */
function generateServiceMethods(relationships) {
    return relationships.map((rel) => {
        const effectiveName = rel.variant || rel.name;
        return {
            methodName: `findManyBy${(0, name_transformer_1.toPascalCase)(effectiveName)}`,
            paramName: `${(0, name_transformer_1.toCamelCase)(effectiveName)}Id`,
            relationshipName: rel.name,
            relationshipEndpoint: (0, name_transformer_1.pluralize)((0, name_transformer_1.toKebabCase)(rel.name)),
        };
    });
}
/**
 * Get unique selector imports needed for the editor
 *
 * @param relationships - Array of frontend relationships
 * @returns Deduplicated array of import statements
 */
function getSelectorImports(relationships) {
    const imports = new Set();
    relationships.forEach((rel) => {
        if (isFoundationImport(rel.directory)) {
            // Foundation entities use named imports from the package
            imports.add(`import { ${rel.selectorComponent} } from "${exports.FOUNDATION_COMPONENTS_PACKAGE}";`);
        }
        else {
            imports.add(`import ${rel.selectorComponent} from "${rel.importPath}";`);
        }
    });
    return Array.from(imports);
}
/**
 * Get form JSX for a relationship field
 *
 * @param rel - Frontend relationship
 * @param moduleName - Module name for i18n keys
 * @returns JSX code for the relationship selector
 */
function getRelationshipFormJsx(rel, moduleName) {
    const isRequired = !rel.nullable;
    const lowerModuleName = moduleName.toLowerCase();
    if (rel.single) {
        // Single selector
        if (rel.variant === field_mapping_types_1.AUTHOR_VARIANT) {
            // Author is auto-set, usually not shown in form or read-only
            return "";
        }
        return `<${rel.name}Selector
  id="${rel.formFieldId}"
  form={form}
  label={t(\`generic.relationships.${rel.formFieldId}.label\`)}
  placeholder={t(\`generic.relationships.${rel.formFieldId}.placeholder\`)}
  ${isRequired ? "isRequired" : ""}
/>`;
    }
    else {
        // Multi selector
        return `<${rel.name}MultiSelector
  id="${rel.formFieldId}"
  form={form}
  label={t(\`types.${(0, name_transformer_1.pluralize)((0, name_transformer_1.toKebabCase)(rel.name))}\`, { count: 2 })}
/>`;
    }
}
/**
 * Get default value expression for a relationship in form
 *
 * @param rel - Frontend relationship
 * @param modelVarName - Variable name for the model (e.g., "article")
 * @returns Expression for default value
 */
function getDefaultValueExpression(rel, modelVarName) {
    const propertyName = rel.variant ? (0, name_transformer_1.toCamelCase)(rel.variant) : (0, name_transformer_1.toCamelCase)(rel.name);
    const pluralPropertyName = (0, name_transformer_1.pluralize)(propertyName);
    if (rel.single) {
        if (rel.variant === field_mapping_types_1.AUTHOR_VARIANT) {
            // Author has special shape with avatar
            return `${modelVarName}?.${propertyName}
        ? { id: ${modelVarName}.${propertyName}.id, name: ${modelVarName}.${propertyName}.name, avatar: ${modelVarName}.${propertyName}.avatar }
        : undefined`;
        }
        return `${modelVarName}?.${propertyName}
        ? { id: ${modelVarName}.${propertyName}.id, name: ${modelVarName}.${propertyName}.name }
        : undefined`;
    }
    else {
        // Multi-select
        return `${modelVarName}?.${pluralPropertyName}
        ? ${modelVarName}.${pluralPropertyName}.map((item) => ({ id: item.id, name: item.name }))
        : []`;
    }
}
/**
 * Get payload mapping for a relationship
 *
 * @param rel - Frontend relationship
 * @returns Payload field assignment code
 */
function getPayloadMapping(rel) {
    if (rel.single) {
        return `${rel.payloadFieldId}: values.${rel.formFieldId}?.id`;
    }
    else {
        return `${rel.payloadFieldId}: values.${rel.formFieldId} ? values.${rel.formFieldId}.map((item) => item.id) : []`;
    }
}
//# sourceMappingURL=relationship-resolver.js.map