<svelte:options customElement={{ props: {} }} />

<script lang="ts">
  import {FloatingTrigger} from './index';
  import type {SelectItem} from '#types';
  import {nodeIcons} from '../../consts';

  let {
        items,
        onSelect,
        value = [],
        defaultValue = [],
        multiple = false,
        placeholder,
        variant = 'default',
        showSelectedType = true,
        ...rest
    }: {
        items: SelectItem[],
        onSelect?: (item: SelectItem) => void,
        value?: (any)[],
        defaultValue?: (number | string | undefined)[],
        multiple?: boolean
        placeholder?: string
        variant?: 'default' | 'reference' | 'model'
        showSelectedType?: boolean
        [key: string]: any
    } = $props();

    let activeItemsState = $derived.by(() => {
        const resultItems: SelectItem[] = [];
        const fillResult = (items: SelectItem[]) => {
            for (let item of items) {
                if (value.length > 0) {
                    if (value.includes(item.value)) {
                        resultItems.push(item);
                    }
                } else {
                    if (defaultValue.includes(item.value)) {
                        resultItems.push(item);
                    }
                }

                if (item.children && item.children.length > 0) {
                    fillResult(item.children);
                }
            }
        };
        fillResult(items);
        return resultItems;
    });

    let triggerObject: any = $state();
    let hoveredItem: SelectItem | null = $state(null);
    let isOpen = $state(false);

    function closeMenu() {
        triggerObject?.hide();
        isOpen = false;
        hoveredItem = null;
    }

    function handlerOnSelect(item: SelectItem) {
        if (item.selectable !== false) {
            onSelect?.(item);
            closeMenu();
        } else {
           if (variant === 'reference') {
               hoveredItem = item;
           } else {
               hoveredItem = hoveredItem === item ? null : item;
           }
        }
    }

    function handleMouseEnter(item: SelectItem) {
        if (variant === 'reference' && item.children && item.children.length > 0) {
            hoveredItem = item;
        }
    }

    function isMarkupIcon(icon?: string) {
        return typeof icon === 'string' && icon.trim().startsWith('<');
    }

</script>

