/* ========================================================================
   SAVE SEARCH MODAL — naming + folder comboboxes; also handles the
   Save-as-Profile / Save-as-Persona preset modes. Port of 06-render.js.
   ======================================================================== */

var saveModalMode = null;   // null | 'search' | 'target' | 'persona'

function openSaveSearchDialog() { saveModalMode = 'search'; notify(); }
function openSavePresetDialog(kind) { saveModalMode = kind; notify(); }
function closeSaveSearchDialog() { saveModalMode = null; notify(); }

function presetSaveAvailable(kind) {
  const controlled = kind === 'target' ? TARGET_CONTROLLED : PERSONA_CONTROLLED;
  const presetFieldId = kind === 'target' ? 'account.target' : 'contact.persona';
  if (state.filters.some(f => f.fieldId === presetFieldId && isFilterComplete(f))) return false;
  return state.filters.some(f => isFilterComplete(f) && controlled.has(f.fieldId));
}

function suggestSearchName() {
  const committed = state.filters.filter(isFilterComplete);
  if (committed.length === 0) return 'Untitled search';
  const labels = committed.slice(0, 2).map(f => {
    const fl = FIELD_BY_ID[f.fieldId];
    return fl ? fl.label : '';
  }).filter(Boolean);
  return labels.join(' · ') || 'Untitled search';
}
function suggestPresetName(kind) {
  const controlled = kind === 'target' ? TARGET_CONTROLLED : PERSONA_CONTROLLED;
  const labels = state.filters.filter(isFilterComplete)
    .filter(f => controlled.has(f.fieldId))
    .slice(0, 2)
    .map(f => FIELD_BY_ID[f.fieldId]?.label || '')
    .filter(Boolean);
  if (kind === 'target') return 'Untitled Profile';
  if (labels.length === 0) return 'Untitled persona';
  return labels.join(' · ');
}

function compileTargetSpec(committed) {
  const spec = { name: '' };
  const asArray = (v) => {
    if (v && typeof v === 'object' && !Array.isArray(v) && Array.isArray(v.include)) return v.include.slice();
    return Array.isArray(v) ? v.slice() : [v];
  };
  committed.forEach(f => {
    const v = f.value;
    switch (f.fieldId) {
      case 'account.type':   spec.type = asArray(v); break;
      case 'account.state':  spec.state = asArray(v); break;
      case 'account.region': spec.region = asArray(v); break;
      case 'account.budget':
        if (f.op === 'gt' || f.op === 'gte' || f.op === 'eq') spec.budgetMin = Number(v);
        else if (f.op === 'lt' || f.op === 'lte') spec.budgetMax = Number(v);
        else if (f.op === 'between' && Array.isArray(v)) { spec.budgetMin = Number(v[0]); spec.budgetMax = Number(v[1]); }
        break;
      case 'account.population':
        if (f.op === 'gt' || f.op === 'gte' || f.op === 'eq') spec.populationMin = Number(v);
        else if (f.op === 'lt' || f.op === 'lte') spec.populationMax = Number(v);
        else if (f.op === 'between' && Array.isArray(v)) { spec.populationMin = Number(v[0]); spec.populationMax = Number(v[1]); }
        break;
      case 'opp.signals':  spec.themes = asArray(v); break;
      case 'signal.type':  spec.signalType = asArray(v); break;
      case 'signal.daysAgo':
        if (f.op === 'lt' || f.op === 'lte') spec.daysAgoMax = Number(v);
        break;
      case 'opp.competitors':
        if (f.op === 'entIs') spec.competitors = [String(v)];
        break;
      case 'opp.keywords':
        if (f.op === 'tokAny') spec.keywords = Array.isArray(v) ? v.slice() : [String(v)];
        if (f.op === 'tokNone') spec.keywordsNone = Array.isArray(v) ? v.slice() : [String(v)];
        break;
      case 'src.hubspot':
      case 'src.salesforce':
      case 'src.enrichment': {
        const src = f.fieldId.split('.')[1];
        spec.dataSources = [...(spec.dataSources || []), src];
        break;
      }
    }
  });
  return spec;
}
function compilePersonaSpec(committed) {
  const spec = { name: '' };
  const asArray = (v) => {
    if (v && typeof v === 'object' && !Array.isArray(v) && Array.isArray(v.include)) return v.include.slice();
    return Array.isArray(v) ? v.slice() : [v];
  };
  committed.forEach(f => {
    const v = f.value;
    switch (f.fieldId) {
      case 'contact.title':      spec.title = asArray(v); break;
      case 'contact.department': spec.department = asArray(v); break;
      case 'contact.seniority':  spec.seniority = [String(v)]; break;
      case 'contact.confidence': spec.confidence = [String(v)]; break;
    }
  });
  return spec;
}

