/**
 * @fileoverview Classify · Tag Library tab.
 *
 * Self-contained sub-page: owns its header-interior (with the tag search box),
 * the tag rows table, the word cloud, the tags-by-source breakdown, and the
 * per-tag drill-down. Receives the shared raw tag + item rows from the host
 * orchestrator via `[ContentTags]`/`[ContentItems]` and rebuilds its view
 * models from them. Opening a content item from the drill-down is a cross-tab
 * concern owned by the host's slide-in, so it bubbles up via @Output.
 */
import { Component, ChangeDetectorRef, EventEmitter, Input, Output, inject } from '@angular/core';
import { NormalizeUUID } from '@memberjunction/global';
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
import { formatWeight, tagFontSize, formatShortDate, deriveDisplayName } from '../shared/classify.format';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@memberjunction/ng-shared-generic";
import * as i3 from "@memberjunction/ng-ui-components";
import * as i4 from "@memberjunction/ng-word-cloud";
const _forTrack0 = ($index, $item) => $item.Tag;
const _forTrack1 = ($index, $item) => $item.SourceName;
const _forTrack2 = ($index, $item) => $item.ID;
function ClassifyTagsTabComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "i", 27);
    i0.ɵɵelementStart(1, "span", 28);
    i0.ɵɵtext(2, "Refreshing\u2026");
    i0.ɵɵelementEnd();
} }
function ClassifyTagsTabComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "i", 29);
    i0.ɵɵelementStart(1, "span", 28);
    i0.ɵɵtext(2, "Refresh");
    i0.ɵɵelementEnd();
} }
function ClassifyTagsTabComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 7);
    i0.ɵɵelement(1, "mj-loading", 30);
    i0.ɵɵelementEnd();
} }
function ClassifyTagsTabComponent_For_32_Template(rf, ctx) { if (rf & 1) {
    const _r1 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "tr", 31);
    i0.ɵɵlistener("click", function ClassifyTagsTabComponent_For_32_Template_tr_click_0_listener() { const row_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.DrillDownTag(row_r2.Tag)); });
    i0.ɵɵelementStart(1, "td", 32);
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "td");
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "td")(6, "div", 33)(7, "div", 34);
    i0.ɵɵelement(8, "div", 35);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(9, "span", 36);
    i0.ɵɵtext(10);
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(11, "td")(12, "div", 37);
    i0.ɵɵelement(13, "div", 38);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(14, "td");
    i0.ɵɵtext(15);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(16, "td");
    i0.ɵɵtext(17);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const row_r2 = ctx.$implicit;
    const ctx_r2 = i0.ɵɵnextContext();
    i0.ɵɵclassProp("at-tag-row-selected", ctx_r2.SelectedDrillDownTag === row_r2.Tag);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(row_r2.Tag);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(row_r2.UsageCount);
    i0.ɵɵadvance(4);
    i0.ɵɵstyleProp("width", row_r2.AvgWeight * 100, "%");
    i0.ɵɵclassProp("at-weight-high", row_r2.AvgWeight >= 0.7)("at-weight-medium", row_r2.AvgWeight >= 0.4 && row_r2.AvgWeight < 0.7)("at-weight-low", row_r2.AvgWeight < 0.4);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(row_r2.AvgWeight.toFixed(2));
    i0.ɵɵadvance(3);
    i0.ɵɵstyleProp("width", row_r2.BarWidthPct, "%");
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(row_r2.TopSource);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(row_r2.FirstSeen);
} }
function ClassifyTagsTabComponent_Conditional_33_Conditional_8_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 45)(1, "p");
    i0.ɵɵtext(2, "No content items found for this tag.");
    i0.ɵɵelementEnd()();
} }
function ClassifyTagsTabComponent_Conditional_33_Conditional_9_For_13_Template(rf, ctx) { if (rf & 1) {
    const _r5 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "tr", 31);
    i0.ɵɵlistener("click", function ClassifyTagsTabComponent_Conditional_33_Conditional_9_For_13_Template_tr_click_0_listener() { const di_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onOpenItemDetail(di_r6.ID)); });
    i0.ɵɵelementStart(1, "td");
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "td");
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "td");
    i0.ɵɵtext(6);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(7, "td");
    i0.ɵɵtext(8);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const di_r6 = ctx.$implicit;
    const ctx_r2 = i0.ɵɵnextContext(3);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(di_r6.Name);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(di_r6.SourceName);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ctx_r2.FormatWeight(di_r6.Weight));
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(di_r6.UpdatedAt);
} }
function ClassifyTagsTabComponent_Conditional_33_Conditional_9_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "table", 13)(1, "thead")(2, "tr")(3, "th");
    i0.ɵɵtext(4, "Name");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "th");
    i0.ɵɵtext(6, "Source");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(7, "th");
    i0.ɵɵtext(8, "Weight");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(9, "th");
    i0.ɵɵtext(10, "Updated");
    i0.ɵɵelementEnd()()();
    i0.ɵɵelementStart(11, "tbody");
    i0.ɵɵrepeaterCreate(12, ClassifyTagsTabComponent_Conditional_33_Conditional_9_For_13_Template, 9, 4, "tr", 46, _forTrack2);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r2 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance(12);
    i0.ɵɵrepeater(ctx_r2.TagDrillDownItems);
} }
function ClassifyTagsTabComponent_Conditional_33_Template(rf, ctx) { if (rf & 1) {
    const _r4 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 15)(1, "div", 39)(2, "span", 40);
    i0.ɵɵelement(3, "i", 41);
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(5, "button", 42);
    i0.ɵɵlistener("click", function ClassifyTagsTabComponent_Conditional_33_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.CloseDrillDownTag()); });
    i0.ɵɵelement(6, "i", 43);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(7, "div", 44);
    i0.ɵɵconditionalCreate(8, ClassifyTagsTabComponent_Conditional_33_Conditional_8_Template, 3, 0, "div", 45)(9, ClassifyTagsTabComponent_Conditional_33_Conditional_9_Template, 14, 0, "table", 13);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r2 = i0.ɵɵnextContext();
    i0.ɵɵadvance(4);
    i0.ɵɵtextInterpolate2(" Content items tagged \"", ctx_r2.SelectedDrillDownTag, "\" (", ctx_r2.TagDrillDownItems.length, ") ");
    i0.ɵɵadvance(4);
    i0.ɵɵconditional(ctx_r2.TagDrillDownItems.length === 0 ? 8 : 9);
} }
function ClassifyTagsTabComponent_Conditional_39_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "mj-word-cloud", 20);
} if (rf & 2) {
    const ctx_r2 = i0.ɵɵnextContext();
    i0.ɵɵproperty("Items", ctx_r2.TagCloudWordItems)("MaxFontSize", 40)("MinFontSize", 12)("MaxItems", 20)("Interactive", true)("Animate", true);
} }
function ClassifyTagsTabComponent_Conditional_40_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 21);
    i0.ɵɵtext(1, "No tags yet");
    i0.ɵɵelementEnd();
} }
function ClassifyTagsTabComponent_For_47_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 26)(1, "span");
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "strong");
    i0.ɵɵtext(4);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const s_r7 = ctx.$implicit;
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(s_r7.SourceName);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(s_r7.Count);
} }
export class ClassifyTagsTabComponent extends BaseAngularComponent {
    cdr = inject(ChangeDetectorRef);
    /** Shared raw `MJ: Content Item Tags` rows, supplied by the host orchestrator. */
    _contentTags = [];
    set ContentTags(value) {
        this._contentTags = value ?? [];
        this.rebuild();
    }
    get ContentTags() {
        return this._contentTags;
    }
    /** Shared raw `MJ: Content Items` rows — used for source mapping and drill-down. */
    _contentItems = [];
    set ContentItems(value) {
        this._contentItems = value ?? [];
        this.rebuild();
    }
    get ContentItems() {
        return this._contentItems;
    }
    /** Shown while a manual Refresh() rebuilds the tag view models. */
    IsLoading = false;
    TagRows = [];
    FilteredTagRows = [];
    TagCloudWordItems = [];
    TagsBySource = [];
    TagSearchQuery = '';
    SelectedDrillDownTag = null;
    TagDrillDownItems = [];
    /** Subtitle reflects the live tag count, mirroring the former host subtitle. */
    get Subtitle() {
        return `${this.TagRows.length} unique tags across all content sources`;
    }
    // Template-facing formatters (shared pure helpers exposed for the view).
    TagFontSize = tagFontSize;
    FormatWeight = formatWeight;
    /** Bubble a request to open a content item's detail slide-in (host-owned). */
    OpenItemDetailRequested = new EventEmitter();
    onOpenItemDetail(contentItemID) {
        this.OpenItemDetailRequested.emit(contentItemID);
    }
    /** Rebuild all tag-tab view models from the current inputs. */
    rebuild() {
        this.buildTagRows();
        this.buildTagCloud();
        this.buildTagsBySource();
        this.FilterTags();
    }
    /**
     * Rebuild the tag view models from the current host-supplied inputs. The tag
     * data is host-owned (flows in via [ContentTags]/[ContentItems]); Refresh
     * recomputes the rows/cloud/breakdown and surfaces a brief loading state.
     */
    async Refresh() {
        this.IsLoading = true;
        this.cdr.detectChanges();
        this.rebuild();
        this.IsLoading = false;
        this.cdr.detectChanges();
    }
    // ── External control surface (host deep-link + agent tool) ──
    /** Apply a search query programmatically (used by the agent tool + deep link). Returns the match count. */
    ApplySearch(query) {
        this.TagSearchQuery = query;
        this.FilterTags();
        return this.FilteredTagRows.length;
    }
    // ── View-model building ──
    buildTagRows() {
        const tagCounts = this.countAllTags();
        const avgWeights = this.computeAvgWeights();
        const tagSourceMap = this.getTopSourcePerTag();
        const tagFirstSeen = this.getFirstSeenPerTag();
        const sorted = Array.from(tagCounts.entries()).sort((a, b) => b[1] - a[1]);
        const maxCount = sorted.length > 0 ? sorted[0][1] : 1;
        this.TagRows = sorted.map(([tag, count]) => ({
            Tag: tag,
            UsageCount: count,
            AvgWeight: avgWeights.get(tag) ?? 1.0,
            BarWidthPct: Math.round((count / maxCount) * 100),
            TopSource: tagSourceMap.get(tag) ?? 'Unknown',
            FirstSeen: tagFirstSeen.get(tag) ?? ''
        }));
    }
    buildTagCloud() {
        const tagCounts = this.countAllTags();
        const avgWeights = this.computeAvgWeights();
        // Sort by a combined score: usage count * avg weight (so high-weight, high-count tags bubble up)
        const scored = Array.from(tagCounts.entries()).map(([tag, count]) => {
            const weight = avgWeights.get(tag) ?? 1.0;
            return { tag, count, weight, score: count * weight };
        }).sort((a, b) => b.score - a.score).slice(0, 20);
        const maxScore = scored.length > 0 ? scored[0].score : 1;
        // Build WordCloudItem[] for the mj-word-cloud component
        this.TagCloudWordItems = scored.map(s => ({
            Text: s.tag,
            Weight: maxScore > 0 ? s.score / maxScore : 0,
            Metadata: { Count: s.count, AvgWeight: s.weight }
        }));
    }
    buildTagsBySource() {
        const sourceTagCounts = new Map();
        const itemSourceMap = new Map();
        for (const item of this._contentItems) {
            itemSourceMap.set(item['ID'], item['ContentSource'] ?? 'Unknown');
        }
        for (const tag of this._contentTags) {
            const source = itemSourceMap.get(tag['ItemID']) ?? 'Unknown';
            sourceTagCounts.set(source, (sourceTagCounts.get(source) ?? 0) + 1);
        }
        this.TagsBySource = Array.from(sourceTagCounts.entries())
            .sort((a, b) => b[1] - a[1])
            .map(([name, count]) => ({ SourceName: name, Count: count }));
    }
    FilterTags() {
        const q = this.TagSearchQuery.toLowerCase().trim();
        this.FilteredTagRows = q
            ? this.TagRows.filter(r => r.Tag.toLowerCase().includes(q))
            : this.TagRows;
        this.cdr.detectChanges();
    }
    /** Drill down into content items matching a specific tag. */
    DrillDownTag(tagName) {
        if (this.SelectedDrillDownTag === tagName) {
            this.CloseDrillDownTag();
            return;
        }
        this.SelectedDrillDownTag = tagName;
        // Find all content items that have this tag
        const matchingItemIDs = new Map(); // itemID → weight
        for (const tag of this._contentTags) {
            if (tag['Tag'] === tagName) {
                matchingItemIDs.set(NormalizeUUID(tag['ItemID']), Number(tag['Weight'] ?? 1));
            }
        }
        this.TagDrillDownItems = [];
        for (let i = 0; i < this._contentItems.length; i++) {
            const item = this._contentItems[i];
            const normalizedID = NormalizeUUID(item['ID']);
            const weight = matchingItemIDs.get(normalizedID);
            if (weight !== undefined) {
                this.TagDrillDownItems.push({
                    ID: item['ID'],
                    Name: deriveDisplayName({ Name: item['Name'], Description: item['Description'] }),
                    SourceName: item['ContentSource'] ?? 'Unknown',
                    Weight: weight,
                    UpdatedAt: formatShortDate(item['__mj_UpdatedAt'] ?? ''),
                    FeedIndex: i,
                });
            }
        }
        // Sort by weight descending
        this.TagDrillDownItems.sort((a, b) => b.Weight - a.Weight);
        this.cdr.detectChanges();
    }
    CloseDrillDownTag() {
        this.SelectedDrillDownTag = null;
        this.TagDrillDownItems = [];
        this.cdr.detectChanges();
    }
    // ── Aggregation utilities (read only the tag + item inputs) ──
    countAllTags() {
        const counts = new Map();
        for (const tag of this._contentTags) {
            const t = tag['Tag'];
            if (t)
                counts.set(t, (counts.get(t) ?? 0) + 1);
        }
        return counts;
    }
    /** Compute average weight per tag across all occurrences. */
    computeAvgWeights() {
        const sums = new Map();
        const counts = new Map();
        for (const tag of this._contentTags) {
            const t = tag['Tag'];
            const w = Number(tag['Weight'] ?? 0.5);
            if (t) {
                sums.set(t, (sums.get(t) ?? 0) + w);
                counts.set(t, (counts.get(t) ?? 0) + 1);
            }
        }
        const avgs = new Map();
        for (const [t, sum] of sums) {
            avgs.set(t, Math.round((sum / (counts.get(t) ?? 1)) * 100) / 100);
        }
        return avgs;
    }
    getTopSourcePerTag() {
        const tagSourceCounts = new Map();
        const itemSourceMap = new Map();
        for (const item of this._contentItems) {
            itemSourceMap.set(item['ID'], item['ContentSource'] ?? 'Unknown');
        }
        for (const tag of this._contentTags) {
            const t = tag['Tag'];
            const source = itemSourceMap.get(tag['ItemID']) ?? 'Unknown';
            if (!tagSourceCounts.has(t))
                tagSourceCounts.set(t, new Map());
            const inner = tagSourceCounts.get(t);
            inner.set(source, (inner.get(source) ?? 0) + 1);
        }
        const result = new Map();
        for (const [tag, sourceCounts] of tagSourceCounts) {
            let maxSource = 'Unknown';
            let maxCount = 0;
            for (const [source, count] of sourceCounts) {
                if (count > maxCount) {
                    maxSource = source;
                    maxCount = count;
                }
            }
            result.set(tag, maxSource);
        }
        return result;
    }
    getFirstSeenPerTag() {
        const result = new Map();
        for (const tag of this._contentTags) {
            const t = tag['Tag'];
            if (t && !result.has(t)) {
                const date = tag['__mj_CreatedAt'];
                result.set(t, date ? formatShortDate(date) : '');
            }
        }
        return result;
    }
    static ɵfac = /*@__PURE__*/ (() => { let ɵClassifyTagsTabComponent_BaseFactory; return function ClassifyTagsTabComponent_Factory(__ngFactoryType__) { return (ɵClassifyTagsTabComponent_BaseFactory || (ɵClassifyTagsTabComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ClassifyTagsTabComponent)))(__ngFactoryType__ || ClassifyTagsTabComponent); }; })();
    static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ClassifyTagsTabComponent, selectors: [["classify-tags-tab"]], inputs: { ContentTags: "ContentTags", ContentItems: "ContentItems" }, outputs: { OpenItemDetailRequested: "OpenItemDetailRequested" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 48, vars: 9, consts: [["Title", "Tag Library", 3, "Subtitle"], ["actions", ""], ["mjButton", "", "variant", "secondary", "size", "sm", 3, "click", "disabled"], ["toolbar", ""], ["type", "text", "placeholder", "Search tags...", 1, "at-search-input", 3, "ngModelChange", "input", "ngModel"], [3, "Padding", "Flex"], [1, "at-main-area"], [1, "at-loading-overlay"], [1, "at-page-body"], [1, "at-tag-lib-layout"], [1, "at-tag-lib-main"], [1, "at-card"], [1, "at-card-body", 2, "max-height", "500px", "overflow-y", "auto"], [1, "at-tag-table"], [1, "at-tag-row-clickable", 3, "at-tag-row-selected"], [1, "at-card", 2, "margin-top", "12px"], [1, "at-tag-lib-sidebar"], [1, "at-card", "at-tag-cloud-card"], [1, "at-card-title", 2, "margin-bottom", "12px"], [1, "fa-solid", "fa-cloud"], ["Layout", "spiral", "ColorMode", "weight-gradient", 3, "Items", "MaxFontSize", "MinFontSize", "MaxItems", "Interactive", "Animate"], [1, "at-tag-cloud-empty"], [1, "at-card", 2, "padding", "16px", "margin-top", "12px"], [1, "at-card-title", 2, "margin-bottom", "10px"], [1, "fa-solid", "fa-chart-pie"], [1, "at-tags-by-source"], [1, "at-tag-source-row"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "mj-action-label"], [1, "fa-solid", "fa-arrows-rotate"], ["text", "Refreshing tags\u2026"], [1, "at-tag-row-clickable", 3, "click"], [1, "at-tag-name-cell"], [1, "at-weight-indicator"], [1, "at-weight-bar"], [1, "at-weight-bar-fill"], [1, "at-weight-value"], [1, "at-tag-bar"], [1, "at-tag-bar-fill"], [1, "at-card-header"], [1, "at-card-title"], [1, "fa-solid", "fa-tag"], ["aria-label", "Close", 1, "at-slide-close", 2, "background", "none", "border", "none", "cursor", "pointer", "color", "var(--mj-text-muted)", 3, "click"], [1, "fa-solid", "fa-times"], [1, "at-card-body", 2, "max-height", "300px", "overflow-y", "auto"], [1, "at-empty-state"], [1, "at-tag-row-clickable"]], template: function ClassifyTagsTabComponent_Template(rf, ctx) { if (rf & 1) {
            i0.ɵɵelementStart(0, "mj-page-header-interior", 0)(1, "div", 1)(2, "button", 2);
            i0.ɵɵlistener("click", function ClassifyTagsTabComponent_Template_button_click_2_listener() { return ctx.Refresh(); });
            i0.ɵɵconditionalCreate(3, ClassifyTagsTabComponent_Conditional_3_Template, 3, 0)(4, ClassifyTagsTabComponent_Conditional_4_Template, 3, 0);
            i0.ɵɵelementEnd()();
            i0.ɵɵelementStart(5, "div", 3)(6, "input", 4);
            i0.ɵɵtwoWayListener("ngModelChange", function ClassifyTagsTabComponent_Template_input_ngModelChange_6_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.TagSearchQuery, $event) || (ctx.TagSearchQuery = $event); return $event; });
            i0.ɵɵlistener("input", function ClassifyTagsTabComponent_Template_input_input_6_listener() { return ctx.FilterTags(); });
            i0.ɵɵelementEnd()()();
            i0.ɵɵelementStart(7, "mj-page-body-interior", 5)(8, "div", 6);
            i0.ɵɵconditionalCreate(9, ClassifyTagsTabComponent_Conditional_9_Template, 2, 0, "div", 7);
            i0.ɵɵelementStart(10, "div", 8)(11, "div", 9)(12, "div", 10)(13, "div", 11)(14, "div", 12)(15, "table", 13)(16, "thead")(17, "tr")(18, "th");
            i0.ɵɵtext(19, "Tag");
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(20, "th");
            i0.ɵɵtext(21, "Count");
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(22, "th");
            i0.ɵɵtext(23, "Avg Weight");
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(24, "th");
            i0.ɵɵtext(25, "Distribution");
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(26, "th");
            i0.ɵɵtext(27, "Top Source");
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(28, "th");
            i0.ɵɵtext(29, "First Seen");
            i0.ɵɵelementEnd()()();
            i0.ɵɵelementStart(30, "tbody");
            i0.ɵɵrepeaterCreate(31, ClassifyTagsTabComponent_For_32_Template, 18, 17, "tr", 14, _forTrack0);
            i0.ɵɵelementEnd()()()();
            i0.ɵɵconditionalCreate(33, ClassifyTagsTabComponent_Conditional_33_Template, 10, 3, "div", 15);
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(34, "div", 16)(35, "div", 17)(36, "div", 18);
            i0.ɵɵelement(37, "i", 19);
            i0.ɵɵtext(38, " Tag Cloud");
            i0.ɵɵelementEnd();
            i0.ɵɵconditionalCreate(39, ClassifyTagsTabComponent_Conditional_39_Template, 1, 6, "mj-word-cloud", 20)(40, ClassifyTagsTabComponent_Conditional_40_Template, 2, 0, "div", 21);
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(41, "div", 22)(42, "div", 23);
            i0.ɵɵelement(43, "i", 24);
            i0.ɵɵtext(44, " By Source");
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(45, "div", 25);
            i0.ɵɵrepeaterCreate(46, ClassifyTagsTabComponent_For_47_Template, 5, 2, "div", 26, _forTrack1);
            i0.ɵɵelementEnd()()()()()()();
        } if (rf & 2) {
            i0.ɵɵproperty("Subtitle", ctx.Subtitle);
            i0.ɵɵadvance(2);
            i0.ɵɵproperty("disabled", ctx.IsLoading);
            i0.ɵɵadvance();
            i0.ɵɵconditional(ctx.IsLoading ? 3 : 4);
            i0.ɵɵadvance(3);
            i0.ɵɵtwoWayProperty("ngModel", ctx.TagSearchQuery);
            i0.ɵɵadvance();
            i0.ɵɵproperty("Padding", false)("Flex", true);
            i0.ɵɵadvance(2);
            i0.ɵɵconditional(ctx.IsLoading ? 9 : -1);
            i0.ɵɵadvance(22);
            i0.ɵɵrepeater(ctx.FilteredTagRows);
            i0.ɵɵadvance(2);
            i0.ɵɵconditional(ctx.SelectedDrillDownTag ? 33 : -1);
            i0.ɵɵadvance(6);
            i0.ɵɵconditional(ctx.TagCloudWordItems.length > 0 ? 39 : 40);
            i0.ɵɵadvance(7);
            i0.ɵɵrepeater(ctx.TagsBySource);
        } }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel, i2.LoadingComponent, i3.MJButtonDirective, i3.MJPageHeaderInteriorComponent, i3.MJPageBodyInteriorComponent, i4.MJWordCloudComponent], encapsulation: 2 });
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ClassifyTagsTabComponent, [{
        type: Component,
        args: [{ standalone: false, selector: 'classify-tags-tab', template: "<mj-page-header-interior\n    Title=\"Tag Library\"\n    [Subtitle]=\"Subtitle\">\n  <div actions>\n    <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"Refresh()\" [disabled]=\"IsLoading\">\n      @if (IsLoading) {\n        <i class=\"fa-solid fa-spinner fa-spin\"></i> <span class=\"mj-action-label\">Refreshing\u2026</span>\n      } @else {\n        <i class=\"fa-solid fa-arrows-rotate\"></i> <span class=\"mj-action-label\">Refresh</span>\n      }\n    </button>\n  </div>\n  <div toolbar>\n    <input type=\"text\" class=\"at-search-input\" placeholder=\"Search tags...\"\n           [(ngModel)]=\"TagSearchQuery\" (input)=\"FilterTags()\">\n  </div>\n</mj-page-header-interior>\n\n<mj-page-body-interior [Padding]=\"false\" [Flex]=\"true\">\n  <div class=\"at-main-area\">\n    @if (IsLoading) {\n      <div class=\"at-loading-overlay\">\n        <mj-loading text=\"Refreshing tags\u2026\"></mj-loading>\n      </div>\n    }\n    <div class=\"at-page-body\">\n        <div class=\"at-tag-lib-layout\">\n            <div class=\"at-tag-lib-main\">\n                <div class=\"at-card\">\n                    <div class=\"at-card-body\" style=\"max-height: 500px; overflow-y: auto;\">\n                        <table class=\"at-tag-table\">\n                            <thead>\n                                <tr>\n                                    <th>Tag</th>\n                                    <th>Count</th>\n                                    <th>Avg Weight</th>\n                                    <th>Distribution</th>\n                                    <th>Top Source</th>\n                                    <th>First Seen</th>\n                                </tr>\n                            </thead>\n                            <tbody>\n                                @for (row of FilteredTagRows; track row.Tag) {\n                                    <tr class=\"at-tag-row-clickable\" (click)=\"DrillDownTag(row.Tag)\"\n                                        [class.at-tag-row-selected]=\"SelectedDrillDownTag === row.Tag\">\n                                        <td class=\"at-tag-name-cell\">{{ row.Tag }}</td>\n                                        <td>{{ row.UsageCount }}</td>\n                                        <td>\n                                            <div class=\"at-weight-indicator\">\n                                                <div class=\"at-weight-bar\">\n                                                    <div class=\"at-weight-bar-fill\" [style.width.%]=\"row.AvgWeight * 100\"\n                                                         [class.at-weight-high]=\"row.AvgWeight >= 0.7\"\n                                                         [class.at-weight-medium]=\"row.AvgWeight >= 0.4 && row.AvgWeight < 0.7\"\n                                                         [class.at-weight-low]=\"row.AvgWeight < 0.4\"></div>\n                                                </div>\n                                                <span class=\"at-weight-value\">{{ row.AvgWeight.toFixed(2) }}</span>\n                                            </div>\n                                        </td>\n                                        <td>\n                                            <div class=\"at-tag-bar\">\n                                                <div class=\"at-tag-bar-fill\" [style.width.%]=\"row.BarWidthPct\"></div>\n                                            </div>\n                                        </td>\n                                        <td>{{ row.TopSource }}</td>\n                                        <td>{{ row.FirstSeen }}</td>\n                                    </tr>\n                                }\n                            </tbody>\n                        </table>\n                    </div>\n                </div>\n\n                <!-- Tag drill-down: content items matching selected tag -->\n                @if (SelectedDrillDownTag) {\n                    <div class=\"at-card\" style=\"margin-top: 12px;\">\n                        <div class=\"at-card-header\">\n                            <span class=\"at-card-title\">\n                                <i class=\"fa-solid fa-tag\"></i>\n                                Content items tagged \"{{ SelectedDrillDownTag }}\"\n                                ({{ TagDrillDownItems.length }})\n                            </span>\n                            <button class=\"at-slide-close\" (click)=\"CloseDrillDownTag()\" style=\"background:none;border:none;cursor:pointer;color:var(--mj-text-muted)\" aria-label=\"Close\">\n                                <i class=\"fa-solid fa-times\"></i>\n                            </button>\n                        </div>\n                        <div class=\"at-card-body\" style=\"max-height: 300px; overflow-y: auto;\">\n                            @if (TagDrillDownItems.length === 0) {\n                                <div class=\"at-empty-state\"><p>No content items found for this tag.</p></div>\n                            } @else {\n                                <table class=\"at-tag-table\">\n                                    <thead>\n                                        <tr>\n                                            <th>Name</th>\n                                            <th>Source</th>\n                                            <th>Weight</th>\n                                            <th>Updated</th>\n                                        </tr>\n                                    </thead>\n                                    <tbody>\n                                        @for (di of TagDrillDownItems; track di.ID) {\n                                            <tr class=\"at-tag-row-clickable\" (click)=\"onOpenItemDetail(di.ID)\">\n                                                <td>{{ di.Name }}</td>\n                                                <td>{{ di.SourceName }}</td>\n                                                <td>{{ FormatWeight(di.Weight) }}</td>\n                                                <td>{{ di.UpdatedAt }}</td>\n                                            </tr>\n                                        }\n                                    </tbody>\n                                </table>\n                            }\n                        </div>\n                    </div>\n                }\n            </div>\n            <div class=\"at-tag-lib-sidebar\">\n                <div class=\"at-card at-tag-cloud-card\">\n                    <div class=\"at-card-title\" style=\"margin-bottom: 12px;\"><i class=\"fa-solid fa-cloud\"></i> Tag Cloud</div>\n                    @if (TagCloudWordItems.length > 0) {\n                        <mj-word-cloud\n                            [Items]=\"TagCloudWordItems\"\n                            [MaxFontSize]=\"40\"\n                            [MinFontSize]=\"12\"\n                            [MaxItems]=\"20\"\n                            Layout=\"spiral\"\n                            ColorMode=\"weight-gradient\"\n                            [Interactive]=\"true\"\n                            [Animate]=\"true\">\n                        </mj-word-cloud>\n                    } @else {\n                        <div class=\"at-tag-cloud-empty\">No tags yet</div>\n                    }\n                </div>\n                <div class=\"at-card\" style=\"padding: 16px; margin-top: 12px;\">\n                    <div class=\"at-card-title\" style=\"margin-bottom: 10px;\"><i class=\"fa-solid fa-chart-pie\"></i> By Source</div>\n                    <div class=\"at-tags-by-source\">\n                        @for (s of TagsBySource; track s.SourceName) {\n                            <div class=\"at-tag-source-row\">\n                                <span>{{ s.SourceName }}</span>\n                                <strong>{{ s.Count }}</strong>\n                            </div>\n                        }\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n  </div>\n</mj-page-body-interior>\n", styles: ["/*\n * Tag Library tab styles.\n *\n * The host (AutotaggingPipelineResourceComponent) uses ViewEncapsulation.None,\n * so its `.at-*` rules are global and already style this tab's markup while it\n * renders inside the host shell. Tab-specific rules live here as the shared CSS\n * is partitioned during the host-slim step.\n */\n"] }]
    }], null, { ContentTags: [{
            type: Input
        }], ContentItems: [{
            type: Input
        }], OpenItemDetailRequested: [{
            type: Output
        }] }); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ClassifyTagsTabComponent, { className: "ClassifyTagsTabComponent", filePath: "src/AI/components/autotagging/tabs/tags-tab.component.ts", lineNumber: 34 }); })();
//# sourceMappingURL=tags-tab.component.js.map