// =============================================================
// Triage View — two-pane (list left, detail right)
// =============================================================

function TriageView({ jobs, selectedId, onSelect, onIgnore, onUnignore, onMarkApplied,
                      onCoverLetter, onStatusChange, onSubmitCoverLetter, onAcceptCoverLetter,
                      onCancelCoverLetter, onUpdateCoverLetter, onUpdateNotes, onToggleStar, scoreViz }) {
  const [statusFilter, setStatusFilter] = React.useState('all');
  const [sortBy, setSortBy] = React.useState('combined');

  let visible = jobs;
  if (statusFilter !== 'all') visible = visible.filter(j => j.status === statusFilter);
  visible = [...visible].sort((a, b) => {
    if (sortBy === 'combined') return (b.matchScore + b.cvFitness/2) - (a.matchScore + a.cvFitness/2);
    if (sortBy === 'cv') return b.cvFitness - a.cvFitness;
    if (sortBy === 'match') return b.matchScore - a.matchScore;
    if (sortBy === 'date') return new Date(b.addedAt) - new Date(a.addedAt);
    return 0;
  });

  // Auto-select first job if none selected
  React.useEffect(() => {
    if (!selectedId && visible.length > 0) {
      onSelect(visible[0].id);
    }
  }, [visible, selectedId]);

  const job = visible.find(j => j.id === selectedId) || visible[0] || null;

  return (
    <div className="triage-view">
      {/* Left: list */}
      <div className="triage-list">
        <div className="triage-list-header">
          <select className="triage-select" value={statusFilter} onChange={(e) => setStatusFilter(e.target.value)}>
            <option value="all">All statuses</option>
            <option value="new">New only</option>
            <option value="cover_letter">Cover letter</option>
            <option value="applied">Applied</option>
            <option value="interviewing">Interviewing</option>
            <option value="rejected">Rejected</option>
            <option value="ignored">Ignored</option>
          </select>
          <select className="triage-select" value={sortBy} onChange={(e) => setSortBy(e.target.value)}>
            <option value="combined">Combined score</option>
            <option value="cv">CV fitness</option>
            <option value="match">Match score</option>
            <option value="date">Most recent</option>
          </select>
          <div className="triage-list-count mono">{visible.length}</div>
        </div>
        <div className="triage-list-body">
          {visible.map(j => (
            <TriageRow
              key={j.id}
              job={j}
              selected={selectedId === j.id}
              onClick={() => onSelect(j.id)}
              onToggleStar={onToggleStar}
            />
          ))}
          {visible.length === 0 && (
            <div className="triage-empty">
              <div>No jobs match these filters.</div>
            </div>
          )}
        </div>
      </div>

      {/* Right: detail */}
      <div className="triage-detail">
        {job ? (
          <TriageDetail
            job={job}
            onIgnore={() => onIgnore(job.id)}
            onUnignore={() => onUnignore(job.id)}
            onMarkApplied={() => onMarkApplied(job.id)}
            onCoverLetter={() => onCoverLetter(job.id)}
            onStatusChange={(s) => onStatusChange(job.id, s)}
            onSubmitCoverLetter={() => onSubmitCoverLetter(job.id)}
            onAcceptCoverLetter={() => onAcceptCoverLetter(job.id)}
            onCancelCoverLetter={() => onCancelCoverLetter(job.id)}
            onUpdateCoverLetter={(t) => onUpdateCoverLetter(job.id, t)}
            onUpdateNotes={(t) => onUpdateNotes(job.id, t)}
            onToggleStar={() => onToggleStar && onToggleStar(job.id)}
            scoreViz={scoreViz}
          />
        ) : (
          <div className="triage-detail-empty">
            <div className="mono" style={{ color: 'var(--text-faint)' }}>— select a job —</div>
          </div>
        )}
      </div>
    </div>
  );
}

