/* ============================================================
   TOOLS & SERVICES MODULE
   Loaded before the Components Model, which reuses ToolLinkButton
   and ToolRow on a component's Links tab.
   ============================================================ */

const NEW_TOOL = (componentIds) => ({
  id:'', name:'', description:'', category:'General', status:'Active',
  primaryUrl:'', primaryLabel:'Production', vendor:'', owner:null,
  accessNotes:'', notes:'', componentIds: componentIds || [], links:[]
});

/**
 * The link control: the primary link is the button, everything else sits
 * behind the caret. With no extra links it collapses to a plain button.
 */
function ToolLinkButton({tool, size}){
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(()=>{
    if (!open) return;
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', h);
    return ()=>document.removeEventListener('mousedown', h);
  }, [open]);

  const extras = tool.links || [];
  return (
    <span className={'tool-link' + (extras.length ? '' : ' solo')} ref={ref}
          style={size === 'sm' ? {fontSize:12} : null}>
      <a className="go" href={tool.primaryUrl} target="_blank" rel="noopener noreferrer"
         title={`${tool.primaryLabel}: ${tool.primaryUrl}`}>
        <I.external size={13}/>
        <span className="lbl">{tool.primaryLabel || 'Open'}</span>
      </a>
      {extras.length > 0 &&
        <button type="button" className={'caret' + (open ? ' open' : '')}
                onClick={(e)=>{ e.stopPropagation(); setOpen(o=>!o); }}
                title={`${extras.length} more link${extras.length===1?'':'s'}`}>
          <I.chev size={13}/>
        </button>}
      {open &&
        <div className="tool-menu" onClick={e=>e.stopPropagation()}>
          <div className="tool-menu-head">{tool.name}</div>
          <a href={tool.primaryUrl} target="_blank" rel="noopener noreferrer">
            <span style={{color:'var(--accent)'}}><I.external size={14}/></span>
            <span style={{minWidth:0,flex:1}}>
              <span className="ml">{tool.primaryLabel}</span>
              <span className="mu" style={{display:'block'}}>{tool.primaryUrl}</span>
            </span>
            <Badge tone="accent">Primary</Badge>
          </a>
          {extras.map(l => (
            <a key={l.id} href={l.url} target="_blank" rel="noopener noreferrer">
              <span className="dim"><I.link size={14}/></span>
              <span style={{minWidth:0,flex:1}}>
                <span className="ml">{l.label}</span>
                <span className="mu" style={{display:'block'}}>{l.url}</span>
                {l.notes && <span className="mn">{l.notes}</span>}
              </span>
              <Badge tone="slate">{l.linkType}</Badge>
            </a>
          ))}
        </div>}
    </span>
  );
}

/** One tool as a row, used in the module list and on a component's Links tab. */
function ToolRow({tool, idx, go, onOpen, onUnlink, showComponents}){
  return (
    <div className="tool-row">
      <span className="tool-icon"><I.tool size={16}/></span>
      <div style={{flex:1,minWidth:0,cursor:onOpen?'pointer':'default'}}
           onClick={()=>onOpen && onOpen(tool)}>
        <div className="row" style={{gap:7}}>
          <span style={{fontWeight:600}}>{tool.name}</span>
          {tool.status !== 'Active' &&
            <Badge tone={TOOL_STATUS_TONE[tool.status]}>{tool.status}</Badge>}
          <Badge tone="slate">{tool.category}</Badge>
          {tool.links.length > 0 &&
            <span className="xsmall dim">+{tool.links.length} link{tool.links.length===1?'':'s'}</span>}
        </div>
        {tool.description && <div className="cell-sub truncate">{tool.description}</div>}
        {showComponents !== false && (tool.componentIds||[]).length > 0 &&
          <div className="pill-list" style={{marginTop:5}}>
            {tool.componentIds.slice(0,4).map(cid => idx.comp[cid]
              ? <span key={cid} className="badge accent" style={{cursor:'pointer'}}
                  onClick={(e)=>{ e.stopPropagation(); go({view:'component', id:cid}); }}>
                  {idx.comp[cid].identifier}</span>
              : null)}
            {tool.componentIds.length > 4 &&
              <span className="badge slate">+{tool.componentIds.length - 4}</span>}
          </div>}
        {showComponents !== false && !(tool.componentIds||[]).length &&
          <div className="xsmall dim" style={{marginTop:4}}>Standalone</div>}
      </div>
      <ToolLinkButton tool={tool}/>
      {onUnlink &&
        <button className="icon-btn" title="Unlink from this component" onClick={()=>onUnlink(tool)}>
          <I.x size={14}/></button>}
    </div>
  );
}

