// OrgLens — AI Copilot (floating chat panel)
// Uses window.claude.complete with conversation history + org context.

// ===== Tiny markdown renderer (bold, bullets, numbered, headings, code) =====
function renderMarkdown(text) {
  if (!text) return null;

  const lines = text.split('\n');
  const blocks = []; // array of {type, content}
  let i = 0;
  while (i < lines.length) {
    const line = lines[i];

    // Heading
    const h = line.match(/^(#{1,3})\s+(.*)$/);
    if (h) {
      blocks.push({ type: 'h', level: h[1].length, content: h[2] });
      i++; continue;
    }
    // Bullet list
    if (/^\s*[-*]\s+/.test(line)) {
      const items = [];
      while (i < lines.length && /^\s*[-*]\s+/.test(lines[i])) {
        items.push(lines[i].replace(/^\s*[-*]\s+/, ''));
        i++;
      }
      blocks.push({ type: 'ul', items });
      continue;
    }
    // Numbered list
    if (/^\s*\d+\.\s+/.test(line)) {
      const items = [];
      while (i < lines.length && /^\s*\d+\.\s+/.test(lines[i])) {
        items.push(lines[i].replace(/^\s*\d+\.\s+/, ''));
        i++;
      }
      blocks.push({ type: 'ol', items });
      continue;
    }
    // Blank line — paragraph break
    if (line.trim() === '') { i++; continue; }
    // Paragraph (collect contiguous non-empty lines)
    const para = [];
    while (i < lines.length && lines[i].trim() !== '' && !/^(#{1,3}\s|\s*[-*]\s|\s*\d+\.\s)/.test(lines[i])) {
      para.push(lines[i]);
      i++;
    }
    blocks.push({ type: 'p', content: para.join(' ') });
  }

  // Inline parser: handles **bold**, `code`
  const renderInline = (s) => {
    const out = [];
    let rest = s;
    let key = 0;
    while (rest.length) {
      const bold = rest.match(/^(.*?)\*\*([^*]+)\*\*(.*)$/);
      const code = rest.match(/^(.*?)`([^`]+)`(.*)$/);
      // Choose earliest match
      let chosen = null;
      if (bold && code) {
        chosen = bold[1].length <= code[1].length ? { kind: 'b', m: bold } : { kind: 'c', m: code };
      } else if (bold) chosen = { kind: 'b', m: bold };
      else if (code) chosen = { kind: 'c', m: code };
      if (!chosen) { out.push(rest); break; }
      if (chosen.m[1]) out.push(chosen.m[1]);
      if (chosen.kind === 'b') {
        out.push(<strong key={key++} style={{color: '#080707', fontWeight: 700}}>{chosen.m[2]}</strong>);
      } else {
        out.push(<code key={key++} style={{
          fontFamily: 'SFMono-Regular, Consolas, monospace', fontSize: '0.92em',
          padding: '1px 5px', background: '#f3f2f2', borderRadius: 3, color: '#3e3e3c',
        }}>{chosen.m[2]}</code>);
      }
      rest = chosen.m[3];
    }
    return out;
  };

  return blocks.map((b, idx) => {
    if (b.type === 'h') {
      const sz = b.level === 1 ? 16 : b.level === 2 ? 15 : 14;
      return <div key={idx} style={{
        fontSize: sz, fontWeight: 700, color: '#080707',
        marginTop: idx === 0 ? 0 : 10, marginBottom: 4, lineHeight: 1.3,
      }}>{renderInline(b.content)}</div>;
    }
    if (b.type === 'ul') {
      return <ul key={idx} style={{paddingLeft: 18, marginTop: 4, marginBottom: 8}}>
        {b.items.map((it, i) => (
          <li key={i} style={{marginBottom: 3, lineHeight: 1.5, color: '#3e3e3c'}}>{renderInline(it)}</li>
        ))}
      </ul>;
    }
    if (b.type === 'ol') {
      return <ol key={idx} style={{paddingLeft: 22, marginTop: 4, marginBottom: 8}}>
        {b.items.map((it, i) => (
          <li key={i} style={{marginBottom: 3, lineHeight: 1.5, color: '#3e3e3c'}}>{renderInline(it)}</li>
        ))}
      </ol>;
    }
    return <p key={idx} style={{
      marginBottom: 8, lineHeight: 1.55, color: '#3e3e3c',
    }}>{renderInline(b.content)}</p>;
  });
}

// ===== Build a system context string from current org state =====
function buildOrgContext({ activeOrg, overallScore, categories, findings }) {
  const open = findings.filter(f => f.status === 'open');
  const p1 = open.filter(f => f.priority === 'P1');
  const p2 = open.filter(f => f.priority === 'P2');
  const topP1 = p1.slice(0, 8).map(f =>
    `- [${f.id}] ${f.title} (object: ${f.object}, risk: ${f.riskScore}, effort: ${f.effort} ${f.effortHours}, owner: ${f.owner})`
  ).join('\n');
  const cats = categories.map(c => `- ${c.label}: ${c.score}/100`).join('\n');

  return `You are OrgLens Copilot — an AI assistant embedded in a Salesforce org health product.

Current org context:
- Org: ${activeOrg.name} (${activeOrg.unit})
- Edition: ${activeOrg.edition}, ${activeOrg.users.toLocaleString()} licensed users
- Overall OrgScore: ${Math.round(overallScore)}/100 (${overallScore >= 75 ? 'Healthy' : overallScore >= 55 ? 'Needs attention' : 'At risk'})
- ${open.length} open findings: ${p1.length} P1, ${p2.length} P2, ${open.length - p1.length - p2.length} P3

Category scores:
${cats}

Top P1 findings open right now:
${topP1}

Your job:
- Help admins, devs, and consultants understand and remediate Salesforce technical debt.
- Be direct. Speak in plain language an admin would understand. Avoid jargon.
- When asked to plan a sprint, propose a concrete ordered list of findings with estimated hours and expected score lift.
- When generating fixes, give a numbered step-by-step plan an admin or developer can execute in the next hour.
- When drafting tickets, output a clean title, description, and acceptance criteria.
- Keep responses concise. Use bullets and short paragraphs. Never use emoji.
- Always ground recommendations in the findings listed above. If asked about findings not listed, say you'd need to inspect them.`;
}

const SUGGESTED_PROMPTS = [
  { label: 'What should I fix this sprint?', icon: ICONS.play },
  { label: 'Why is my Agentforce score so low?', icon: ICONS.sparkle },
  { label: 'Summarize the top security risks', icon: ICONS.lock },
  { label: 'Draft an exec summary I can email', icon: ICONS.report },
];

// ===== Floating launcher button =====
function CopilotLauncher({ open, onClick }) {
  return (
    <button onClick={onClick} title="Ask OrgLens Copilot" style={{
      position: 'fixed', bottom: 20, right: 20,
      width: 52, height: 52, borderRadius: '50%',
      background: open ? '#fff' : 'linear-gradient(135deg, #032d60 0%, #0070d2 50%, #1b96ff 100%)',
      color: open ? '#0070d2' : '#fff',
      border: open ? '1px solid #dddbda' : 'none',
      boxShadow: '0 4px 16px rgba(3, 45, 96, 0.32)',
      cursor: 'pointer', zIndex: 6000,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      transition: 'transform 150ms, box-shadow 150ms',
    }} onMouseEnter={e => { e.currentTarget.style.transform = 'scale(1.05)'; }}
       onMouseLeave={e => { e.currentTarget.style.transform = 'scale(1)'; }}>
      <Icon d={open ? ICONS.close : ICONS.sparkle} size={open ? 20 : 22}/>
    </button>
  );
}

// ===== AI Copilot Panel =====
function AICopilot({ open, onClose, activeOrg, overallScore, categories, findings, onNavigate, initialPrompt, onConsumedInitialPrompt }) {
  const [messages, setMessages] = React.useState([]); // [{role, content, loading?}]
  const [input, setInput] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const scrollRef = React.useRef(null);

  // Reset when active org changes
  React.useEffect(() => { setMessages([]); }, [activeOrg.id]);

  // Auto-scroll to bottom on new message
  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, busy]);

  const send = async (text) => {
    const trimmed = (text || '').trim();
    if (!trimmed || busy) return;
    setInput('');
    const userMsg = { role: 'user', content: trimmed };
    const placeholder = { role: 'assistant', content: '', loading: true };
    setMessages(prev => [...prev, userMsg, placeholder]);
    setBusy(true);

    try {
      const system = buildOrgContext({ activeOrg, overallScore, categories, findings });
      // Build messages list for the API. Inject system as a prefix to the first user turn.
      const turns = [...messages, userMsg].filter(m => !m.loading);
      const apiMessages = turns.map((m, idx) => ({
        role: m.role,
        content: (idx === 0 && m.role === 'user')
          ? `${system}\n\n---\nUser:\n${m.content}`
          : m.content,
      }));

      const response = await window.claude.complete({ messages: apiMessages });

      setMessages(prev => {
        const next = [...prev];
        next[next.length - 1] = { role: 'assistant', content: response };
        return next;
      });
    } catch (err) {
      setMessages(prev => {
        const next = [...prev];
        next[next.length - 1] = {
          role: 'assistant',
          content: '_Sorry — I could not reach the AI service. Try again in a moment._',
        };
        return next;
      });
    } finally {
      setBusy(false);
    }
  };

  // Auto-send initial prompt when panel opens with one
  React.useEffect(() => {
    if (open && initialPrompt && !busy) {
      send(initialPrompt);
      onConsumedInitialPrompt && onConsumedInitialPrompt();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open, initialPrompt]);

  if (!open) return null;

  const panelStyles = {
    panel: {
      position: 'fixed', top: 0, right: 0, bottom: 0,
      width: 'min(440px, 100vw)', background: '#fff',
      boxShadow: '-8px 0 32px rgba(0,0,0,0.2)',
      zIndex: 5999, display: 'flex', flexDirection: 'column',
      animation: 'slideInRight 240ms cubic-bezier(0.4,0,0.2,1)',
      borderLeft: '1px solid #dddbda',
    },
    header: {
      padding: '14px 16px', flexShrink: 0,
      background: 'linear-gradient(135deg, #032d60 0%, #0a4a8c 100%)',
      color: '#fff', display: 'flex', alignItems: 'center', gap: 10,
    },
    headerIcon: {
      width: 32, height: 32, borderRadius: '50%',
      background: 'rgba(255,255,255,0.18)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    },
    title: { fontSize: 14, fontWeight: 700, letterSpacing: '-0.005em' },
    sub: { fontSize: 11, color: 'rgba(255,255,255,0.7)', marginTop: 1 },
    closeBtn: {
      marginLeft: 'auto', background: 'rgba(255,255,255,0.15)', border: 'none',
      width: 28, height: 28, borderRadius: 4, cursor: 'pointer',
      color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center',
    },
    body: {
      flex: 1, overflow: 'auto', padding: 16,
      background: '#fafaf9', display: 'flex', flexDirection: 'column', gap: 12,
    },
    inputBar: {
      padding: 12, borderTop: '1px solid #dddbda',
      background: '#fff', flexShrink: 0,
    },
    inputWrap: {
      display: 'flex', alignItems: 'flex-end', gap: 8,
      border: '1px solid #dddbda', borderRadius: 8,
      padding: 8, background: '#fff',
    },
    textarea: {
      flex: 1, border: 'none', outline: 'none', resize: 'none',
      fontSize: 13, fontFamily: 'inherit', color: '#080707',
      maxHeight: 100, minHeight: 22, lineHeight: 1.4,
    },
    sendBtn: (canSend) => ({
      width: 32, height: 32, borderRadius: 4, border: 'none', cursor: canSend ? 'pointer' : 'not-allowed',
      background: canSend ? '#0070d2' : '#dddbda',
      color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center',
      flexShrink: 0, transition: 'background 150ms',
    }),
    footer: {
      fontSize: 10, color: '#706e6b', marginTop: 6, textAlign: 'center',
    },
  };

  return (
    <div style={panelStyles.panel}>
      <div style={panelStyles.header}>
        <div style={panelStyles.headerIcon}>
          <Icon d={ICONS.sparkle} size={16}/>
        </div>
        <div>
          <div style={panelStyles.title}>OrgLens Copilot</div>
          <div style={panelStyles.sub}>Grounded in {activeOrg.name} · {Math.round(overallScore)}/100</div>
        </div>
        <button style={panelStyles.closeBtn} onClick={onClose}>
          <Icon d={ICONS.close} size={14}/>
        </button>
      </div>

      <div style={panelStyles.body} ref={scrollRef}>
        {messages.length === 0 && (
          <CopilotIntro
            activeOrg={activeOrg} overallScore={overallScore}
            onSuggest={(p) => send(p)}
          />
        )}
        {messages.map((m, i) => (
          <ChatBubble key={i} role={m.role} content={m.content} loading={m.loading}/>
        ))}
      </div>

      <div style={panelStyles.inputBar}>
        <div style={panelStyles.inputWrap}>
          <textarea
            style={panelStyles.textarea}
            placeholder="Ask about findings, plan a sprint, draft a summary…"
            value={input}
            onChange={e => setInput(e.target.value)}
            onKeyDown={e => {
              if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                send(input);
              }
            }}
            rows={1}
            disabled={busy}
          />
          <button style={panelStyles.sendBtn(input.trim() && !busy)} onClick={() => send(input)} disabled={!input.trim() || busy}>
            <Icon d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" size={14}/>
          </button>
        </div>
        <div style={panelStyles.footer}>
          Powered by Claude · responses ground in the findings in this org
        </div>
      </div>
    </div>
  );
}

// Intro card with suggested prompts
function CopilotIntro({ activeOrg, overallScore, onSuggest }) {
  return (
    <div style={{display: 'flex', flexDirection: 'column', gap: 12}}>
      <div style={{
        padding: 14, background: '#fff', border: '1px solid #ecebea',
        borderRadius: 8, fontSize: 13, lineHeight: 1.55, color: '#3e3e3c',
      }}>
        <div style={{fontSize: 14, fontWeight: 700, color: '#080707', marginBottom: 4}}>
          Hi — I can help with this org.
        </div>
        I have the latest scan for <b>{activeOrg.name}</b> (OrgScore <b>{Math.round(overallScore)}</b>) in my context.
        Ask me anything, or pick a starter below.
      </div>
      <div style={{
        fontSize: 11, fontWeight: 700, color: '#706e6b',
        textTransform: 'uppercase', letterSpacing: '0.06em', marginTop: 4, marginBottom: 2,
      }}>Try</div>
      {SUGGESTED_PROMPTS.map(p => (
        <button key={p.label} onClick={() => onSuggest(p.label)} style={{
          textAlign: 'left', padding: '10px 12px',
          background: '#fff', border: '1px solid #dddbda',
          borderRadius: 6, cursor: 'pointer', fontFamily: 'inherit',
          fontSize: 13, color: '#080707', fontWeight: 600,
          display: 'flex', alignItems: 'center', gap: 10, transition: 'all 150ms',
        }} onMouseEnter={e => { e.currentTarget.style.borderColor = '#0070d2'; e.currentTarget.style.background = '#eaf4ff'; }}
           onMouseLeave={e => { e.currentTarget.style.borderColor = '#dddbda'; e.currentTarget.style.background = '#fff'; }}>
          <div style={{
            width: 24, height: 24, borderRadius: 4,
            background: 'linear-gradient(135deg, #0070d2 0%, #1b96ff 100%)',
            color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
          }}><Icon d={p.icon} size={12}/></div>
          {p.label}
        </button>
      ))}
    </div>
  );
}

// Chat bubble
function ChatBubble({ role, content, loading }) {
  const isUser = role === 'user';
  const wrapStyle = {
    display: 'flex', gap: 8,
    flexDirection: isUser ? 'row-reverse' : 'row',
    alignItems: 'flex-start',
  };
  const avatarStyle = {
    width: 28, height: 28, borderRadius: '50%', flexShrink: 0,
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    fontSize: 11, fontWeight: 700, color: '#fff',
    background: isUser ? '#7f8de1' : 'linear-gradient(135deg, #032d60 0%, #0070d2 100%)',
  };
  const bubbleStyle = {
    flex: 1, padding: '10px 12px', borderRadius: 8,
    background: isUser ? '#eaf4ff' : '#fff',
    border: isUser ? '1px solid #c9dff4' : '1px solid #ecebea',
    fontSize: 13, color: '#080707', maxWidth: '100%',
    boxShadow: isUser ? 'none' : '0 1px 2px rgba(0,0,0,0.04)',
  };

  return (
    <div style={wrapStyle}>
      <div style={avatarStyle}>
        {isUser ? 'JD' : <Icon d={ICONS.sparkle} size={14}/>}
      </div>
      <div style={bubbleStyle}>
        {loading ? <TypingDots/> : (isUser
          ? <div style={{lineHeight: 1.55, color: '#080707'}}>{content}</div>
          : <div>{renderMarkdown(content)}</div>
        )}
      </div>
    </div>
  );
}

function TypingDots() {
  return (
    <div style={{display: 'flex', gap: 4, alignItems: 'center', padding: '4px 0'}}>
      {[0, 1, 2].map(i => (
        <span key={i} style={{
          width: 6, height: 6, borderRadius: '50%', background: '#706e6b',
          animation: `bounce 1.2s ${i * 0.15}s infinite ease-in-out`,
        }}/>
      ))}
      <style>{`
        @keyframes bounce {
          0%, 80%, 100% { transform: scale(0.6); opacity: 0.5; }
          40% { transform: scale(1); opacity: 1; }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, { AICopilot, CopilotLauncher, renderMarkdown, buildOrgContext });
