// Thread Formatter — split long text into Twitter/X or Mastodon threads.

window.TOOL_HANDLERS['thread-formatter'] = function ThreadFormatterTool() {
  const [text, setText] = React.useState('');
  const [limitMode, setLimitMode] = React.useState('280');
  const [customLimit, setCustomLimit] = React.useState(280);
  const [numberStyle, setNumberStyle] = React.useState('1/n');
  const [splitMode, setSplitMode] = React.useState('sentence');
  const [copiedAll, setCopiedAll] = React.useState(false);
  const [copiedIdx, setCopiedIdx] = React.useState(-1);

  const charLimit = limitMode === 'custom' ? customLimit : Number(limitMode);

  const threads = React.useMemo(() => {
    const trimmed = text.trim();
    if (!trimmed) return [];

    // Build numbering prefix for a given index/total
    function makePrefix(idx, total) {
      switch (numberStyle) {
        case '1/n':   return (idx + 1) + '/' + total + ' ';
        case '(1/n)': return '(' + (idx + 1) + '/' + total + ') ';
        case 'emoji': return '\u{1F9F5} ' + (idx + 1) + '/' + total + ' ';
        default:      return '';
      }
    }

    // Worst-case prefix length (for estimating max digits)
    function prefixLen(total) {
      return makePrefix(total - 1, total).length;
    }

    // Split text into sentences
    function splitSentences(str) {
      const result = [];
      const re = /[^.!?]*[.!?]+[\s]*/g;
      let match;
      let lastIndex = 0;
      while ((match = re.exec(str)) !== null) {
        result.push(match[0]);
        lastIndex = re.lastIndex;
      }
      // Remaining text without sentence-ending punctuation
      if (lastIndex < str.length) {
        const remainder = str.slice(lastIndex);
        if (remainder.trim()) result.push(remainder);
      }
      return result.length > 0 ? result : [str];
    }

    // Split a chunk at word boundaries to fit within maxLen
    function splitByWords(str, maxLen) {
      const parts = [];
      const words = str.split(/(\s+)/);
      let current = '';
      for (const word of words) {
        if ((current + word).length <= maxLen) {
          current += word;
        } else {
          if (current.trim()) parts.push(current.trim());
          // If a single word exceeds maxLen, we must include it anyway (never break mid-word)
          current = word.trimStart();
        }
      }
      if (current.trim()) parts.push(current.trim());
      return parts;
    }

    // First pass: rough split to estimate thread count, then refine
    function buildThreads(txt) {
      // Start with an estimate for prefix length
      let estimatedTotal = Math.max(1, Math.ceil(txt.length / (charLimit - 10)));
      let pLen = prefixLen(estimatedTotal);
      let maxContent = charLimit - pLen;
      if (maxContent < 10) maxContent = 10; // safety floor

      let chunks;
      if (splitMode === 'sentence') {
        const sentences = splitSentences(txt);
        chunks = [];
        let current = '';
        for (const sentence of sentences) {
          // If the sentence itself is too long, split it by words
          if (sentence.trim().length > maxContent) {
            if (current.trim()) { chunks.push(current.trim()); current = ''; }
            const wordChunks = splitByWords(sentence.trim(), maxContent);
            chunks.push(...wordChunks);
            continue;
          }
          if ((current + sentence).trim().length > maxContent) {
            if (current.trim()) chunks.push(current.trim());
            current = sentence;
          } else {
            current += sentence;
          }
        }
        if (current.trim()) chunks.push(current.trim());
      } else {
        // Word-boundary splitting
        chunks = splitByWords(txt, maxContent);
      }

      // Recalculate with actual count (prefix length might change with digit count)
      const actualTotal = chunks.length;
      if (actualTotal !== estimatedTotal) {
        pLen = prefixLen(actualTotal);
        maxContent = charLimit - pLen;
        if (maxContent < 10) maxContent = 10;

        // Re-split with corrected maxContent
        if (splitMode === 'sentence') {
          const sentences = splitSentences(txt);
          chunks = [];
          let current = '';
          for (const sentence of sentences) {
            if (sentence.trim().length > maxContent) {
              if (current.trim()) { chunks.push(current.trim()); current = ''; }
              const wordChunks = splitByWords(sentence.trim(), maxContent);
              chunks.push(...wordChunks);
              continue;
            }
            if ((current + sentence).trim().length > maxContent) {
              if (current.trim()) chunks.push(current.trim());
              current = sentence;
            } else {
              current += sentence;
            }
          }
          if (current.trim()) chunks.push(current.trim());
        } else {
          chunks = splitByWords(txt, maxContent);
        }
      }

      return chunks.map((c, i) => {
        const prefix = makePrefix(i, chunks.length);
        return { text: prefix + c, content: c, index: i, total: chunks.length, charCount: (prefix + c).length };
      });
    }

    return buildThreads(trimmed);
  }, [text, charLimit, numberStyle, splitMode]);

  const copyAll = () => {
    if (!threads.length) return;
    const joined = threads.map(t => t.text).join('\n---\n');
    navigator.clipboard.writeText(joined);
    setCopiedAll(true);
    setTimeout(() => setCopiedAll(false), 1500);
  };

  const copyOne = (idx) => {
    navigator.clipboard.writeText(threads[idx].text);
    setCopiedIdx(idx);
    setTimeout(() => setCopiedIdx(-1), 1500);
  };

  return (
    <div className="mini-tool">
      <label className="mini-label">Your text</label>
      <textarea
        className="mini-input mini-textarea"
        style={{ minHeight: 180 }}
        placeholder="Paste your long-form text here and it will be split into threads..."
        value={text}
        onChange={(e) => setText(e.target.value)}
      />

      {/* Settings row */}
      <div className="mini-row" style={{ marginTop: 16, gridTemplateColumns: 'repeat(3, 1fr)' }}>
        <div className="mini-field">
          <label className="mini-label">Character limit</label>
          <select className="mini-input" value={limitMode} onChange={(e) => setLimitMode(e.target.value)}>
            <option value="280">280 (X / Twitter)</option>
            <option value="500">500 (Mastodon)</option>
            <option value="custom">Custom</option>
          </select>
          {limitMode === 'custom' && (
            <input
              type="number"
              className="mini-input"
              style={{ marginTop: 6 }}
              min="50"
              max="10000"
              value={customLimit}
              onChange={(e) => setCustomLimit(Math.max(50, Math.min(10000, Number(e.target.value) || 280)))}
            />
          )}
        </div>
        <div className="mini-field">
          <label className="mini-label">Numbering style</label>
          <select className="mini-input" value={numberStyle} onChange={(e) => setNumberStyle(e.target.value)}>
            <option value="1/n">1/n</option>
            <option value="(1/n)">(1/n)</option>
            <option value="emoji">&#x1F9F5; 1/n</option>
            <option value="none">None</option>
          </select>
        </div>
        <div className="mini-field">
          <label className="mini-label">Split on</label>
          <select className="mini-input" value={splitMode} onChange={(e) => setSplitMode(e.target.value)}>
            <option value="sentence">Sentence boundary</option>
            <option value="word">Word boundary</option>
          </select>
        </div>
      </div>

      {/* Summary + actions */}
      {threads.length > 0 && (
        <div className="cmp-actions" style={{ marginTop: 16, justifyContent: 'space-between', alignItems: 'center' }}>
          <span className="cmp-meta" style={{ margin: 0 }}>
            {threads.length} thread{threads.length !== 1 ? 's' : ''} &middot; {text.trim().length.toLocaleString()} characters total
          </span>
          <button className="btn btn-primary" onClick={copyAll}>
            <window.Icon name={copiedAll ? 'check' : 'doc'} size={16} />
            {copiedAll ? ' Copied!' : ' Copy All'}
          </button>
        </div>
      )}

      {/* Thread cards */}
      {threads.length > 0 && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 16 }}>
          {threads.map((t, i) => {
            const overLimit = t.charCount > charLimit;
            const isCopied = copiedIdx === i;
            return (
              <div
                key={i}
                onClick={() => copyOne(i)}
                title="Click to copy this thread"
                style={{
                  padding: '12px 16px',
                  border: '1px solid var(--id-border)',
                  borderRadius: 10,
                  background: 'var(--id-surface)',
                  cursor: 'pointer',
                  transition: 'border-color 0.15s, box-shadow 0.15s',
                  borderColor: isCopied ? 'var(--id-success)' : undefined,
                  boxShadow: isCopied ? '0 0 0 2px var(--id-success-soft)' : undefined,
                }}
              >
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
                  <span style={{
                    fontSize: 11,
                    fontWeight: 700,
                    textTransform: 'uppercase',
                    letterSpacing: '0.06em',
                    color: 'var(--id-text-muted)',
                  }}>
                    Thread {i + 1} of {t.total}
                  </span>
                  <span style={{
                    fontSize: 12,
                    fontWeight: 600,
                    color: overLimit ? 'var(--id-danger)' : 'var(--id-success)',
                  }}>
                    {isCopied ? 'Copied!' : t.charCount + ' / ' + charLimit}
                  </span>
                </div>
                <div style={{
                  whiteSpace: 'pre-wrap',
                  wordBreak: 'break-word',
                  fontSize: 14,
                  lineHeight: 1.55,
                  color: 'var(--id-text)',
                }}>
                  {t.text}
                </div>
                {/* Character count bar */}
                <div style={{
                  marginTop: 8,
                  height: 3,
                  borderRadius: 2,
                  background: 'var(--id-border)',
                  overflow: 'hidden',
                }}>
                  <div style={{
                    height: '100%',
                    width: Math.min(100, (t.charCount / charLimit) * 100) + '%',
                    borderRadius: 2,
                    background: overLimit ? 'var(--id-danger)' : 'var(--id-success)',
                    transition: 'width 0.2s',
                  }} />
                </div>
              </div>
            );
          })}
        </div>
      )}

      {/* Empty state */}
      {text.trim() === '' && (
        <div style={{ textAlign: 'center', padding: '30px 20px', color: 'var(--id-text-muted)' }}>
          <window.Icon name="doc" size={28} />
          <div style={{ marginTop: 8, fontSize: 14 }}>
            Type or paste your text above to split it into threads
          </div>
        </div>
      )}
    </div>
  );
};