/* ----------------------------------------------------------------- module */

function ToolsModule({state, idx, go, act, toast, route}){
  const [q, setQ] = useState(()=>urlParam('q'));
  const [fCategory, setFCategory] = useState(()=>urlParam('category'));
  const [fStatus, setFStatus] = useState(()=>urlParam('status'));
  const [fScope, setFScope] = useState(()=>urlParam('scope'));
  const [fComponent, setFComponent] = useState(()=>urlParam('component'));
  const [view, setView] = useState(()=>urlParam('view','list'));
  const [editing, setEditing] = useState(null);
  const [open, setOpen] = useState(null);
  useFilterUrlSync({q:[q,''], category:[fCategory,''], status:[fStatus,''], scope:[fScope,''],
    component:[fComponent,''], view:[view,'list']});

  const canEdit = (id) => {
    const ids = state.permissions.editableToolIds;
    return ids === '*' || (Array.isArray(ids) && ids.includes(id));
  };
  const canCreate = state.permissions.editableToolIds === '*'
    || state.permissions.editableComponentIds === '*'
    || (Array.isArray(state.permissions.editableComponentIds)
        && state.permissions.editableComponentIds.length > 0);

  useEffect(()=>{
    if (route && route.action === 'new' && canCreate) setEditing(NEW_TOOL());
  }, [route]);

  const categories = state.lookups.tool_category || [];
  const rows = useMemo(()=>{
    const term = q.trim().toLowerCase();
    return state.tools.filter(t => {
      if (fCategory && t.category !== fCategory) return false;
      if (fStatus && t.status !== fStatus) return false;
      if (fScope === 'standalone' && (t.componentIds||[]).length) return false;
      if (fScope === 'linked' && !(t.componentIds||[]).length) return false;
      if (fScope === 'multi' && !(t.links||[]).length) return false;
      if (fComponent && !(t.componentIds||[]).includes(fComponent)) return false;
      if (!term) return true;
      return [t.name, t.description, t.category, t.vendor, t.primaryUrl, t.accessNotes,
        partyName(t.owner, idx),
        (t.links||[]).map(l => l.label + ' ' + l.url).join(' '),
        (t.componentIds||[]).map(cid => (idx.comp[cid]||{}).name).join(' ')
      ].join(' ').toLowerCase().includes(term);
    });
  }, [state.tools, q, fCategory, fStatus, fScope, fComponent, idx]);

  const grouped = {};
  rows.forEach(t => { (grouped[t.category] = grouped[t.category] || []).push(t); });

  const exportList = () => exportCsv('fuse-tools.csv',
    ['Name','Category','Status','Primary label','Primary URL','Extra links','Vendor','Owner',
     'Components','Access notes'],
    rows.map(t => [t.name, t.category, t.status, t.primaryLabel, t.primaryUrl,
      (t.links||[]).map(l => `${l.label} <${l.url}>`).join(' | '), t.vendor, partyName(t.owner, idx),
      (t.componentIds||[]).map(cid => (idx.comp[cid]||{}).identifier).filter(Boolean).join(' '),
      t.accessNotes]));

  return (
    <div className="mod">
      <div className="mod-head">
        <div className="stats-row">
          <div className="stat"><div className="n">{state.tools.length}</div><div className="l">Tools</div></div>
          <div className="stat"><div className="n">{state.tools.filter(t=>!(t.componentIds||[]).length).length}</div>
            <div className="l">Standalone</div></div>
          <div className="stat"><div className="n">{state.tools.filter(t=>(t.componentIds||[]).length).length}</div>
            <div className="l">On a component</div></div>
          <div className="stat"><div className="n">{state.tools.reduce((s,t)=>s+(t.links||[]).length,0)}</div>
            <div className="l">Extra links</div></div>
          <div className="stat"><div className="n" style={{color: state.tools.filter(t=>t.status!=='Active').length ? 'var(--amber)' : undefined}}>
            {state.tools.filter(t=>t.status!=='Active').length}</div>
            <div className="l">Deprecated</div></div>
        </div>

        <div className="row wrap">
          <ViewSwitch value={view} onChange={setView} views={[
            {k:'list', label:'List', icon:<I.list size={13}/>},
            {k:'cards', label:'Cards', icon:<I.grid size={13}/>}
          ]}/>
          <div className="spacer"/>
          <button className="btn" onClick={exportList}><I.down size={14}/>CSV</button>
        </div>

        <div className="row wrap">
          <SearchBox value={q} onChange={setQ} aria="Search tools and services"
                     title="Search name, URL, component or owner"/>
          <select style={{width:'auto'}} value={fCategory} onChange={e=>setFCategory(e.target.value)}>
            <option value="">All categories</option>{categories.map(c=><option key={c}>{c}</option>)}
          </select>
          <select style={{width:'auto'}} value={fStatus} onChange={e=>setFStatus(e.target.value)}>
            <option value="">All statuses</option>
            {(state.toolStatuses||[]).map(s=><option key={s}>{s}</option>)}
          </select>
          <select style={{width:'auto'}} value={fScope} onChange={e=>setFScope(e.target.value)}>
            <option value="">Everything</option>
            <option value="linked">On a component</option>
            <option value="standalone">Standalone only</option>
            <option value="multi">Has extra links</option>
          </select>
          <select style={{width:'auto',maxWidth:220}} value={fComponent} onChange={e=>setFComponent(e.target.value)}>
            <option value="">Any component</option>
            {state.components.map(c=><option key={c.id} value={c.id}>{c.identifier} — {c.name}</option>)}
          </select>
          {(q||fCategory||fStatus||fScope||fComponent) &&
            <button className="btn ghost sm" onClick={()=>{
              setQ('');setFCategory('');setFStatus('');setFScope('');setFComponent('');
            }}>Clear</button>}
          <div className="spacer"/>
          <span className="xsmall dim">{rows.length} shown</span>
        </div>
      </div>

      <div className="mod-body">
      {rows.length === 0
        ? <div className="card"><EmptyState icon={<I.tool size={28}/>}
            title={(q||fCategory||fStatus||fScope||fComponent) ? 'No tools match' : 'Nothing here yet'}
            body="Every link people need, whether it belongs to a component or stands on its own."
            action={(q||fCategory||fStatus||fScope||fComponent)
              ? <button className="btn sm" onClick={()=>{
                  setQ('');setFCategory('');setFStatus('');setFScope('');setFComponent('');
                }}>Clear filters</button>
              : canCreate ? <button className="btn primary sm" onClick={()=>setEditing(NEW_TOOL())}>
                  Add the first tool</button> : null}/></div>
        : view === 'list'
          ? <div className="stack mod-scroll">
              {Object.keys(grouped).sort().map(cat => (
                <div className="card" key={cat}>
                  <div className="card-head"><h3>{cat}</h3><Badge tone="slate">{grouped[cat].length}</Badge></div>
                  <div>
                    {grouped[cat].map(t =>
                      <ToolRow key={t.id} tool={t} idx={idx} go={go} onOpen={setOpen}/>)}
                  </div>
                </div>
              ))}
            </div>
          : <div className="grid mod-scroll" style={{gridTemplateColumns:'repeat(auto-fit,minmax(300px,1fr))',alignContent:'start'}}>
              {rows.map(t => (
                <div className="tool-card" key={t.id}>
                  <div className="row" style={{gap:10,alignItems:'flex-start'}}>
                    <span className="tool-icon"><I.tool size={16}/></span>
                    <div style={{flex:1,minWidth:0,cursor:'pointer'}} onClick={()=>setOpen(t)}>
                      <div style={{fontWeight:650}}>{t.name}</div>
                      <div className="cell-sub">{t.category}{t.vendor ? ' · ' + t.vendor : ''}</div>
                    </div>
                    {t.status !== 'Active' && <Badge tone={TOOL_STATUS_TONE[t.status]}>{t.status}</Badge>}
                  </div>
                  {t.description && <div className="small muted">{t.description}</div>}
                  <div className="row wrap" style={{gap:8}}>
                    <ToolLinkButton tool={t}/>
                    <div className="spacer"/>
                    <span className="xsmall dim">
                      {(t.componentIds||[]).length
                        ? `${t.componentIds.length} component${t.componentIds.length===1?'':'s'}`
                        : 'Standalone'}</span>
                  </div>
                </div>
              ))}
            </div>}
      </div>

      {open &&
        <ToolDetail tool={state.tools.find(t => t.id === open.id) || open}
          state={state} idx={idx} go={go} act={act} editable={canEdit(open.id)}
          onClose={()=>setOpen(null)}
          onEdit={()=>{ setEditing(state.tools.find(t => t.id === open.id)); setOpen(null); }}/>}

      {editing &&
        <ToolForm value={editing} state={state} onClose={()=>setEditing(null)}
          onSave={async (v)=>{
            const isNew = !v.id;
            const ok = await act(isNew ? API.post('/api/tools', v) : API.put(`/api/tools/${v.id}`, v),
              isNew ? 'Tool created' : 'Tool saved');
            if (ok) setEditing(null);
          }}/>}
    </div>
  );
}