function commitSaveTargetNamed(name) {
  const committed = state.filters.filter(isFilterComplete).filter(f => TARGET_CONTROLLED.has(f.fieldId));
  if (committed.length === 0) return;
  const spec = compileTargetSpec(committed);
  spec.name = name;
  TARGETS.unshift(spec);
  state.filters = state.filters.filter(f => !TARGET_CONTROLLED.has(f.fieldId));
  state.filters.push({ id: uid(), fieldId: 'account.target', op: 'tgtIs', value: [name] });
  saveModalMode = null;
  notify();
}
function commitSavePersonaNamed(name) {
  const committed = state.filters.filter(isFilterComplete).filter(f => PERSONA_CONTROLLED.has(f.fieldId));
  if (committed.length === 0) return;
  const spec = compilePersonaSpec(committed);
  spec.name = name;
  PERSONAS.unshift(spec);
  state.filters = state.filters.filter(f => !PERSONA_CONTROLLED.has(f.fieldId));
  state.filters.push({ id: uid(), fieldId: 'contact.persona', op: 'persIs', value: [name] });
  saveModalMode = null;
  notify();
}
function commitSaveSearchNamed(name, folder) {
  const committed = state.filters.filter(isFilterComplete);
  if (committed.length === 0) return;
  const id = 'ss' + (SAVED_SEARCHES.length + 1) + '_' + Math.random().toString(36).slice(2, 5);
  SAVED_SEARCHES.unshift({
    id, name, folder: folder || null, count: committed.length,
    entity: state.entity,
    filterSpecs: committed.map(f => ({ fieldId: f.fieldId, op: f.op, value: deepClone(f.value) })),
  });
  if (folder && !SAVED_SEARCH_FOLDERS.includes(folder)) SAVED_SEARCH_FOLDERS.push(folder);
  state.activeSavedSearchId = id;
  saveModalMode = null;
  notify();
}

/* ---- modal component -------------------------------------------------------- */
function SaveSearchModal() {
  useAppState();
  const mode = saveModalMode;
  if (!mode) return null;
  return <SaveSearchModalBody key={mode} mode={mode} />;
}