function statusBadge(status) {
  const map = {
    new: { label: 'New', color: 'var(--status-new)' },
    cover_letter: { label: 'Drafted', color: 'var(--status-cover)' },
    applied: { label: 'Applied', color: 'var(--status-applied)' },
    interviewing: { label: 'Interviewing', color: 'var(--status-interview)' },
    rejected: { label: 'Rejected', color: 'var(--status-rejected)' },
    ignored: { label: 'Ignored', color: 'var(--status-ignored)' },
  };
  return map[status] || map.new;
}

function TriageRow({ job, selected, onClick, onToggleStar }) {
  const sb = statusBadge(job.status);
  return (
    <div className={`triage-row${selected ? ' selected' : ''}${job.status === 'ignored' ? ' dim' : ''}${job.starred ? ' starred' : ''}`}
         onClick={onClick}>
      <div className="triage-row-pip" style={{ background: sb.color }}></div>
      <div className="triage-row-main">
        <div className="triage-row-top">
          <span className="triage-row-company mono">{job.company}</span>
          <span className="triage-row-posted mono">{job.posted}</span>
        </div>
        <div className="triage-row-title">{job.title}</div>
        <div className="triage-row-bottom">
          <span className="triage-row-status" style={{ color: sb.color }}>● {sb.label}</span>
          {job.salary && <span className="mono triage-row-salary">{job.salary.replace(/€\s*/g, '€')}</span>}
          {job.isRemote && <span className="mono" style={{ color: 'var(--status-interview)' }}>· remote</span>}
        </div>
      </div>
      <div className="triage-row-aside">
        <button className={`star-btn${job.starred ? ' on' : ''}`}
          onClick={(e) => { e.stopPropagation(); onToggleStar && onToggleStar(job.id); }}
          title={job.starred ? 'Unstar' : 'Star'}>
          {job.starred ? <Icon.starFilled /> : <Icon.star />}
        </button>
        <div className="triage-row-scores">
          <div className="triage-mini-score">
            <span className="lbl">CV</span>
            <span className="val mono">{Math.round(job.cvFitness)}</span>
          </div>
          <div className="triage-mini-score">
            <span className="lbl">Match</span>
            <span className="val mono" style={{ color: 'var(--accent)' }}>{Math.round(job.matchScore)}</span>
          </div>
        </div>
      </div>
    </div>
  );
}