{#snippet renderDefaultItems(items: SelectItem[], depth = 0)}
    {#each items as item}
        <button class="tf-select-default-item" style="padding-left: {10 + depth * 14}px" onclick={(e) => { e.stopPropagation(); handlerOnSelect(item); }}>
             <span class="tf-select-default-item-label">{item.label}</span>
        </button>
        {#if item.children && item.children.length > 0}
            <div class="tf-select-default-children">
                {@render renderDefaultItems(item.children, depth + 1)}
            </div>
        {/if}
    {/each}
{/snippet}

{#snippet renderModelItems(items: SelectItem[])}
    {#each items as group}
        {#if group.selectable === false}
            <div class="tf-select-model-group-title">
                {#if group.icon}
                   <span class="tf-select-model-group-icon">
                       {#if isMarkupIcon(group.icon)}
                           {@html group.icon}
                       {:else}
                           <img src={group.icon} alt="" />
                       {/if}
                   </span>
                {/if}
                <span>{group.label}</span>
            </div>
            {#each group.children || [] as model}
                <button class="tf-select-model-item {value.includes(model.value) ? 'active' : ''}" onclick={(e) => { e.stopPropagation(); handlerOnSelect(model); }}>
                    <div class="tf-select-model-icon">
                        {#if model.icon}
                            {#if isMarkupIcon(model.icon)}
                                {@html model.icon}
                            {:else}
                                <img src={model.icon} alt="" />
                            {/if}
                        {:else}
                            <div class="tf-select-model-avatar">{group.label ? group.label.toString().charAt(0) : 'M'}</div>
                        {/if}
                    </div>
                    <div class="tf-select-model-info">
                        <div class="tf-select-model-title">{model.label}</div>
                        {#if model.tags && model.tags.length > 0}
                            <div class="tf-select-model-tags">
                                {#each model.tags as tag}
                                    <span class="tf-select-model-tag">{tag}</span>
                                {/each}
                            </div>
                        {/if}
                        {#if model.description}
                            <div class="tf-select-model-desc">{model.description}</div>
                        {/if}
                    </div>
                </button>
            {/each}
        {:else}
            <button class="tf-select-model-item {value.includes(group.value) ? 'active' : ''}" onclick={(e) => { e.stopPropagation(); handlerOnSelect(group); }}>
                <div class="tf-select-model-icon">
                    {#if group.icon}
                        {#if isMarkupIcon(group.icon)}
                            {@html group.icon}
                        {:else}
                            <img src={group.icon} alt="" />
                        {/if}
                    {:else}
                        <div class="tf-select-model-avatar">{group.label ? group.label.toString().charAt(0) : 'M'}</div>
                    {/if}
                </div>
                <div class="tf-select-model-info">
                    <div class="tf-select-model-title">{group.label}</div>
                    {#if group.tags && group.tags.length > 0}
                        <div class="tf-select-model-tags">
                            {#each group.tags as tag}
                                <span class="tf-select-model-tag">{tag}</span>
                            {/each}
                        </div>
                    {/if}
                    {#if group.description}
                        <div class="tf-select-model-desc">{group.description}</div>
                    {/if}
                </div>
            </button>
        {/if}
    {/each}
{/snippet}

{#snippet renderNestedItems(items: SelectItem[], depth = 0)}
    {#each items as item}
        <div class="tf-select-item-container" style="padding-left: {depth * 16}px">
            <button class="tf-select-item {item.children && item.children.length > 0 ? 'has-children' : ''}"
                    onclick={() => handlerOnSelect(item)}>
                <div class="tf-parameter-label">
                    <div class="tf-parameter-name-wrapper">
                        {#if item.children && item.children.length > 0}
                            <span class="tf-parameter-expand-icon">
                                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"></polyline></svg>
                            </span>
                        {/if}
                        <span class="tf-parameter-name">{item.displayLabel || item.label}</span>
                    </div>
                    {#if item.dataType}
                        <span class="tf-parameter-type">{item.dataType}</span>
                    {/if}
                    {#if item.itemTypeLabel}
                        <span class="tf-parameter-meta">{item.itemTypeLabel}</span>
                    {/if}
                </div>
            </button>
        </div>
        {#if item.children && item.children.length > 0}
            <div class="tf-select-item-children">
                {@render renderNestedItems(item.children, depth + 1)}
            </div>
        {/if}
    {/each}
{/snippet}

<div {...rest} class="tf-select {rest['class']}">
    <FloatingTrigger
        bind:this={triggerObject}
        onShow={() => isOpen = true}
        onHide={() => { isOpen = false; hoveredItem = null; }}
        syncWidth={true}
        syncWidthMode={variant === 'default' ? 'equal' : 'min'}
    >
        <button class="tf-select-input nopan nodrag {isOpen ? 'active' : ''}" {...rest}>
            <div class="tf-select-input-value">
                {#each activeItemsState as item, index (`${index}_${item.value}`)}
                    {#if !multiple}
                        {#if index === 0}
                            <div class="tf-parameter-label-input">
                                {#if variant === 'reference' && item.nodeType && nodeIcons[item.nodeType]}
                                    <span class="tf-select-item-icon-input">
                                        {@html nodeIcons[item.nodeType]}
                                    </span>
                                {:else if variant === 'model' && item.icon}
                                    <span class="tf-select-item-icon-input-model">
                                        {#if isMarkupIcon(item.icon)}
                                            {@html item.icon}
                                        {:else}
                                            <img src={item.icon} alt="" />
                                        {/if}
                                    </span>
                                {/if}
                                <span class="tf-parameter-name">{item.displayLabel || item.label}</span>
                                {#if variant === 'reference' && showSelectedType && item.dataType}
                                    <span class="tf-parameter-type">{item.dataType}</span>
                                {/if}
                            </div>
                        {/if}
                    {:else}
                         <div class="tf-parameter-label-input">
                            {#if variant === 'reference' && item.nodeType && nodeIcons[item.nodeType]}
                                <span class="tf-select-item-icon-input">
                                    {@html nodeIcons[item.nodeType]}
                                </span>
                            {:else if variant === 'model' && item.icon}
                                <span class="tf-select-item-icon-input-model">
                                    {#if isMarkupIcon(item.icon)}
                                        {@html item.icon}
                                    {:else}
                                        <img src={item.icon} alt="" />
                                    {/if}
                                </span>
                            {/if}
                            <span class="tf-parameter-name">{item.displayLabel || item.label}</span>
                            {#if variant === 'reference' && showSelectedType && item.dataType}
                                <span class="tf-parameter-type">{item.dataType}</span>
                            {/if}
                        </div>
                        {#if index < activeItemsState.length - 1}
                            <span style="margin-right: 4px;">,</span>
                        {/if}
                    {/if}
                {:else}
                    <div class="tf-select-input-placeholder">
                        {placeholder}
                    </div>
                {/each}
            </div>
            <div class="tf-select-input-arrow">
                {#if variant === 'reference'}
                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M12 2L20.6603 7V17L12 22L3.33975 17V7L12 2Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                        <circle cx="12" cy="12" r="2" fill="currentColor"/>
                    </svg>
                {:else}
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
                        <path d="M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z"></path>
                    </svg>
                {/if}
            </div>
        </button>

        {#snippet floating()}
            {#if variant === 'default'}
                <div class="tf-select-default-wrapper nopan nodrag nowheel">
                    {@render renderDefaultItems(items)}
                </div>
            {:else if variant === 'model'}
                <div class="tf-select-model-wrapper nopan nodrag nowheel">
                    <div class="tf-select-model-header">
                        <span class="tf-select-model-header-title">Model selection</span>
                        <svg class="tf-select-model-header-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
                    </div>
                    <div class="tf-select-model-list">
                        {@render renderModelItems(items)}
                    </div>
                </div>
            {:else}
                <div class="tf-select-wrapper nopan nodrag nowheel {hoveredItem?.children?.length ? 'has-secondary' : ''}">
                    <!-- 一级列表：节点/分类 -->
                    <div class="tf-select-list tf-select-primary-list">
                        {#each items as item}
                            <button class="tf-select-item {hoveredItem?.value === item.value ? 'active' : ''}"
                                    onmouseenter={() => handleMouseEnter(item)}
                                    onclick={() => handlerOnSelect(item)}
                            >
                                <span class="tf-select-item-icon">
                                    {#if item.icon}
                                        {@html item.icon}
                                    {:else if item.nodeType && nodeIcons[item.nodeType]}
                                        {@html nodeIcons[item.nodeType]}
                                    {:else if item.children && item.children.length > 0}
                                         <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 7h18M3 12h18M3 17h18"></path></svg>
                                    {/if}
                                </span>
                                <span class="tf-select-item-label">{item.label}</span>
                                {#if item.children && item.children.length > 0}
                                    <span class="tf-select-item-arrow">
                                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>
                                    </span>
                                {/if}
                            </button>
                        {/each}
                    </div>

                    <!-- 二级列表：树形展示参数及其嵌套子项 -->
                    {#if hoveredItem && hoveredItem.children && hoveredItem.children.length > 0}
                        <div class="tf-select-list tf-select-secondary-list">
                            {@render renderNestedItems(hoveredItem.children)}
                        </div>
                    {/if}
                </div>
            {/if}
        {/snippet}
    </FloatingTrigger>
</div>

<style lang="less">
  :global(.tf-select > div:first-child) {
    display: flex;
    flex: 1;
    width: 100%;
    min-width: 0;
  }

  .tf-select-default-wrapper {
      display: flex;
      flex-direction: column;
      background: var(--tf-bg-surface);
      margin-top: 5px;
      border: 1px solid var(--tf-border-color);
      border-radius: 6px;
      padding: 4px;
      width: 100%;
      z-index: 99999;
      box-sizing: border-box;
      max-height: 220px;
      overflow: auto;
      box-shadow: var(--tf-shadow-soft);
  }

  .tf-select-default-item {
      display: flex;
      align-items: center;
      padding: 6px 12px;
      border: none;
      background: var(--tf-bg-surface);
      border-radius: 4px;
      cursor: pointer;
      line-height: 1.5;
      gap: 2px;
      width: 100%;
      text-align: left;
      font-size: 13px;
      color: var(--tf-text-primary);

      &:hover {
          background: var(--tf-bg-hover);
      }
  }

  .tf-select-default-children {
      display: flex;
      flex-direction: column;
  }

  /* Model Variant Styles */
  .tf-select-model-wrapper {
      display: flex;
      flex-direction: column;
      background: var(--tf-bg-surface);
      margin-top: 5px;
      border: 1px solid var(--tf-border-color);
      border-radius: 10px; 
      /* Removed fixed width to allow syncWidth to control it */
      z-index: 99999;
      box-sizing: border-box;
      max-height: 400px; 
      overflow: hidden;
      box-shadow: var(--tf-shadow-medium);
  }

  .tf-select-model-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 10px 12px; 
      border-bottom: 1px solid var(--tf-bg-muted);
      background: var(--tf-bg-surface);
  }

  .tf-select-model-header-title {
      font-size: 13px; 
      font-weight: 600;
      color: var(--tf-text-primary);
  }

  .tf-select-model-header-icon {
      width: 14px;
      height: 14px;
      color: var(--tf-text-secondary);
      cursor: pointer;
  }

  .tf-select-model-list {
      display: flex;
      flex-direction: column;
      padding: 8px; 
      overflow-y: auto;
      gap: 4px; 
  }

  .tf-select-model-group-title {
      font-size: 12px; 
      font-weight: 500;
      color: var(--tf-text-secondary);
      margin-top: 6px;
      margin-bottom: 2px;
      padding-left: 6px;
      display: flex;
      align-items: center;
      gap: 6px;
  }

  .tf-select-model-group-icon {
      width: 14px; 
      height: 14px;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
  }

  .tf-select-model-group-icon :global(svg), .tf-select-model-group-icon img {
      width: 100%;
      height: 100%;
      object-fit: contain;
  }

  .tf-select-model-group-title:first-child {
      margin-top: 0;
  }

  .tf-select-model-item {
      display: flex;
      align-items: flex-start;
      padding: 6px 8px; 
      border: none;
      background: transparent;
      border-radius: 6px;
      cursor: pointer;
      text-align: left;
      gap: 10px;
      transition: all 0.2s;
  }

  .tf-select-model-item:hover {
      background: var(--tf-bg-surface-alt);
  }

  .tf-select-model-item.active {
      background: var(--tf-primary-soft-bg);
  }

  .tf-select-model-icon {
      flex-shrink: 0;
      width: 32px; 
      height: 32px;
      border-radius: 6px;
      overflow: hidden;
      display: flex;
      align-items: center;
      justify-content: center;
      background: var(--tf-bg-muted);
      margin-top: 2px;
  }

  .tf-select-model-icon :global(svg), .tf-select-model-icon img {
      width: 70%; 
      height: 70%;
      object-fit: contain;
  }

  .tf-select-model-avatar {
      font-size: 14px;
      font-weight: 600;
      color: var(--tf-text-muted);
  }

  .tf-select-model-info {
      display: flex;
      flex-direction: column;
      gap: 2px; 
      flex-grow: 1;
      overflow: hidden;
  }

  .tf-select-model-title {
      font-size: 13px; 
      font-weight: 500;
      color: var(--tf-text-primary);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
  }

  .tf-select-model-tags {
      display: flex;
      flex-wrap: wrap;
      gap: 4px;
  }

  .tf-select-model-tag {
      background: var(--tf-bg-muted);
      color: var(--tf-text-secondary);
      font-size: 10px; 
      padding: 1px 6px;
      border-radius: 4px;
  }

  .tf-select-model-desc {
      font-size: 11px; 
      color: var(--tf-text-secondary);
      line-height: 1.3;
      margin-top: 2px;
      line-clamp: 2;
      display: -webkit-box;
      -webkit-line-clamp: 2; 
      -webkit-box-orient: vertical;  
      overflow: hidden;
  }

  /* Reference Variant Styles */
  .tf-select-wrapper {
    display: flex;
    background: var(--tf-bg-surface);
    border-radius: 12px;
    box-shadow: var(--tf-shadow-medium);
    border: 1px solid var(--tf-border-color);
    overflow: hidden;
    /* width expands naturally since createFloating sets minWidth, not width */
    width: max-content;
    box-sizing: border-box;
    max-height: 480px;
    z-index: 99999;
    margin-top: 5px;
  }

  .tf-select-list {
    display: flex;
    flex-direction: column;
    padding: 6px;
    overflow-y: auto;
    min-width: 0;

    &.tf-select-primary-list {
       width: 100%; /* Default fills the wrapper, which is minWidth-constrained by the input */
       flex-shrink: 0;
       background: var(--tf-bg-surface-alt);
    }

    /* When a secondary list is open, we fix the primary list to 100% of the input's width (done via absolute positioning or just keeping it wide enough) */
    .tf-select-wrapper.has-secondary &.tf-select-primary-list {
        /* Let it take the width of the input minus borders/paddings if needed, but minWidth handles it mostly */
        width: auto; 
        min-width: 160px;
    }

    &.tf-select-secondary-list {
       min-width: 188px;
       background: var(--tf-bg-surface);
       padding: 10px;
       border-left: 1px solid var(--tf-bg-muted);
       animation: slideIn 0.2s ease-out;
       box-sizing: border-box;
    }
  }  @keyframes slideIn {
    from { opacity: 0; transform: translateX(-10px); }
    to { opacity: 1; transform: translateX(0); }
  }

  .tf-select-item-container {
     position: relative;
     width: 100%;
     min-width: 0;
  }

  .tf-select-item-children {
     position: relative;
     &::before {
        content: '';
        position: absolute;
        left: 8px;
        top: 0;
        bottom: 0;
        width: 1px;
        background: var(--tf-border-color-soft);
     }
  }

  .tf-select-item {
    display: flex;
    align-items: center;
    padding: 8px 12px;
    border: none;
    background: transparent;
    border-radius: 8px;
    cursor: pointer;
    text-align: left;
    font-size: 13px;
    color: var(--tf-text-primary);
    gap: 10px;
    width: 100%;
    transition: all 0.15s;
    margin-bottom: 2px;

    &:hover {
      background: var(--tf-bg-muted);
    }

    &.active {
       background: var(--tf-primary-soft-bg);
       color: var(--tf-primary-color);
       font-weight: 500;
    }

    &.has-children {
       background: var(--tf-bg-hover);
       margin-bottom: 4px;
       &:hover {
          background: var(--tf-bg-active);
       }
    }

    &-icon {
       width: 22px;
       height: 22px;
       display: flex;
       align-items: center;
       justify-content: center;
       flex-shrink: 0;
       color: var(--tf-icon-color);
       background: var(--tf-icon-bg);
       border-radius: 5px;
       padding: 3px;
       box-sizing: border-box;

       :global(svg) {
          width: 16px;
          height: 16px;
       }
    }

    &-label {
       flex-grow: 1;
       white-space: nowrap;
       overflow: hidden;
       text-overflow: ellipsis;
    }

    &-arrow {
       width: 14px;
       height: 14px;
       color: var(--tf-text-muted);
    }
  }

  .tf-parameter-label-input {
     display: flex;
     align-items: center;
     gap: 4px;
     min-width: 0;
     flex: 1;
     overflow: hidden;

     .tf-select-item-icon-input {
         width: 18px;
         height: 18px;
         display: flex;
         align-items: center;
         justify-content: center;
         flex-shrink: 0;
         color: var(--tf-icon-color);
         background: var(--tf-icon-bg);
         border-radius: 4px;
         padding: 2px;
         box-sizing: border-box;

         :global(svg) {
            width: 12px;
            height: 12px;
         }
     }

     .tf-select-item-icon-input-model {
         width: 18px;
         height: 18px;
         display: flex;
         align-items: center;
         justify-content: center;
         flex-shrink: 0;
         border-radius: 4px;
         overflow: hidden;

         :global(svg), img {
            width: 100%;
            height: 100%;
            object-fit: contain;
         }
     }
  }

  .tf-parameter-label {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    width: 100%;
    gap: 8px;
    min-width: 0;
    overflow: hidden;
  }

  .tf-parameter-name-wrapper {
     display: flex;
     align-items: center;
     gap: 6px;
     min-width: 0;
     overflow: hidden;
  }

  .tf-parameter-expand-icon {
     width: 12px;
     height: 12px;
     color: currentColor;
     opacity: 0.6;
  }

  .tf-parameter-name {
    color: inherit;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .tf-parameter-type {
    background: var(--tf-bg-tag);
    color: var(--tf-text-secondary);
    padding: 2px 6px;
    border-radius: 4px;
    font-size: 11px;
    font-weight: 500;
    line-height: 1.2;
    white-space: nowrap;
    flex-shrink: 0;
  }

  .tf-parameter-meta {
    color: var(--tf-text-muted);
    font-size: 11px;
    white-space: nowrap;
    flex-shrink: 0;
  }
</style>