function SaveSearchModalBody({ mode }) {
  const isPreset = mode === 'target' || mode === 'persona';
  const [name, setName] = React.useState(() => isPreset ? suggestPresetName(mode) : suggestSearchName());
  const [folder, setFolder] = React.useState('');
  const [folderIsNew, setFolderIsNew] = React.useState(false);
  const [namePopOpen, setNamePopOpen] = React.useState(false);
  const [folderPopOpen, setFolderPopOpen] = React.useState(false);
  const nameRef = React.useRef(null);

  React.useEffect(() => {
    setTimeout(() => { if (nameRef.current) { nameRef.current.focus(); nameRef.current.select(); } }, 50);
  }, []);

  const committedAll = state.filters.filter(isFilterComplete);
  const controlled = mode === 'target' ? TARGET_CONTROLLED : mode === 'persona' ? PERSONA_CONTROLLED : null;
  const committed = controlled ? committedAll.filter(f => controlled.has(f.fieldId)) : committedAll;
  const canSave = !!name.trim() && committed.length > 0;

  const title = mode === 'target' ? 'Save as Profile' : mode === 'persona' ? 'Save as Persona' : 'Save this search';
  const saveLabel = mode === 'target' ? 'Save Profile' : mode === 'persona' ? 'Save Persona' : 'Save';

  const doSave = () => {
    if (!canSave) return;
    if (mode === 'target') return commitSaveTargetNamed(name.trim());
    if (mode === 'persona') return commitSavePersonaNamed(name.trim());
    commitSaveSearchNamed(name.trim(), folder.trim() || null);
  };

  const nameMatches = (() => {
    if (!namePopOpen || isPreset) return null;
    const q = name.trim().toLowerCase();
    const matches = q ? SAVED_SEARCHES.filter(s => s.name.toLowerCase().includes(q)) : SAVED_SEARCHES;
    return { q, matches: matches.slice(0, 6), exact: matches.some(s => s.name.toLowerCase() === q) };
  })();

  const folderMatches = (() => {
    if (!folderPopOpen) return null;
    const q = folder.trim().toLowerCase();
    const matches = q ? SAVED_SEARCH_FOLDERS.filter(f => f.toLowerCase().includes(q)) : SAVED_SEARCH_FOLDERS;
    return { q, matches, exact: SAVED_SEARCH_FOLDERS.some(f => f.toLowerCase() === q) };
  })();

  return (
    <div className="modal-overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) closeSaveSearchDialog(); }}>
      <div className="modal" role="dialog" aria-labelledby="ss-modal-title">
        <div className="modal-header">
          <div className="modal-title" id="ss-modal-title">{title}</div>
          <button className="modal-close" aria-label="Close" onClick={closeSaveSearchDialog}>×</button>
        </div>
        <div className="modal-body">
          <div className="modal-field">
            <label className="modal-field-label" htmlFor="ss-name-input">Name</label>
            <div className="modal-combo-wrap">
              <input
                ref={nameRef}
                className="modal-input" id="ss-name-input" type="text" autoComplete="off"
                placeholder={mode === 'target' ? 'Give this profile a name…' : mode === 'persona' ? 'Give this persona a name…' : 'Give this search a name…'}
                value={name}
                onChange={(e) => { setName(e.target.value); setNamePopOpen(true); }}
                onFocus={() => setNamePopOpen(true)}
                onBlur={() => setTimeout(() => setNamePopOpen(false), 120)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') { e.preventDefault(); setNamePopOpen(false); }
                  if (e.key === 'Escape') closeSaveSearchDialog();
                }}
              />
            </div>
            {nameMatches && (nameMatches.matches.length || nameMatches.q) ? (
              <div className="modal-combo-popover">
                {nameMatches.matches.map(s => (
                  <div className="modal-combo-item" key={s.id}
                    onMouseDown={(e) => { e.preventDefault(); setName(s.name); setNamePopOpen(false); }}>
                    <Icon name="bookmark" size={14} style={{ color: 'var(--muted-foreground)' }} />
                    <span>{s.name}</span>
                  </div>
                ))}
                {nameMatches.q && !nameMatches.exact ? (
                  <div className="modal-combo-item modal-combo-create"
                    onMouseDown={(e) => { e.preventDefault(); setNamePopOpen(false); }}>
                    <Icon name="plus" size={14} />
                    Create "{name.trim()}"
                  </div>
                ) : null}
              </div>
            ) : null}
          </div>
          {!isPreset ? (
            <div className="modal-field">
              <label className="modal-field-label" htmlFor="ss-folder-input">Folder</label>
              <div className="modal-combo-wrap">
                <input
                  className="modal-input" id="ss-folder-input" type="text" autoComplete="off"
                  placeholder="Pick or create a folder (optional)…"
                  value={folder}
                  onChange={(e) => { setFolder(e.target.value); setFolderIsNew(false); setFolderPopOpen(true); }}
                  onFocus={() => setFolderPopOpen(true)}
                  onBlur={() => setTimeout(() => setFolderPopOpen(false), 120)}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') { e.preventDefault(); setFolderPopOpen(false); }
                    if (e.key === 'Escape') closeSaveSearchDialog();
                  }}
                />
                {folderIsNew ? <span className="modal-badge">new</span> : null}
                {folder.trim() ? (
                  <button className="modal-input-clear" type="button" aria-label="Clear"
                    onClick={() => { setFolder(''); setFolderIsNew(false); }}>×</button>
                ) : null}
              </div>
              {folderMatches ? (
                <div className="modal-combo-popover">
                  {folderMatches.matches.map(f => (
                    <div className="modal-combo-item" key={f}
                      onMouseDown={(e) => { e.preventDefault(); setFolder(f); setFolderIsNew(false); setFolderPopOpen(false); }}>
                      <Icon name="folder" size={14} style={{ color: 'var(--muted-foreground)' }} />
                      <span>{f}</span>
                    </div>
                  ))}
                  {folderMatches.q && !folderMatches.exact ? (
                    <div className="modal-combo-item modal-combo-create"
                      onMouseDown={(e) => { e.preventDefault(); setFolderIsNew(true); setFolderPopOpen(false); }}>
                      <Icon name="plus" size={14} />
                      Create folder "{folder.trim()}"
                    </div>
                  ) : null}
                </div>
              ) : null}
            </div>
          ) : null}
          <div className="modal-field modal-field-tight">
            <span className="modal-field-label">{isPreset ? 'Bundled filters' : 'Active filters'}</span>
            <div className="modal-filter-summary">
              {committed.length === 0
                ? <em>{isPreset ? `No ${mode === 'target' ? 'account-level' : 'contact-level'} filters set yet.` : 'No filters applied yet.'}</em>
                : <React.Fragment>
                    <strong>{committed.length}</strong> filter{committed.length === 1 ? '' : 's'}
                    {isPreset ? ` will be bundled into this ${mode === 'target' ? 'profile' : 'persona'}: ` : <React.Fragment> on <strong>{ENTITY[state.entity].plural}</strong>: </React.Fragment>}
                    {committed.map((f, i) => (
                      <React.Fragment key={f.id}>{i > 0 ? ', ' : ''}<span>{displayLabel(FIELD_BY_ID[f.fieldId], state.entity)}</span></React.Fragment>
                    ))}
                  </React.Fragment>}
            </div>
          </div>
        </div>
        <div className="modal-footer">
          <button className="btn-modal" onClick={closeSaveSearchDialog}>Cancel</button>
          <button className="btn-modal btn-modal-primary" disabled={!canSave} onClick={doSave}>{saveLabel}</button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  SaveSearchModal, openSaveSearchDialog, openSavePresetDialog, closeSaveSearchDialog,
  presetSaveAvailable, suggestSearchName, compileTargetSpec, compilePersonaSpec,
});
