/**
 * @module step-relationships.component
 * @description Step 3 — optional foreign key relationship definitions.
 *
 * Presents one card per FK row. Each card has cascading dropdowns:
 *   Source Column → Target Schema → Target Table → Target Column → FK Type
 *
 * All FK target data comes from `Metadata.Entities` (already in-memory at login),
 * so every dropdown is synchronous — no async loading needed.
 *
 * Phase C: FK source columns are no longer restricted to UUID type — any column
 * may be used as a FK source.  When the user selects a target column, the
 * component reads its SQL type and auto-selects the first source column whose
 * type matches, improving UX and preventing silent type mismatches.
 */
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ChangeDetectorRef, inject, } from '@angular/core';
import { Metadata } from '@memberjunction/core';
import { UUIDsEqual } from '@memberjunction/global';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@memberjunction/ng-ui-components";
const _forTrack0 = ($index, $item) => $item.Name;
const _forTrack1 = ($index, $item) => $item.ID;
function StepRelationshipsComponent_Conditional_4_For_2_For_14_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "option", 17);
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const col_r4 = ctx.$implicit;
    i0.ɵɵproperty("value", col_r4.Name);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(col_r4.Name);
} }
function StepRelationshipsComponent_Conditional_4_For_2_For_22_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "option", 17);
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const schema_r5 = ctx.$implicit;
    i0.ɵɵproperty("value", schema_r5);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(schema_r5);
} }
function StepRelationshipsComponent_Conditional_4_For_2_For_30_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "option", 17);
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const entity_r6 = ctx.$implicit;
    i0.ɵɵproperty("value", entity_r6.ID);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(entity_r6.BaseTable);
} }
function StepRelationshipsComponent_Conditional_4_For_2_For_38_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "option", 17);
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const col_r7 = ctx.$implicit;
    i0.ɵɵproperty("value", col_r7.Name);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate2("", col_r7.Name, " (", col_r7.SqlType, ")");
} }
function StepRelationshipsComponent_Conditional_4_For_2_Template(rf, ctx) { if (rf & 1) {
    const _r1 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 7)(1, "div", 8)(2, "span", 9);
    i0.ɵɵtext(3);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "button", 10);
    i0.ɵɵlistener("click", function StepRelationshipsComponent_Conditional_4_For_2_Template_button_click_4_listener() { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.DeleteRow(row_r2.rowIndex)); });
    i0.ɵɵelement(5, "i", 11);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(6, "div", 12)(7, "div", 13)(8, "label", 14);
    i0.ɵɵtext(9, "Source Column");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(10, "select", 15);
    i0.ɵɵlistener("change", function StepRelationshipsComponent_Conditional_4_For_2_Template_select_change_10_listener($event) { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnSourceColumnChange(row_r2.rowIndex, $event.target.value)); });
    i0.ɵɵelementStart(11, "option", 16);
    i0.ɵɵtext(12);
    i0.ɵɵelementEnd();
    i0.ɵɵrepeaterCreate(13, StepRelationshipsComponent_Conditional_4_For_2_For_14_Template, 2, 2, "option", 17, _forTrack0);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(15, "div", 13)(16, "label", 14);
    i0.ɵɵtext(17, "Target Schema");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(18, "select", 15);
    i0.ɵɵlistener("change", function StepRelationshipsComponent_Conditional_4_For_2_Template_select_change_18_listener($event) { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnSchemaChange(row_r2.rowIndex, $event.target.value)); });
    i0.ɵɵelementStart(19, "option", 16);
    i0.ɵɵtext(20, "\u2014 select schema \u2014");
    i0.ɵɵelementEnd();
    i0.ɵɵrepeaterCreate(21, StepRelationshipsComponent_Conditional_4_For_2_For_22_Template, 2, 2, "option", 17, i0.ɵɵrepeaterTrackByIdentity);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(23, "div", 13)(24, "label", 14);
    i0.ɵɵtext(25, "Target Table");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(26, "select", 18);
    i0.ɵɵlistener("change", function StepRelationshipsComponent_Conditional_4_For_2_Template_select_change_26_listener($event) { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnTableChange(row_r2.rowIndex, $event.target.value)); });
    i0.ɵɵelementStart(27, "option", 16);
    i0.ɵɵtext(28);
    i0.ɵɵelementEnd();
    i0.ɵɵrepeaterCreate(29, StepRelationshipsComponent_Conditional_4_For_2_For_30_Template, 2, 2, "option", 17, _forTrack1);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(31, "div", 13)(32, "label", 14);
    i0.ɵɵtext(33, "Target Column");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(34, "select", 18);
    i0.ɵɵlistener("change", function StepRelationshipsComponent_Conditional_4_For_2_Template_select_change_34_listener($event) { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnColumnChange(row_r2.rowIndex, $event.target.value, row_r2.selectedEntityId)); });
    i0.ɵɵelementStart(35, "option", 16);
    i0.ɵɵtext(36);
    i0.ɵɵelementEnd();
    i0.ɵɵrepeaterCreate(37, StepRelationshipsComponent_Conditional_4_For_2_For_38_Template, 2, 3, "option", 17, _forTrack0);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(39, "div", 13)(40, "label", 14);
    i0.ɵɵtext(41, "FK Type");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(42, "select", 15);
    i0.ɵɵlistener("change", function StepRelationshipsComponent_Conditional_4_For_2_Template_select_change_42_listener($event) { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.OnFkTypeChange(row_r2.rowIndex, $event.target.value === "soft")); });
    i0.ɵɵelementStart(43, "option", 19);
    i0.ɵɵtext(44, "Soft (metadata only)");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(45, "option", 20);
    i0.ɵɵtext(46, "Hard (DB constraint)");
    i0.ɵɵelementEnd()()()()();
} if (rf & 2) {
    const row_r2 = ctx.$implicit;
    const ctx_r2 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate1("Relationship ", row_r2.rowIndex + 1);
    i0.ɵɵadvance(7);
    i0.ɵɵproperty("value", row_r2.ColumnName);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate1("\u2014 auto-create ", row_r2.ColumnName || "\u2014", " \u2014");
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r2.AllColumns);
    i0.ɵɵadvance(5);
    i0.ɵɵproperty("value", row_r2.ReferencedSchema);
    i0.ɵɵadvance(3);
    i0.ɵɵrepeater(ctx_r2.AvailableSchemas);
    i0.ɵɵadvance(5);
    i0.ɵɵproperty("value", row_r2.selectedEntityId)("disabled", !row_r2.ReferencedSchema);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ctx_r2.TablePlaceholder(row_r2));
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r2.EntitiesForSchema(row_r2.ReferencedSchema));
    i0.ɵɵadvance(5);
    i0.ɵɵproperty("value", row_r2.ReferencedColumn)("disabled", !row_r2.selectedEntityId);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ctx_r2.ColumnPlaceholder(row_r2));
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r2.ColumnsForEntity(row_r2.selectedEntityId));
    i0.ɵɵadvance(5);
    i0.ɵɵproperty("value", row_r2.IsSoft ? "soft" : "hard");
} }
function StepRelationshipsComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 3);
    i0.ɵɵrepeaterCreate(1, StepRelationshipsComponent_Conditional_4_For_2_Template, 47, 11, "div", 7, i0.ɵɵcomponentInstance().TrackByIndex, true);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r2 = i0.ɵɵnextContext();
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r2.rows);
} }
// `MJ: Schema Info` only surfaces MJ-registered schemas, so only __mj needs blocking here.
// Server-side RSM.GetAllProtectedSchemas() remains the authoritative gate.
const FRONTEND_BLOCKED_SCHEMAS = new Set(['__mj']);
/** Default referenced column name used when a FK relationship is first created or schema/table changes. */
const DEFAULT_PK_COLUMN = 'ID';
export class StepRelationshipsComponent {
    cdr = inject(ChangeDetectorRef);
    InitialForeignKeys = [];
    AvailableColumns = [];
    ForeignKeysChanged = new EventEmitter();
    /** All Step 2 columns are valid FK source candidates (not just UUID). */
    get AllColumns() {
        return this.AvailableColumns;
    }
    // ─── Metadata-backed synchronous getters ──────────────────────────────────
    /**
     * Sorted schema names present in Metadata.Entities, excluding blocked schemas.
     * `MJ: Schema Info` only surfaces MJ-registered schemas, so __mj is the only
     * schema that needs filtering here.
     */
    get AvailableSchemas() {
        return [...new Set(new Metadata().Entities.map(e => e.SchemaName))] // global-provider-ok: client-side Angular component, single provider
            .filter(s => !FRONTEND_BLOCKED_SCHEMAS.has(s))
            .sort();
    }
    /** Entities that belong to the given schema, sorted by BaseTable. */
    EntitiesForSchema(schemaName) {
        if (!schemaName)
            return [];
        return new Metadata().Entities // global-provider-ok: client-side Angular component, single provider
            .filter(e => e.SchemaName === schemaName)
            .sort((a, b) => a.BaseTable.localeCompare(b.BaseTable));
    }
    /**
     * Physical columns for the entity identified by `entityId`, including SQL type info.
     * Returns `EntityColumnInfo[]` so the template can display `Name (SqlType)` and
     * the component can auto-match source columns by type.
     */
    ColumnsForEntity(entityId) {
        if (!entityId)
            return [];
        const entity = new Metadata().Entities.find(e => UUIDsEqual(e.ID, entityId)); // global-provider-ok: client-side Angular component, single provider
        if (!entity)
            return [{ Name: 'ID', SqlType: 'uniqueidentifier' }];
        return entity.Fields
            .filter(f => !f.IsVirtual)
            .map(f => ({ Name: f.Name, SqlType: f.Type ?? '' }));
    }
    // ─── Placeholder helpers ───────────────────────────────────────────────────
    TablePlaceholder(row) {
        if (!row.ReferencedSchema)
            return '— select schema first —';
        if (this.EntitiesForSchema(row.ReferencedSchema).length === 0)
            return '— no entities in this schema —';
        return '— select table —';
    }
    ColumnPlaceholder(row) {
        if (!row.selectedEntityId)
            return '— select table first —';
        return '— select column —';
    }
    // ─── Row state ─────────────────────────────────────────────────────────────
    rows = [];
    // ─── Cascade handlers ──────────────────────────────────────────────────────
    OnSchemaChange(rowIndex, schema) {
        this.rows = this.rows.map(r => r.rowIndex === rowIndex
            ? { ...r, ReferencedSchema: schema, ReferencedTable: '', ReferencedColumn: DEFAULT_PK_COLUMN, selectedEntityId: '', referencedColumnType: undefined }
            : r);
        this.emit();
    }
    OnTableChange(rowIndex, entityId) {
        if (!entityId) {
            this.rows = this.rows.map(r => r.rowIndex === rowIndex
                ? { ...r, ReferencedTable: '', ReferencedColumn: DEFAULT_PK_COLUMN, selectedEntityId: '', referencedColumnType: undefined }
                : r);
            this.emit();
            return;
        }
        const entity = new Metadata().Entities.find(e => UUIDsEqual(e.ID, entityId)); // global-provider-ok: client-side Angular component, single provider
        this.rows = this.rows.map(r => {
            if (r.rowIndex !== rowIndex)
                return r;
            // Auto-name the source FK column if the user hasn't chosen one — the
            // wizard state service will materialize this as a real UUID column.
            const autoSourceName = !r.ColumnName && entity?.BaseTable
                ? this.defaultFkColumnName(entity.BaseTable)
                : r.ColumnName;
            return {
                ...r,
                ColumnName: autoSourceName,
                ReferencedTable: entity?.BaseTable ?? '',
                ReferencedColumn: DEFAULT_PK_COLUMN,
                selectedEntityId: entityId,
                referencedColumnType: undefined,
            };
        });
        this.emit();
    }
    /** "CustomerOrders" → "CustomerOrderID"; "People" → "PersonID". Best-effort singularizer. */
    defaultFkColumnName(tableName) {
        const base = tableName.endsWith('ies')
            ? tableName.slice(0, -3) + 'y'
            : tableName.endsWith('s') && !tableName.endsWith('ss')
                ? tableName.slice(0, -1)
                : tableName;
        return `${base}ID`;
    }
    /**
     * Handle target-column selection.  Reads the column's SQL type, stores it in row
     * state, then auto-selects the first source column whose (normalised) type matches.
     */
    OnColumnChange(rowIndex, column, entityId) {
        const colInfo = this.ColumnsForEntity(entityId).find(c => c.Name === column);
        const targetType = colInfo?.SqlType;
        const autoSourceColumn = targetType
            ? this.findMatchingSourceColumn(targetType)
            : undefined;
        this.rows = this.rows.map(r => {
            if (r.rowIndex !== rowIndex)
                return r;
            return {
                ...r,
                ReferencedColumn: column,
                referencedColumnType: targetType,
                // Only update source column if a better match was found
                ColumnName: autoSourceColumn ?? r.ColumnName,
            };
        });
        this.emit();
    }
    OnSourceColumnChange(rowIndex, column) {
        this.rows = this.rows.map(r => r.rowIndex === rowIndex ? { ...r, ColumnName: column } : r);
        this.emit();
    }
    OnFkTypeChange(rowIndex, isSoft) {
        this.rows = this.rows.map(r => r.rowIndex === rowIndex ? { ...r, IsSoft: isSoft } : r);
        this.emit();
    }
    // ─── Add / Delete ──────────────────────────────────────────────────────────
    AddRelationship() {
        const schemas = this.AvailableSchemas;
        const defaultSchema = schemas.includes('__mj_UDT') ? '__mj_UDT' : (schemas[0] ?? '');
        // Default the new row's source column to the first Step 2 column
        // that isn't already used by another FK row.  This honours the
        // "give the user a sensible default of any type" intent from
        // f842848683 while avoiding the multi-FK source-column collision
        // bug fixed in 8e52898ec6 — when every existing column is already
        // wired up, we fall through to OnTableChange's auto-naming
        // (mints a unique "<TargetTable>ID" once the user picks a table).
        const usedColumns = new Set(this.rows.map(r => r.ColumnName).filter(Boolean));
        const firstFreeColumn = this.AllColumns.find(c => !usedColumns.has(c.Name))?.Name ?? '';
        this.rows = [
            ...this.rows,
            {
                ColumnName: firstFreeColumn,
                ReferencedSchema: defaultSchema,
                ReferencedTable: '',
                ReferencedColumn: DEFAULT_PK_COLUMN,
                IsSoft: true,
                rowIndex: this.rows.length,
                selectedEntityId: '',
            },
        ];
        this.emit();
    }
    DeleteRow(index) {
        this.rows = this.rows
            .filter(r => r.rowIndex !== index)
            .map((r, i) => ({ ...r, rowIndex: i }));
        this.emit();
    }
    // ─── Restore from InitialForeignKeys (when navigating back) ───────────────
    InitFromForeignKeys(fks) {
        this.rows = fks.map((fk, index) => this.buildRowState(fk, index));
        this.cdr.markForCheck();
    }
    buildRowState(fk, index) {
        const entity = new Metadata().Entities.find(// global-provider-ok: client-side Angular component, single provider
        // global-provider-ok: client-side Angular component, single provider
        e => e.SchemaName === fk.ReferencedSchema && e.BaseTable === fk.ReferencedTable);
        return { ...fk, rowIndex: index, selectedEntityId: entity?.ID ?? '' };
    }
    TrackByIndex(_, row) { return row.rowIndex; }
    // ─── Source-column type matching ───────────────────────────────────────────
    /**
     * Find the first Step 2 source column whose SQL type matches `targetSqlType`.
     * Type comparison is case-insensitive and ignores length/precision qualifiers
     * (e.g. `NVARCHAR(255)` normalises to `NVARCHAR`).
     *
     * Returns `undefined` when no match is found so the caller can decide whether
     * to leave the existing selection untouched.
     */
    findMatchingSourceColumn(targetSqlType) {
        const normalise = (t) => t.toUpperCase().replace(/\s*\(.*\)$/, '').trim();
        const targetNorm = normalise(targetSqlType);
        const match = this.AllColumns.find(c => {
            const colType = c.RawSqlType ?? c.Type ?? '';
            return normalise(colType) === targetNorm;
        });
        return match?.Name;
    }
    // ─── Emit ──────────────────────────────────────────────────────────────────
    emit() {
        const fks = this.rows.map(row => ({
            ColumnName: row.ColumnName,
            ReferencedSchema: row.ReferencedSchema,
            ReferencedTable: row.ReferencedTable,
            ReferencedColumn: row.ReferencedColumn,
            IsSoft: row.IsSoft,
        }));
        this.ForeignKeysChanged.emit(fks);
        this.cdr.markForCheck();
    }
    static ɵfac = function StepRelationshipsComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || StepRelationshipsComponent)(); };
    static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: StepRelationshipsComponent, selectors: [["mj-entity-step-relationships"]], inputs: { InitialForeignKeys: "InitialForeignKeys", AvailableColumns: "AvailableColumns" }, outputs: { ForeignKeysChanged: "ForeignKeysChanged" }, standalone: false, decls: 9, vars: 1, consts: [[1, "step-relationships"], [1, "step-info"], [1, "fa-solid", "fa-circle-info"], [1, "fk-rows"], [1, "add-bar"], ["mjButton", "", "buttonStyle", "secondary", "type", "button", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "fk-row"], [1, "fk-row-header"], [1, "fk-row-label"], ["type", "button", "title", "Remove relationship", 1, "delete-btn", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "fk-row-grid"], [1, "fk-field"], [1, "fk-label"], [1, "mj-input", 3, "change", "value"], ["value", ""], [3, "value"], [1, "mj-input", 3, "change", "value", "disabled"], ["value", "soft"], ["value", "hard"]], template: function StepRelationshipsComponent_Template(rf, ctx) { if (rf & 1) {
            i0.ɵɵelementStart(0, "div", 0)(1, "p", 1);
            i0.ɵɵelement(2, "i", 2);
            i0.ɵɵtext(3, " Optionally define foreign key relationships to other entities. Picking a target table auto-creates the UUID source column for you \u2014 or you can reuse an existing UUID column via the Source Column dropdown. ");
            i0.ɵɵelementEnd();
            i0.ɵɵconditionalCreate(4, StepRelationshipsComponent_Conditional_4_Template, 3, 0, "div", 3);
            i0.ɵɵelementStart(5, "div", 4)(6, "button", 5);
            i0.ɵɵlistener("click", function StepRelationshipsComponent_Template_button_click_6_listener() { return ctx.AddRelationship(); });
            i0.ɵɵelement(7, "i", 6);
            i0.ɵɵtext(8, " Add Relationship ");
            i0.ɵɵelementEnd()()();
        } if (rf & 2) {
            i0.ɵɵadvance(4);
            i0.ɵɵconditional(ctx.rows.length > 0 ? 4 : -1);
        } }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i2.MJButtonDirective], styles: [".step-relationships[_ngcontent-%COMP%] {\n  padding: 16px 24px;\n  display: flex;\n  flex-direction: column;\n  gap: 16px;\n}\n\n\n\n\n.step-info[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: flex-start;\n  gap: 8px;\n  margin: 0;\n  font-size: 0.875rem;\n  color: var(--mj-text-secondary);\n}\n\n.step-info[_ngcontent-%COMP%]   i[_ngcontent-%COMP%] {\n  color: var(--mj-status-info);\n  margin-top: 2px;\n  flex-shrink: 0;\n}\n\n\n\n\n.no-fk-hint[_ngcontent-%COMP%] {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  gap: 10px;\n  padding: 32px;\n  text-align: center;\n  color: var(--mj-text-muted);\n}\n\n.no-fk-hint[_ngcontent-%COMP%]   i[_ngcontent-%COMP%] {\n  font-size: 1.8rem;\n}\n\n.no-fk-hint[_ngcontent-%COMP%]   p[_ngcontent-%COMP%] {\n  margin: 0;\n  font-size: 0.875rem;\n  max-width: 400px;\n}\n\n\n\n\n.fk-rows[_ngcontent-%COMP%] {\n  display: flex;\n  flex-direction: column;\n  gap: 12px;\n}\n\n.fk-row[_ngcontent-%COMP%] {\n  border: 1px solid var(--mj-border-default);\n  border-radius: 8px;\n  background: var(--mj-bg-surface-card);\n  padding: 12px 16px;\n}\n\n\n\n\n.fk-row-header[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  margin-bottom: 12px;\n}\n\n.fk-row-label[_ngcontent-%COMP%] {\n  font-size: 0.8rem;\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.04em;\n  color: var(--mj-text-secondary);\n}\n\n\n\n\n.fk-row-grid[_ngcontent-%COMP%] {\n  display: grid;\n  grid-template-columns: 1fr 1fr 1.5fr 1fr 1.2fr;\n  gap: 12px;\n  align-items: end;\n}\n\n\n\n\n.fk-field[_ngcontent-%COMP%] {\n  display: flex;\n  flex-direction: column;\n  gap: 4px;\n}\n\n.fk-label[_ngcontent-%COMP%] {\n  font-size: 0.75rem;\n  font-weight: 600;\n  color: var(--mj-text-secondary);\n  white-space: nowrap;\n}\n\n.fk-field[_ngcontent-%COMP%]   select[_ngcontent-%COMP%] {\n  width: 100%;\n  font-size: 0.875rem;\n}\n\n\n\n\n.delete-btn[_ngcontent-%COMP%] {\n  background: none;\n  border: none;\n  padding: 5px 7px;\n  cursor: pointer;\n  color: var(--mj-text-muted);\n  border-radius: 4px;\n  transition: color 0.15s, background 0.15s;\n  line-height: 1;\n}\n\n.delete-btn[_ngcontent-%COMP%]:hover {\n  color: var(--mj-status-error-text);\n  background: var(--mj-status-error-bg);\n}\n\n\n\n\n.add-bar[_ngcontent-%COMP%] {\n  padding-top: 4px;\n}\n\n\n\n\n@media (max-width: 640px) {\n  .fk-row-grid[_ngcontent-%COMP%] {\n    grid-template-columns: 1fr 1fr;\n  }\n}"], changeDetection: 0 });
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(StepRelationshipsComponent, [{
        type: Component,
        args: [{ standalone: false, selector: 'mj-entity-step-relationships', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"step-relationships\">\n\n  <p class=\"step-info\">\n    <i class=\"fa-solid fa-circle-info\"></i>\n    Optionally define foreign key relationships to other entities.\n    Picking a target table auto-creates the UUID source column for you \u2014 or you can reuse an existing UUID column via the Source Column dropdown.\n  </p>\n\n  @if (rows.length > 0) {\n    <div class=\"fk-rows\">\n      @for (row of rows; track TrackByIndex($index, row)) {\n        <div class=\"fk-row\">\n\n          <div class=\"fk-row-header\">\n            <span class=\"fk-row-label\">Relationship {{ row.rowIndex + 1 }}</span>\n            <button type=\"button\" class=\"delete-btn\" title=\"Remove relationship\" (click)=\"DeleteRow(row.rowIndex)\">\n              <i class=\"fa-solid fa-trash\"></i>\n            </button>\n          </div>\n\n          <div class=\"fk-row-grid\">\n\n            <!-- Source Column \u2014 any Step 2 column, not just UUID -->\n            <div class=\"fk-field\">\n              <label class=\"fk-label\">Source Column</label>\n              <select class=\"mj-input\"\n                      [value]=\"row.ColumnName\"\n                      (change)=\"OnSourceColumnChange(row.rowIndex, $any($event.target).value)\">\n                <option value=\"\">\u2014 auto-create {{ row.ColumnName || '\u2014' }} \u2014</option>\n                @for (col of AllColumns; track col.Name) {\n                  <option [value]=\"col.Name\">{{ col.Name }}</option>\n                }\n              </select>\n            </div>\n\n            <!-- Target Schema -->\n            <div class=\"fk-field\">\n              <label class=\"fk-label\">Target Schema</label>\n              <select class=\"mj-input\"\n                      [value]=\"row.ReferencedSchema\"\n                      (change)=\"OnSchemaChange(row.rowIndex, $any($event.target).value)\">\n                <option value=\"\">\u2014 select schema \u2014</option>\n                @for (schema of AvailableSchemas; track schema) {\n                  <option [value]=\"schema\">{{ schema }}</option>\n                }\n              </select>\n            </div>\n\n            <!-- Target Table -->\n            <div class=\"fk-field\">\n              <label class=\"fk-label\">Target Table</label>\n              <select class=\"mj-input\"\n                      [value]=\"row.selectedEntityId\"\n                      [disabled]=\"!row.ReferencedSchema\"\n                      (change)=\"OnTableChange(row.rowIndex, $any($event.target).value)\">\n                <option value=\"\">{{ TablePlaceholder(row) }}</option>\n                @for (entity of EntitiesForSchema(row.ReferencedSchema); track entity.ID) {\n                  <option [value]=\"entity.ID\">{{ entity.BaseTable }}</option>\n                }\n              </select>\n            </div>\n\n            <!-- Target Column \u2014 shows SQL type to help user match source column type -->\n            <div class=\"fk-field\">\n              <label class=\"fk-label\">Target Column</label>\n              <select class=\"mj-input\"\n                      [value]=\"row.ReferencedColumn\"\n                      [disabled]=\"!row.selectedEntityId\"\n                      (change)=\"OnColumnChange(row.rowIndex, $any($event.target).value, row.selectedEntityId)\">\n                <option value=\"\">{{ ColumnPlaceholder(row) }}</option>\n                @for (col of ColumnsForEntity(row.selectedEntityId); track col.Name) {\n                  <option [value]=\"col.Name\">{{ col.Name }} ({{ col.SqlType }})</option>\n                }\n              </select>\n            </div>\n\n            <!-- FK Type -->\n            <div class=\"fk-field\">\n              <label class=\"fk-label\">FK Type</label>\n              <select class=\"mj-input\"\n                      [value]=\"row.IsSoft ? 'soft' : 'hard'\"\n                      (change)=\"OnFkTypeChange(row.rowIndex, $any($event.target).value === 'soft')\">\n                <option value=\"soft\">Soft (metadata only)</option>\n                <option value=\"hard\">Hard (DB constraint)</option>\n              </select>\n            </div>\n\n          </div>\n        </div>\n      }\n    </div>\n  }\n\n  <div class=\"add-bar\">\n    <button mjButton buttonStyle=\"secondary\" type=\"button\"\n            (click)=\"AddRelationship()\">\n      <i class=\"fa-solid fa-plus\"></i>\n      Add Relationship\n    </button>\n  </div>\n\n</div>\n", styles: [".step-relationships {\n  padding: 16px 24px;\n  display: flex;\n  flex-direction: column;\n  gap: 16px;\n}\n\n/* \u2500\u2500 Info banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.step-info {\n  display: flex;\n  align-items: flex-start;\n  gap: 8px;\n  margin: 0;\n  font-size: 0.875rem;\n  color: var(--mj-text-secondary);\n}\n\n.step-info i {\n  color: var(--mj-status-info);\n  margin-top: 2px;\n  flex-shrink: 0;\n}\n\n/* \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.no-fk-hint {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  gap: 10px;\n  padding: 32px;\n  text-align: center;\n  color: var(--mj-text-muted);\n}\n\n.no-fk-hint i {\n  font-size: 1.8rem;\n}\n\n.no-fk-hint p {\n  margin: 0;\n  font-size: 0.875rem;\n  max-width: 400px;\n}\n\n/* \u2500\u2500 FK card list \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.fk-rows {\n  display: flex;\n  flex-direction: column;\n  gap: 12px;\n}\n\n.fk-row {\n  border: 1px solid var(--mj-border-default);\n  border-radius: 8px;\n  background: var(--mj-bg-surface-card);\n  padding: 12px 16px;\n}\n\n/* \u2500\u2500 Card header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.fk-row-header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  margin-bottom: 12px;\n}\n\n.fk-row-label {\n  font-size: 0.8rem;\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.04em;\n  color: var(--mj-text-secondary);\n}\n\n/* \u2500\u2500 5-column grid \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.fk-row-grid {\n  display: grid;\n  grid-template-columns: 1fr 1fr 1.5fr 1fr 1.2fr;\n  gap: 12px;\n  align-items: end;\n}\n\n/* \u2500\u2500 Field (label + select) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.fk-field {\n  display: flex;\n  flex-direction: column;\n  gap: 4px;\n}\n\n.fk-label {\n  font-size: 0.75rem;\n  font-weight: 600;\n  color: var(--mj-text-secondary);\n  white-space: nowrap;\n}\n\n.fk-field select {\n  width: 100%;\n  font-size: 0.875rem;\n}\n\n/* \u2500\u2500 Delete button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.delete-btn {\n  background: none;\n  border: none;\n  padding: 5px 7px;\n  cursor: pointer;\n  color: var(--mj-text-muted);\n  border-radius: 4px;\n  transition: color 0.15s, background 0.15s;\n  line-height: 1;\n}\n\n.delete-btn:hover {\n  color: var(--mj-status-error-text);\n  background: var(--mj-status-error-bg);\n}\n\n/* \u2500\u2500 Add bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.add-bar {\n  padding-top: 4px;\n}\n\n/* \u2500\u2500 Responsive: stack to 2-col on narrow panels \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n@media (max-width: 640px) {\n  .fk-row-grid {\n    grid-template-columns: 1fr 1fr;\n  }\n}\n"] }]
    }], null, { InitialForeignKeys: [{
            type: Input
        }], AvailableColumns: [{
            type: Input
        }], ForeignKeysChanged: [{
            type: Output
        }] }); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(StepRelationshipsComponent, { className: "StepRelationshipsComponent", filePath: "src/DatabaseDesigner/components/create-wizard/steps/step-relationships.component.ts", lineNumber: 55 }); })();
//# sourceMappingURL=step-relationships.component.js.map