/* ----------------------------------------------------------------- detail */

function ToolDetail({tool, state, idx, go, act, editable, onClose, onEdit}){
  const owner = resolveParty(tool.owner, idx);
  const linked = (tool.componentIds||[]).map(id => idx.comp[id]).filter(Boolean);

  return (
    <Modal wide title={tool.name} onClose={onClose}
      footer={<>
        <button className="btn" onClick={onClose}>Close</button>
        {editable && <button className="btn primary" onClick={onEdit}><I.edit size={14}/>Edit</button>}
      </>}>
      <div className="row wrap" style={{gap:8, marginBottom:14}}>
        <Badge tone={TOOL_STATUS_TONE[tool.status] || 'slate'} dot>{tool.status}</Badge>
        <Badge tone="slate">{tool.category}</Badge>
        {tool.vendor && <Badge tone="blue">{tool.vendor}</Badge>}
        <div className="spacer"/>
        <ToolLinkButton tool={tool}/>
      </div>

      {tool.description && <p className="muted pre-wrap" style={{marginTop:0}}>{tool.description}</p>}

      <div className="sub-head">Links</div>
      <div className="card">
        <div className="link-row">
          <span style={{color:'var(--accent)'}}><I.external size={16}/></span>
          <a href={tool.primaryUrl} target="_blank" rel="noopener noreferrer" style={{flex:1,minWidth:0}}>
            <div style={{fontWeight:600}}>{tool.primaryLabel}</div>
            <div className="link-url">{tool.primaryUrl}</div>
          </a>
          <Badge tone="accent">Primary</Badge>
        </div>
        {(tool.links||[]).map(l => (
          <div className="link-row" key={l.id}>
            <span className="dim"><I.link size={16}/></span>
            <a href={l.url} target="_blank" rel="noopener noreferrer" style={{flex:1,minWidth:0}}>
              <div style={{fontWeight:600}}>{l.label}</div>
              <div className="link-url">{l.url}</div>
              {l.notes && <div className="xsmall muted" style={{marginTop:2}}>{l.notes}</div>}
            </a>
            <Badge tone="slate">{l.linkType}</Badge>
          </div>
        ))}
        {!(tool.links||[]).length &&
          <div className="card-body xsmall dim" style={{paddingTop:0}}>
            No additional links. Add staging, admin or documentation URLs and they appear in the
            dropdown next to the primary link.
          </div>}
      </div>

      <dl className="kv-block" style={{marginTop:16}}>
        <dt>Owner</dt><dd>{owner
          ? <span className="row" style={{gap:7}}><PartyAvatar resolved={owner} size="sm"/>{owner.name}
              <span className="dim small">{owner.sub}</span></span>
          : <span className="dim">Not assigned</span>}</dd>
        <dt>Access</dt><dd className="pre-wrap">{tool.accessNotes || <span className="dim">Not recorded</span>}</dd>
        {tool.notes && <><dt>Notes</dt><dd className="pre-wrap">{tool.notes}</dd></>}
        <dt>Added</dt><dd className="small muted">{fmtDateTime(tool.createdAt)} by {tool.createdBy}</dd>
        <dt>Last updated</dt><dd className="small muted">{fmtDateTime(tool.updatedAt)} by {tool.updatedBy}</dd>
      </dl>

      <div className="sub-head">Components</div>
      {linked.length
        ? <div className="pill-list">
            {linked.map(c =>
              <span key={c.id} className="chip-toggle" style={{cursor:'pointer'}}
                onClick={()=>{ onClose(); go({view:'component', id:c.id}); }}>
                <TierBadge tier={c.tier}/> <span style={{marginLeft:5}}>{c.name}</span></span>)}
          </div>
        : <p className="dim small" style={{margin:0}}>
            Standalone. This tool is not attached to anything in the Components Model.</p>}
    </Modal>
  );
}