function TriageDetail({ job, onIgnore, onUnignore, onMarkApplied, onCoverLetter, onStatusChange,
                        onSubmitCoverLetter, onAcceptCoverLetter, onCancelCoverLetter,
                        onUpdateCoverLetter, onUpdateNotes, onToggleStar, scoreViz }) {
  const [descExpanded, setDescExpanded] = React.useState(false);
  const sb = statusBadge(job.status);

  return (
    <div className="triage-detail-inner">
      <div className="triage-detail-header">
        <div className="info">
          <div className="company-line">
            <span style={{ color: sb.color, marginRight: 8 }}>●</span>
            {job.company} · <span style={{ color: sb.color }}>{sb.label}</span>
          </div>
          <h2>
            {job.title}
            <button className={`star-btn star-btn-lg${job.starred ? ' on' : ''}`}
              onClick={onToggleStar}
              title={job.starred ? 'Unstar' : 'Star'}
              style={{ marginLeft: 10, verticalAlign: 'middle' }}>
              {job.starred ? <Icon.starFilled /> : <Icon.star />}
            </button>
          </h2>
          <div className="meta-row">
            {job.location && <span><Icon.location /> {shortLoc(job.location)}</span>}
            {job.isRemote && <span><Icon.pin /> Remote</span>}
            {job.seniority && job.seniority !== 'Not Applicable' && (
              <span><Icon.briefcase /> {job.seniority}</span>
            )}
            {job.employment && <span>{job.employment}</span>}
            {job.salary && <span><Icon.cash /> {job.salary}</span>}
            {job.posted && <span className="mono" style={{ fontSize: 11 }}>{job.posted}</span>}
          </div>
        </div>
        <a className="btn" href={job.jobLink || '#'} target="_blank" rel="noopener noreferrer">
          <span className="linkedin-icon">in</span> Open <Icon.external />
        </a>
      </div>

      <div className="triage-detail-body">
        <div className="detail-section">
          <h3>Scores</h3>
          <div className="score-board score-board-triage">
            <div className="score-card">
              <div className="sc-label">CV fitness</div>
              <div className="sc-value mono">{Math.round(job.cvFitness)}<span className="of"> / 100</span></div>
              <div className="sc-bar">
                <div className="fill" style={{ width: `${job.cvFitness}%`, background: 'var(--status-applied)' }}></div>
              </div>
            </div>
            <div className="score-card">
              <div className="sc-label">Interest match</div>
              <div className="sc-value mono">{Math.round(job.matchScore)}<span className="of"> / 100</span></div>
              <div className="sc-bar">
                <div className="fill" style={{ width: `${job.matchScore}%`, background: 'var(--accent)' }}></div>
              </div>
            </div>
            <div className="score-card score-card-viz">
              <div className="sc-label">Combined</div>
              <ScoreViz cv={job.cvFitness} match={job.matchScore} variant="quadrant" />
            </div>
          </div>
        </div>

        {job.oneLineReason && (
          <div className="detail-section">
            <h3>Why this matches</h3>
            <div className="reasoning-block" style={{ borderLeft: '3px solid var(--accent)', background: 'color-mix(in oklab, var(--accent) 5%, var(--bg-elev))' }}>
              {job.oneLineReason}
            </div>
          </div>
        )}

        {job.cvReasoning && (
          <div className="detail-section">
            <h3>CV fitness reasoning</h3>
            <div className="reasoning-block">{job.cvReasoning.trim()}</div>
          </div>
        )}

        {job.matchReasoning && (
          <div className="detail-section">
            <h3>Match reasoning</h3>
            <div className="reasoning-block">{job.matchReasoning.trim()}</div>
          </div>
        )}

        {/* Cover letter inline flow */}
        {job._coverFlow && (
          <div className="detail-section">
            <h3>Cover letter</h3>
            <CoverLetterInline
              job={job}
              state={job._coverFlow}
              onSubmit={onSubmitCoverLetter}
              onAccept={onAcceptCoverLetter}
              onCancel={onCancelCoverLetter}
              onUpdateText={onUpdateCoverLetter}
              onUpdateNotes={onUpdateNotes}
            />
          </div>
        )}

        {!job._coverFlow && job.coverLetter && (
          <div className="detail-section">
            <h3>Saved cover letter</h3>
            <div className="reasoning-block" style={{ fontFamily: 'inherit', fontSize: 12.5 }}>{job.coverLetter}</div>
          </div>
        )}

        {job.description && (
          <div className="detail-section">
            <h3>Full description</h3>
            <div className={`desc-block${descExpanded ? '' : ' collapsed'}`}>
              {job.description}
            </div>
            <button className="desc-toggle" onClick={() => setDescExpanded(v => !v)}>
              {descExpanded ? 'Show less ↑' : 'Show full description ↓'}
            </button>
          </div>
        )}
      </div>

      <div className="triage-detail-footer">
        {job.status === 'new' && (
          <>
            <button className="btn" onClick={onIgnore}><Icon.archive /> Ignore</button>
            <div style={{ flex: 1 }}></div>
            <button className="btn accent" onClick={onCoverLetter}><Icon.letter /> Cover letter</button>
          </>
        )}
        {job.status === 'cover_letter' && (
          <>
            <button className="btn" onClick={onIgnore}>Ignore</button>
            <div style={{ flex: 1 }}></div>
            <button className="btn primary" onClick={onMarkApplied}><Icon.check /> Mark applied</button>
          </>
        )}
        {job.status === 'applied' && (
          <>
            <button className="btn" onClick={() => onStatusChange('rejected')}>Move to rejected</button>
            <div style={{ flex: 1 }}></div>
            <button className="btn primary" onClick={() => onStatusChange('interviewing')}>Move to interviewing</button>
          </>
        )}
        {job.status === 'interviewing' && (
          <>
            <button className="btn" onClick={() => onStatusChange('rejected')}>Got rejected</button>
            <div style={{ flex: 1 }}></div>
            <button className="btn" onClick={() => onStatusChange('applied')}>Back to applied</button>
          </>
        )}
        {(job.status === 'ignored' || job.status === 'rejected') && (
          <button className="btn" onClick={onUnignore}>Restore to inbox</button>
        )}
      </div>
    </div>
  );
}