/* ------------------------------------------------------------------- form */

function ToolForm({value, state, onClose, onSave, lockedComponentId}){
  const [t, setT] = useState(()=>clone(value));
  const [busy, setBusy] = useState(false);
  const set = (k,v) => setT(x => ({...x, [k]:v}));
  const isNew = !value.id;
  const categories = state.lookups.tool_category || ['General'];
  const linkTypes = state.toolLinkTypes || ['Other'];

  const setLink = (i, patch) =>
    setT(x => ({...x, links: x.links.map((l, j) => j === i ? {...l, ...patch} : l)}));
  const addLink = () =>
    setT(x => ({...x, links: [...x.links, {label:'', url:'', linkType:'Other', notes:''}]}));
  const removeLink = (i) =>
    setT(x => ({...x, links: x.links.filter((l, j) => j !== i)}));

  const valid = t.name.trim() && t.primaryUrl.trim()
    && t.links.every(l => (!l.label.trim() && !l.url.trim()) || (l.label.trim() && l.url.trim()));

  return (
    <Modal wide title={isNew ? 'New tool or service' : 'Edit ' + value.name} onClose={onClose}
      footer={<>
        <button className="btn" onClick={onClose} disabled={busy}>Cancel</button>
        <button className="btn primary" disabled={!valid || busy}
          onClick={async ()=>{
            setBusy(true);
            try {
              await onSave({...t, links: t.links.filter(l => l.label.trim() && l.url.trim())});
            } finally { setBusy(false); }
          }}>{busy ? 'Saving…' : isNew ? 'Create tool' : 'Save changes'}</button>
      </>}>
      <div className="form-grid">
        <Field label="Name"><input type="text" value={t.name} autoFocus
          onChange={e=>set('name', e.target.value)} placeholder="e.g. Grafana"/></Field>
        <Field label="Category">
          <select value={t.category} onChange={e=>set('category', e.target.value)}>
            {categories.map(c => <option key={c}>{c}</option>)}</select></Field>
      </div>
      <Field label="Description"><textarea value={t.description}
        onChange={e=>set('description', e.target.value)}
        placeholder="What is this for, and who uses it?"/></Field>

      <div className="sub-head">Primary link</div>
      <div className="info-box" style={{marginBottom:14}}>
        The primary link is what people click first — normally the production system. Everything
        else you add below appears in the dropdown next to it.
      </div>
      <div className="form-grid">
        <Field label="Primary URL"><input type="url" value={t.primaryUrl}
          onChange={e=>set('primaryUrl', e.target.value)} placeholder="https://"/></Field>
        <Field label="Button label" hint="What the button says. Production by default.">
          <input type="text" value={t.primaryLabel}
            onChange={e=>set('primaryLabel', e.target.value)} placeholder="Production"/></Field>
      </div>

      <div className="sub-head">Additional links</div>
      {t.links.length === 0 &&
        <p className="dim small" style={{marginTop:0}}>
          None yet. Add staging, admin consoles, documentation or status pages.</p>}
      {t.links.map((l, i) => (
        <div key={i} className="card" style={{padding:12, marginBottom:10}}>
          <div className="row" style={{gap:10, alignItems:'flex-start'}}>
            <div style={{flex:1}}>
              <div className="form-grid">
                <Field label="Label" style={{marginBottom:8}}>
                  <input type="text" value={l.label} onChange={e=>setLink(i, {label:e.target.value})}
                    placeholder="e.g. Staging"/></Field>
                <Field label="Type" style={{marginBottom:8}}>
                  <select value={l.linkType} onChange={e=>setLink(i, {linkType:e.target.value})}>
                    {linkTypes.map(x => <option key={x}>{x}</option>)}</select></Field>
              </div>
              <Field label="URL" style={{marginBottom:8}}>
                <input type="url" value={l.url} onChange={e=>setLink(i, {url:e.target.value})}
                  placeholder="https://"/></Field>
              <Field label="Note" style={{marginBottom:0}}>
                <input type="text" value={l.notes || ''} onChange={e=>setLink(i, {notes:e.target.value})}
                  placeholder="Anything worth knowing before clicking"/></Field>
            </div>
            <button className="icon-btn" title="Remove this link" onClick={()=>removeLink(i)}>
              <I.trash size={15}/></button>
          </div>
        </div>
      ))}
      <button className="btn sm" onClick={addLink}><I.plus size={13}/>Add another link</button>

      <div className="sub-head">Ownership and access</div>
      <div className="form-grid">
        <Field label="Owner"><PartySelect value={t.owner} state={state} onChange={v=>set('owner', v)}/></Field>
        <Field label="Vendor"><input type="text" value={t.vendor}
          onChange={e=>set('vendor', e.target.value)} placeholder="In-house or vendor name"/></Field>
        <Field label="Status">
          <select value={t.status} onChange={e=>set('status', e.target.value)}>
            {(state.toolStatuses||['Active']).map(s => <option key={s}>{s}</option>)}</select></Field>
      </div>
      <Field label="How to get access" hint="Who can use it, and how someone requests access.">
        <textarea value={t.accessNotes} onChange={e=>set('accessNotes', e.target.value)}/></Field>

      <div className="sub-head">Components</div>
      {lockedComponentId
        ? <p className="small muted" style={{marginTop:0}}>
            This tool will be attached to the component you are working on. You can add more
            components later from Tools &amp; Services.</p>
        : <>
            <ComponentPicker state={state} value={t.componentIds} onChange={v=>set('componentIds', v)}/>
            <div className="hint" style={{marginTop:8}}>
              {'Leave empty for a standalone tool. Anything you attach here appears on that ' +
               'component’s Links tab.'}
            </div>
          </>}
    </Modal>
  );
}