// =============================================================
// Scatter View
// =============================================================

const STATUS_COLORS = {
  new: 'var(--status-new)',
  cover_letter: 'var(--status-cover)',
  applied: 'var(--status-applied)',
  interviewing: 'var(--status-interview)',
  rejected: 'var(--status-rejected)',
  ignored: 'var(--status-ignored)',
};

function ScatterView({ jobs, onSelect, scoreViz }) {
  const [hover, setHover] = React.useState(null);
  const [showLabels, setShowLabels] = React.useState(false);
  const [statusFilter, setStatusFilter] = React.useState('active'); // active, all, new only

  let visible = jobs;
  if (statusFilter === 'active') visible = visible.filter(j => j.status !== 'ignored' && j.status !== 'rejected');
  else if (statusFilter === 'new') visible = visible.filter(j => j.status === 'new');

  // Group jobs by exact coords to detect overlaps
  const grouped = {};
  for (const j of visible) {
    const k = `${j.cvFitness}-${j.matchScore}`;
    if (!grouped[k]) grouped[k] = [];
    grouped[k].push(j);
  }

  return (
    <div className="scatter-view">
      <div className="scatter-toolbar">
        <div className="seg">
          {[
            ['active', 'Active'],
            ['new', 'New only'],
            ['all', 'All']
          ].map(([k, l]) => (
            <button key={k} className={`seg-btn${statusFilter === k ? ' active' : ''}`}
              onClick={() => setStatusFilter(k)}>{l}</button>
          ))}
        </div>
        <label className="scatter-toggle">
          <input type="checkbox" checked={showLabels} onChange={(e) => setShowLabels(e.target.checked)} />
          <span>Show labels</span>
        </label>
        <div style={{ flex: 1 }}></div>
        <div className="scatter-legend">
          {[
            ['new', 'New'],
            ['cover_letter', 'Drafted'],
            ['applied', 'Applied'],
            ['interviewing', 'Interviewing'],
            ['rejected', 'Rejected'],
            ['ignored', 'Ignored'],
          ].map(([k, l]) => (
            <span key={k} className="legend-item">
              <span className="legend-dot" style={{ background: STATUS_COLORS[k] }}></span>
              {l}
            </span>
          ))}
        </div>
      </div>

      <div className="scatter-plot-wrap">
        <div className="scatter-plot">
          {/* axes */}
          <div className="ax ax-y"></div>
          <div className="ax ax-x"></div>
          {/* quadrant lines */}
          <div className="quad-line quad-h"></div>
          <div className="quad-line quad-v"></div>
          {/* grid */}
          {[20, 40, 60, 80].map(v => (
            <React.Fragment key={v}>
              <div className="grid-line grid-h" style={{ bottom: `${v}%` }}></div>
              <div className="grid-line grid-v" style={{ left: `${v}%` }}></div>
            </React.Fragment>
          ))}

          {/* quadrant labels */}
          <div className="quad-label" style={{ top: 10, right: 10 }}>Ideal — strong CV fit & strong match</div>
          <div className="quad-label muted" style={{ top: 10, left: 10 }}>Aspirational — match high, CV gaps</div>
          <div className="quad-label muted" style={{ bottom: 10, right: 10 }}>Safe — CV fits, low interest</div>
          <div className="quad-label muted" style={{ bottom: 10, left: 10 }}>Pass — weak on both</div>

          {/* axis labels */}
          <div className="axis-label x-label">CV fitness →</div>
          <div className="axis-label y-label">Match score →</div>

          {/* ticks */}
          <div className="tick" style={{ left: '0%', bottom: -4, transform: 'translateX(-50%)' }}>0</div>
          <div className="tick" style={{ left: '50%', bottom: -4, transform: 'translateX(-50%)' }}>50</div>
          <div className="tick" style={{ left: '100%', bottom: -4, transform: 'translateX(-50%)' }}>100</div>
          <div className="tick tick-y" style={{ left: -8, bottom: '0%', transform: 'translateY(50%)' }}>0</div>
          <div className="tick tick-y" style={{ left: -8, bottom: '50%', transform: 'translateY(50%)' }}>50</div>
          <div className="tick tick-y" style={{ left: -8, bottom: '100%', transform: 'translateY(50%)' }}>100</div>

          {/* dots */}
          {Object.values(grouped).map((group) => {
            const first = group[0];
            const cv = first.cvFitness;
            const ms = first.matchScore;
            const stack = group.length;
            return (
              <div
                key={`${cv}-${ms}`}
                className="scatter-dot-group"
                style={{ left: `${cv}%`, bottom: `${ms}%` }}
                onMouseEnter={() => setHover({ x: cv, y: ms, jobs: group })}
                onMouseLeave={() => setHover(h => h && h.x === cv && h.y === ms ? null : h)}
              >
                {group.map((j, i) => (
                  <div
                    key={j.id}
                    className={`scatter-dot scatter-dot-${j.status}${j.starred ? ' starred' : ''}`}
                    style={{
                      width: stack > 1 ? 11 : 13,
                      height: stack > 1 ? 11 : 13,
                      transform: stack > 1 ? `translate(${(i % 3 - 1) * 6}px, ${Math.floor(i / 3) * -6 - 6}px)` : 'translate(-50%, 50%)',
                      zIndex: stack - i,
                    }}
                    onClick={() => onSelect(j.id)}
                    title={`${j.company} — ${j.title}${j.starred ? ' ★' : ''}`}
                  ></div>
                ))}
                {showLabels && stack === 1 && (
                  <div className="scatter-label">{shortCompany(first.company)}</div>
                )}
                {stack > 1 && (
                  <div className="scatter-stack-count mono">{stack}</div>
                )}
              </div>
            );
          })}

          {/* hover popover */}
          {hover && (
            <div className="scatter-popover"
              style={{
                left: `${hover.x}%`,
                bottom: `${hover.y}%`,
                transform: `translate(${hover.x > 60 ? '-110%' : '20%'}, ${hover.y > 50 ? '0' : '-100%'})`
              }}>
              <div className="sp-coord mono">CV {hover.x} · Match {hover.y}</div>
              {hover.jobs.map(j => (
                <div key={j.id} className="sp-job" onClick={() => onSelect(j.id)}>
                  <div className="sp-company mono">{j.company}</div>
                  <div className="sp-title">{j.title}</div>
                  <div className="sp-status mono" style={{ color: STATUS_COLORS[j.status] }}>
                    {statusBadge(j.status).label}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>

      <div className="scatter-stats">
        <div className="stat">
          <div className="stat-label">Showing</div>
          <div className="stat-value mono">{visible.length} / {jobs.length}</div>
        </div>
        <div className="stat">
          <div className="stat-label">Avg CV fit</div>
          <div className="stat-value mono">{visible.length ? Math.round(avg(visible.map(j => j.cvFitness))) : '—'}</div>
        </div>
        <div className="stat">
          <div className="stat-label">Avg match</div>
          <div className="stat-value mono">{visible.length ? Math.round(avg(visible.map(j => j.matchScore))) : '—'}</div>
        </div>
        <div className="stat">
          <div className="stat-label">In "Ideal"</div>
          <div className="stat-value mono">{visible.filter(j => j.cvFitness >= 50 && j.matchScore >= 50).length}</div>
        </div>
      </div>
    </div>
  );
}

function avg(arr) { return arr.reduce((a, b) => a + b, 0) / arr.length; }

function shortCompany(c) {
  if (!c) return '';
  return c.length > 16 ? c.substring(0, 14) + '…' : c;
}

Object.assign(window, { TriageView, ScatterView, statusBadge });
