import React, { useState, useEffect, useCallback } from 'react';
import { Search, RefreshCw, Plus, ExternalLink, Loader, AlertCircle, CheckCircle, Trash2, Edit3, X, Wifi, WifiOff, BarChart2 } from 'lucide-react';
import { useAuth } from '../../contexts/AuthContext';

const API_BASE = process.env.REACT_APP_API_BASE || 'http://localhost:3001/api';

// ---------------------------------------------------------------------------
// Styles — matches DESIGN_SYSTEM.md tactical intelligence aesthetic
// ---------------------------------------------------------------------------
const STYLES = {
  page: {
    minHeight: '60vh',
  },
  card: {
    background: 'linear-gradient(135deg, rgba(30, 41, 59, 0.95), rgba(15, 23, 42, 0.98))',
    border: '1px solid rgba(14, 165, 233, 0.15)',
    borderRadius: '12px',
    padding: '1.5rem',
    marginBottom: '1rem',
  },
  header: {
    fontFamily: 'monospace',
    fontSize: '0.7rem',
    fontWeight: 700,
    color: '#0EA5E9',
    textTransform: 'uppercase',
    letterSpacing: '0.15em',
    marginBottom: '1rem',
  },
  statCard: {
    background: 'linear-gradient(135deg, rgba(30, 41, 59, 0.9), rgba(15, 23, 42, 0.95))',
    border: '1px solid rgba(14, 165, 233, 0.15)',
    borderRadius: '10px',
    padding: '1rem 1.25rem',
    position: 'relative',
    overflow: 'hidden',
  },
  btn: {
    padding: '0.5rem 1rem',
    borderRadius: '8px',
    border: '1px solid rgba(14, 165, 233, 0.3)',
    background: 'rgba(14, 165, 233, 0.1)',
    color: '#7DD3FC',
    cursor: 'pointer',
    fontSize: '0.8rem',
    fontWeight: 600,
    display: 'inline-flex',
    alignItems: 'center',
    gap: '0.4rem',
    transition: 'all 0.2s',
  },
  btnDanger: {
    border: '1px solid rgba(239, 68, 68, 0.3)',
    background: 'rgba(239, 68, 68, 0.1)',
    color: '#FCA5A5',
  },
  btnSuccess: {
    border: '1px solid rgba(16, 185, 129, 0.3)',
    background: 'rgba(16, 185, 129, 0.1)',
    color: '#6EE7B7',
  },
  input: {
    background: 'rgba(15, 23, 42, 0.8)',
    border: '1px solid rgba(14, 165, 233, 0.2)',
    borderRadius: '8px',
    padding: '0.5rem 0.75rem',
    color: '#F8FAFC',
    fontSize: '0.85rem',
    width: '100%',
    outline: 'none',
  },
  table: {
    width: '100%',
    borderCollapse: 'separate',
    borderSpacing: '0 4px',
  },
  th: {
    textAlign: 'left',
    padding: '0.5rem 0.75rem',
    fontSize: '0.7rem',
    fontWeight: 700,
    color: '#94A3B8',
    textTransform: 'uppercase',
    letterSpacing: '0.1em',
    borderBottom: '1px solid rgba(14, 165, 233, 0.1)',
  },
  td: {
    padding: '0.6rem 0.75rem',
    fontSize: '0.85rem',
    color: '#E2E8F0',
    borderBottom: '1px solid rgba(51, 65, 85, 0.3)',
  },
  badge: (color) => ({
    display: 'inline-flex',
    alignItems: 'center',
    gap: '0.3rem',
    padding: '0.2rem 0.6rem',
    borderRadius: '9999px',
    fontSize: '0.7rem',
    fontWeight: 600,
    border: `1px solid ${color}`,
    background: `${color}26`,
    color: color,
  }),
  modal: {
    position: 'fixed',
    inset: 0,
    zIndex: 100,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
  },
  modalBackdrop: {
    position: 'fixed',
    inset: 0,
    background: 'rgba(0,0,0,0.7)',
    backdropFilter: 'blur(4px)',
  },
  modalContent: {
    position: 'relative',
    background: 'linear-gradient(135deg, #1E293B, #0F172A)',
    border: '1px solid rgba(14, 165, 233, 0.25)',
    borderRadius: '16px',
    padding: '2rem',
    width: '90%',
    maxWidth: '520px',
    maxHeight: '85vh',
    overflowY: 'auto',
    zIndex: 101,
  },
};

const STATUS_COLORS = {
  'Open': '#F59E0B',
  'In Progress': '#0EA5E9',
  'Closed': '#10B981',
  'Done': '#10B981',
  'Resolved': '#10B981',
  'Approval/Handoff': '#8B5CF6',
  'Prioritizing': '#0EA5E9',
  'In Review': '#0EA5E9',
  'In Development': '#0EA5E9',
  'In Testing': '#0EA5E9',
};

// Determine if a status represents a "closed/done" state
function isClosedStatus(status) {
  if (!status) return false;
  const lower = status.toLowerCase();
  return ['closed', 'done', 'resolved', 'complete', 'completed', 'cancelled', 'canceled', "won't do", 'declined'].some(s => lower.includes(s));
}

function getStatusColor(status) {
  if (STATUS_COLORS[status]) return STATUS_COLORS[status];
  if (isClosedStatus(status)) return '#10B981';
  return '#F59E0B';
}

const SOURCE_CONTEXT_CONFIG = {
  cve: { label: 'CVE', color: '#0EA5E9' },
  archer: { label: 'Archer', color: '#8B5CF6' },
  ivanti_queue: { label: 'Ivanti', color: '#F59E0B' },
  email: { label: 'Email', color: '#10B981' },
  manual: { label: 'Manual', color: '#94A3B8' },
};

const getSourceBadge = (sourceContext) => {
  if (!sourceContext) return SOURCE_CONTEXT_CONFIG.cve; // legacy tickets default to CVE
  return SOURCE_CONTEXT_CONFIG[sourceContext] || SOURCE_CONTEXT_CONFIG.cve;
};


// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------
export default function JiraPage() {
  const { canWrite, isAdmin } = useAuth();

  // Data state
  const [tickets, setTickets] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  // Filters
  const [filterStatus, setFilterStatus] = useState('');
  const [filterSource, setFilterSource] = useState('');
  const [filterSearch, setFilterSearch] = useState('');

  // Connection test
  const [connectionStatus, setConnectionStatus] = useState(null); // null | 'testing' | { connected, user?, error? }

  // Rate limit
  const [rateLimit, setRateLimit] = useState(null);

  // Sync
  const [syncing, setSyncing] = useState(false);
  const [syncResult, setSyncResult] = useState(null);

  // Lookup modal
  const [showLookup, setShowLookup] = useState(false);
  const [lookupKey, setLookupKey] = useState('');
  const [lookupResult, setLookupResult] = useState(null);
  const [lookupLoading, setLookupLoading] = useState(false);
  const [lookupError, setLookupError] = useState(null);
  const [linkingSaving, setLinkingSaving] = useState(false);
  const [linkingError, setLinkingError] = useState(null);
  const [linkingSuccess, setLinkingSuccess] = useState(null);

  // Add/Edit modal
  const [showForm, setShowForm] = useState(false);
  const [editingId, setEditingId] = useState(null);
  const [form, setForm] = useState({ cve_id: '', vendor: '', ticket_key: '', url: '', summary: '', status: 'Open' });
  const [formError, setFormError] = useState(null);
  const [formSaving, setFormSaving] = useState(false);

  // Create-in-Jira modal
  const [showCreateJira, setShowCreateJira] = useState(false);
  const [createJiraForm, setCreateJiraForm] = useState({ cve_id: '', vendor: '', summary: '', description: '', project_key: '', issue_type: '', source_context: '' });
  const [createJiraError, setCreateJiraError] = useState(null);
  const [createJiraSaving, setCreateJiraSaving] = useState(false);
  const [createJiraLocked, setCreateJiraLocked] = useState({}); // { source_context: true } when set externally
  const [summaryError, setSummaryError] = useState(null);

  // ---------------------------------------------------------------------------
  // Data fetching
  // ---------------------------------------------------------------------------
  const fetchTickets = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const res = await fetch(`${API_BASE}/jira-tickets`, { credentials: 'include' });
      if (!res.ok) throw new Error('Failed to fetch tickets');
      const data = await res.json();
      setTickets(data);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => { fetchTickets(); }, [fetchTickets]);

  // ---------------------------------------------------------------------------
  // Connection test
  // ---------------------------------------------------------------------------
  const testConnection = async () => {
    setConnectionStatus('testing');
    try {
      const res = await fetch(`${API_BASE}/jira-tickets/connection-test`, { credentials: 'include' });
      const data = await res.json();
      setConnectionStatus(data);
    } catch (err) {
      setConnectionStatus({ connected: false, error: err.message });
    }
  };

  // ---------------------------------------------------------------------------
  // Rate limit
  // ---------------------------------------------------------------------------
  const fetchRateLimit = async () => {
    try {
      const res = await fetch(`${API_BASE}/jira-tickets/rate-limit`, { credentials: 'include' });
      if (res.ok) setRateLimit(await res.json());
    } catch (_) { /* ignore */ }
  };

  useEffect(() => {
    if (isAdmin()) fetchRateLimit();
  }, [isAdmin]);

  // ---------------------------------------------------------------------------
  // Sync all
  // ---------------------------------------------------------------------------
  const syncAll = async () => {
    setSyncing(true);
    setSyncResult(null);
    try {
      const res = await fetch(`${API_BASE}/jira-tickets/sync-all`, { method: 'POST', credentials: 'include' });
      const data = await res.json();
      setSyncResult(data);
      fetchTickets();
      fetchRateLimit();
    } catch (err) {
      setSyncResult({ errors: [err.message] });
    } finally {
      setSyncing(false);
    }
  };

  // ---------------------------------------------------------------------------
  // Lookup
  // ---------------------------------------------------------------------------
  const doLookup = async () => {
    if (!lookupKey.trim()) return;
    setLookupLoading(true);
    setLookupError(null);
    setLookupResult(null);
    try {
      const res = await fetch(`${API_BASE}/jira-tickets/lookup/${encodeURIComponent(lookupKey.trim())}`, { credentials: 'include' });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || `HTTP ${res.status}`);
      }
      setLookupResult(await res.json());
    } catch (err) {
      setLookupError(err.message);
    } finally {
      setLookupLoading(false);
    }
  };

  // ---------------------------------------------------------------------------
  // Link existing Jira ticket — save to local DB without recreating in Jira
  // ---------------------------------------------------------------------------
  const linkExistingTicket = async (issue) => {
    setLinkingError(null);
    setLinkingSuccess(null);
    setLinkingSaving(true);
    try {
      const jiraUrl = `https://jira.charter.com/browse/${issue.key}`;
      const res = await fetch(`${API_BASE}/jira-tickets`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({
          ticket_key: issue.key,
          url: jiraUrl,
          summary: issue.summary || '',
          status: issue.status || 'Open',
        }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`);
      setLinkingSuccess(`${issue.key} saved to dashboard.`);
      fetchTickets();
    } catch (err) {
      setLinkingError(err.message);
    } finally {
      setLinkingSaving(false);
    }
  };


  // ---------------------------------------------------------------------------
  // CRUD — save (create or update)
  // ---------------------------------------------------------------------------
  const saveTicket = async () => {
    setFormError(null);
    setFormSaving(true);
    try {
      const method = editingId ? 'PUT' : 'POST';
      const url = editingId ? `${API_BASE}/jira-tickets/${editingId}` : `${API_BASE}/jira-tickets`;
      const res = await fetch(url, {
        method,
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify(form),
      });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || `HTTP ${res.status}`);
      }
      setShowForm(false);
      setEditingId(null);
      fetchTickets();
    } catch (err) {
      setFormError(err.message);
    } finally {
      setFormSaving(false);
    }
  };

  const deleteTicket = async (id) => {
    if (!window.confirm('Delete this Jira ticket record?')) return;
    try {
      const res = await fetch(`${API_BASE}/jira-tickets/${id}`, { method: 'DELETE', credentials: 'include' });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || `HTTP ${res.status}`);
      }
      fetchTickets();
    } catch (err) {
      alert(err.message);
    }
  };

  const syncOne = async (id) => {
    try {
      const res = await fetch(`${API_BASE}/jira-tickets/${id}/sync`, { method: 'POST', credentials: 'include' });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || `HTTP ${res.status}`);
      }
      fetchTickets();
      fetchRateLimit();
    } catch (err) {
      alert(err.message);
    }
  };

  // ---------------------------------------------------------------------------
  // Create in Jira
  // ---------------------------------------------------------------------------
  const createInJira = async () => {
    // Inline summary validation
    setSummaryError(null);
    const trimmedSummary = (createJiraForm.summary || '').trim();
    if (!trimmedSummary) {
      setSummaryError('Summary is required.');
      return;
    }
    if (trimmedSummary.length > 255) {
      setSummaryError('Summary must be 255 characters or fewer.');
      return;
    }

    setCreateJiraError(null);
    setCreateJiraSaving(true);
    try {
      // Build payload — only include source_context when selected
      const payload = { ...createJiraForm };
      if (!payload.source_context) {
        delete payload.source_context;
      }

      const res = await fetch(`${API_BASE}/jira-tickets/create-in-jira`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify(payload),
      });
      const data = await res.json();
      if (!res.ok && res.status !== 207) {
        throw new Error(data.error || `HTTP ${res.status}`);
      }
      setShowCreateJira(false);
      setCreateJiraForm({ cve_id: '', vendor: '', summary: '', description: '', project_key: '', issue_type: '', source_context: '' });
      setCreateJiraLocked({});
      setSummaryError(null);
      fetchTickets();
      fetchRateLimit();
    } catch (err) {
      setCreateJiraError(err.message);
    } finally {
      setCreateJiraSaving(false);
    }
  };

  // ---------------------------------------------------------------------------
  // Open Create-in-Jira modal with optional pre-populated values and locks
  // Called externally from Ivanti queue or Archer detail views
  // ---------------------------------------------------------------------------
  // eslint-disable-next-line no-unused-vars
  const openCreateJiraModal = (prePopulate = {}, locked = {}) => {
    setCreateJiraForm({
      cve_id: prePopulate.cve_id || '',
      vendor: prePopulate.vendor || '',
      summary: prePopulate.summary || '',
      description: prePopulate.description || '',
      project_key: prePopulate.project_key || '',
      issue_type: prePopulate.issue_type || '',
      source_context: prePopulate.source_context || '',
    });
    setCreateJiraLocked(locked);
    setCreateJiraError(null);
    setSummaryError(null);
    setShowCreateJira(true);
  };

  // ---------------------------------------------------------------------------
  // Filtering
  // ---------------------------------------------------------------------------
  const filtered = tickets.filter(t => {
    if (filterStatus && t.status !== filterStatus) return false;
    if (filterSource) {
      const ticketSource = t.source_context || 'cve';
      if (ticketSource !== filterSource) return false;
    }
    if (filterSearch) {
      const q = filterSearch.toLowerCase();
      return (t.ticket_key || '').toLowerCase().includes(q)
        || (t.cve_id || '').toLowerCase().includes(q)
        || (t.vendor || '').toLowerCase().includes(q)
        || (t.summary || '').toLowerCase().includes(q)
        || (t.source_context || '').toLowerCase().includes(q);
    }
    return true;
  });

  const counts = {
    total: tickets.length,
    open: tickets.filter(t => !isClosedStatus(t.status)).length,
    closed: tickets.filter(t => isClosedStatus(t.status)).length,
  };


  // ---------------------------------------------------------------------------
  // Render
  // ---------------------------------------------------------------------------
  return (
    <div style={STYLES.page}>
      {/* Page header */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1.5rem', flexWrap: 'wrap', gap: '0.75rem' }}>
        <div>
          <h2 style={{ margin: 0, fontSize: '1.25rem', color: '#F8FAFC', fontWeight: 700 }}>Jira Tickets</h2>
          <p style={{ margin: '0.25rem 0 0', fontSize: '0.8rem', color: '#94A3B8' }}>
            Track and sync Jira issues linked to CVE findings
          </p>
        </div>
        <div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
          {isAdmin() && (
            <button style={STYLES.btn} onClick={testConnection} disabled={connectionStatus === 'testing'}>
              {connectionStatus === 'testing' ? <Loader size={14} className="animate-spin" /> : connectionStatus?.connected ? <Wifi size={14} /> : <WifiOff size={14} />}
              Test Connection
            </button>
          )}
          <button style={STYLES.btn} onClick={() => setShowLookup(true)}>
            <Search size={14} /> Lookup Issue
          </button>
          {canWrite() && (
            <>
              <button style={STYLES.btn} onClick={() => { setShowCreateJira(true); setCreateJiraError(null); setSummaryError(null); setCreateJiraLocked({}); setCreateJiraForm({ cve_id: '', vendor: '', summary: '', description: '', project_key: '', issue_type: '', source_context: '' }); }}>
                <Plus size={14} /> Create in Jira
              </button>
              <button style={STYLES.btn} onClick={() => { setEditingId(null); setForm({ cve_id: '', vendor: '', ticket_key: '', url: '', summary: '', status: 'Open' }); setFormError(null); setShowForm(true); }}>
                <Plus size={14} /> Add Manual
              </button>
            </>
          )}
          {isAdmin() && (
            <button style={{ ...STYLES.btn, ...STYLES.btnSuccess }} onClick={syncAll} disabled={syncing}>
              {syncing ? <Loader size={14} className="animate-spin" /> : <RefreshCw size={14} />}
              Sync All
            </button>
          )}
        </div>
      </div>

      {/* Connection status banner */}
      {connectionStatus && connectionStatus !== 'testing' && (
        <div style={{ ...STYLES.card, padding: '0.75rem 1rem', marginBottom: '1rem', borderColor: connectionStatus.connected ? 'rgba(16, 185, 129, 0.3)' : 'rgba(239, 68, 68, 0.3)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', fontSize: '0.85rem' }}>
            {connectionStatus.connected
              ? <><CheckCircle size={16} color="#10B981" /><span style={{ color: '#6EE7B7' }}>Connected as {connectionStatus.user?.displayName || connectionStatus.user?.name}</span></>
              : <><AlertCircle size={16} color="#EF4444" /><span style={{ color: '#FCA5A5' }}>Connection failed: {connectionStatus.error || `HTTP ${connectionStatus.status}`}</span></>
            }
          </div>
        </div>
      )}

      {/* Sync result banner */}
      {syncResult && (
        <div style={{ ...STYLES.card, padding: '0.75rem 1rem', marginBottom: '1rem', borderColor: 'rgba(14, 165, 233, 0.3)' }}>
          <div style={{ fontSize: '0.85rem', color: '#E2E8F0' }}>
            Sync complete: {syncResult.synced} updated, {syncResult.unchanged || 0} unchanged, {syncResult.failed} failed, {syncResult.skipped} skipped
            {syncResult.errors?.length > 0 && (
              <div style={{ marginTop: '0.25rem', fontSize: '0.75rem', color: '#FCA5A5' }}>
                {syncResult.errors.slice(0, 3).map((e, i) => <div key={i}>{e}</div>)}
              </div>
            )}
          </div>
        </div>
      )}

      {/* Stats row */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))', gap: '0.75rem', marginBottom: '1.5rem' }}>
        {[
          { label: 'Total', value: counts.total, color: '#0EA5E9' },
          { label: 'Open', value: counts.open, color: '#F59E0B' },
          { label: 'Closed', value: counts.closed, color: '#10B981' },
        ].map(s => (
          <div key={s.label} style={STYLES.statCard}>
            <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: '2px', background: s.color }} />
            <div style={{ fontSize: '0.65rem', color: '#94A3B8', textTransform: 'uppercase', letterSpacing: '0.1em', fontWeight: 700 }}>{s.label}</div>
            <div style={{ fontSize: '1.5rem', fontWeight: 700, color: s.color, fontFamily: 'monospace' }}>{s.value}</div>
          </div>
        ))}
        {rateLimit && (
          <div style={STYLES.statCard}>
            <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: '2px', background: rateLimit.daily.remaining < 100 ? '#EF4444' : '#8B5CF6' }} />
            <div style={{ fontSize: '0.65rem', color: '#94A3B8', textTransform: 'uppercase', letterSpacing: '0.1em', fontWeight: 700 }}>API Budget</div>
            <div style={{ fontSize: '1rem', fontWeight: 700, color: '#C4B5FD', fontFamily: 'monospace' }}>
              {rateLimit.daily.remaining}/{rateLimit.daily.limit}
            </div>
            <div style={{ fontSize: '0.65rem', color: '#94A3B8' }}>burst: {rateLimit.burst.remaining}/{rateLimit.burst.limit}</div>
          </div>
        )}
      </div>

      {/* Filters */}
      <div style={{ ...STYLES.card, display: 'flex', gap: '0.75rem', alignItems: 'center', flexWrap: 'wrap', padding: '1rem 1.25rem' }}>
        <div style={{ flex: '1 1 250px' }}>
          <input
            style={STYLES.input}
            placeholder="Search tickets, CVEs, vendors..."
            value={filterSearch}
            onChange={e => setFilterSearch(e.target.value)}
          />
        </div>
        <select
          style={{ ...STYLES.input, width: 'auto', minWidth: '140px', cursor: 'pointer' }}
          value={filterStatus}
          onChange={e => setFilterStatus(e.target.value)}
        >
          <option value="">All Statuses</option>
          {[...new Set(tickets.map(t => t.status).filter(Boolean))].sort().map(s => (
            <option key={s} value={s}>{s}</option>
          ))}
        </select>
        <select
          style={{ ...STYLES.input, width: 'auto', minWidth: '140px', cursor: 'pointer' }}
          value={filterSource}
          onChange={e => setFilterSource(e.target.value)}
        >
          <option value="">All Sources</option>
          <option value="cve">CVE</option>
          <option value="archer">Archer</option>
          <option value="ivanti_queue">Ivanti</option>
          <option value="email">Email</option>
          <option value="manual">Manual</option>
        </select>
      </div>

      {/* Table */}
      {loading ? (
        <div style={{ textAlign: 'center', padding: '3rem', color: '#94A3B8' }}>
          <Loader size={24} className="animate-spin" style={{ margin: '0 auto 0.5rem' }} />
          Loading tickets...
        </div>
      ) : error ? (
        <div style={{ textAlign: 'center', padding: '2rem', color: '#FCA5A5' }}>
          <AlertCircle size={20} style={{ margin: '0 auto 0.5rem' }} />
          {error}
        </div>
      ) : filtered.length === 0 ? (
        <div style={{ textAlign: 'center', padding: '3rem', color: '#94A3B8' }}>
          {tickets.length === 0 ? 'No Jira tickets yet. Add one manually or create from Jira.' : 'No tickets match your filters.'}
        </div>
      ) : (
        <div style={{ ...STYLES.card, padding: '0', overflow: 'auto' }}>
          <table style={STYLES.table}>
            <thead>
              <tr>
                <th style={STYLES.th}>Ticket</th>
                <th style={STYLES.th}>CVE</th>
                <th style={STYLES.th}>Vendor</th>
                <th style={STYLES.th}>Source</th>
                <th style={STYLES.th}>Summary</th>
                <th style={STYLES.th}>Status</th>
                <th style={STYLES.th}>Last Synced</th>
                <th style={STYLES.th}>Actions</th>
              </tr>
            </thead>
            <tbody>
              {filtered.map(t => (
                <tr key={t.id} style={{ transition: 'background 0.15s' }}
                  onMouseEnter={e => e.currentTarget.style.background = 'rgba(14, 165, 233, 0.05)'}
                  onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
                >
                  <td style={STYLES.td}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: '0.4rem' }}>
                      <span style={{ fontFamily: 'monospace', fontWeight: 600, color: '#7DD3FC' }}>{t.ticket_key}</span>
                      {t.url && (
                        <a href={t.url} target="_blank" rel="noopener noreferrer" style={{ color: '#94A3B8' }} title="Open in Jira">
                          <ExternalLink size={12} />
                        </a>
                      )}
                    </div>
                  </td>
                  <td style={{ ...STYLES.td, fontFamily: 'monospace', fontSize: '0.8rem' }}>{t.cve_id}</td>
                  <td style={STYLES.td}>{t.vendor}</td>
                  <td style={STYLES.td}>
                    {(() => {
                      const badge = getSourceBadge(t.source_context);
                      return (
                        <span style={{
                          display: 'inline-flex',
                          alignItems: 'center',
                          padding: '0.15rem 0.5rem',
                          borderRadius: '9999px',
                          fontSize: '0.65rem',
                          fontWeight: 600,
                          letterSpacing: '0.02em',
                          background: `${badge.color}22`,
                          color: badge.color,
                          border: `1px solid ${badge.color}44`,
                          whiteSpace: 'nowrap',
                        }}>
                          {badge.label}
                        </span>
                      );
                    })()}
                  </td>
                  <td style={{ ...STYLES.td, maxWidth: '250px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{t.summary || '-'}</td>
                  <td style={STYLES.td}>
                    <span style={STYLES.badge(getStatusColor(t.status))}>
                      <span style={{ width: 6, height: 6, borderRadius: '50%', background: getStatusColor(t.status) }} />
                      {t.status}
                    </span>
                  </td>
                  <td style={{ ...STYLES.td, fontSize: '0.75rem', color: '#94A3B8' }}>
                    {t.last_synced_at ? new Date(t.last_synced_at).toLocaleDateString() : 'Never'}
                  </td>
                  <td style={STYLES.td}>
                    <div style={{ display: 'flex', gap: '0.3rem' }}>
                      {canWrite() && t.ticket_key && (
                        <button style={{ ...STYLES.btn, padding: '0.25rem 0.5rem', fontSize: '0.7rem' }} onClick={() => syncOne(t.id)} title="Sync with Jira">
                          <RefreshCw size={12} />
                        </button>
                      )}
                      {canWrite() && (
                        <button style={{ ...STYLES.btn, padding: '0.25rem 0.5rem', fontSize: '0.7rem' }} onClick={() => {
                          setEditingId(t.id);
                          setForm({ cve_id: t.cve_id, vendor: t.vendor, ticket_key: t.ticket_key, url: t.url || '', summary: t.summary || '', status: t.status });
                          setFormError(null);
                          setShowForm(true);
                        }} title="Edit">
                          <Edit3 size={12} />
                        </button>
                      )}
                      {canWrite() && (
                        <button style={{ ...STYLES.btn, ...STYLES.btnDanger, padding: '0.25rem 0.5rem', fontSize: '0.7rem' }} onClick={() => deleteTicket(t.id)} title="Delete">
                          <Trash2 size={12} />
                        </button>
                      )}
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {/* Lookup Modal */}
      {showLookup && (
        <div style={STYLES.modal}>
          <div style={STYLES.modalBackdrop} onClick={() => setShowLookup(false)} />
          <div style={STYLES.modalContent}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1.25rem' }}>
              <h3 style={{ margin: 0, color: '#F8FAFC', fontSize: '1rem' }}>Lookup Jira Issue</h3>
              <button onClick={() => setShowLookup(false)} style={{ background: 'none', border: 'none', color: '#94A3B8', cursor: 'pointer' }}><X size={18} /></button>
            </div>
            <div style={{ display: 'flex', gap: '0.5rem', marginBottom: '1rem' }}>
              <input
                style={{ ...STYLES.input, flex: 1 }}
                placeholder="e.g. VULN-123"
                value={lookupKey}
                onChange={e => setLookupKey(e.target.value.toUpperCase())}
                onKeyDown={e => e.key === 'Enter' && doLookup()}
              />
              <button style={STYLES.btn} onClick={doLookup} disabled={lookupLoading}>
                {lookupLoading ? <Loader size={14} className="animate-spin" /> : <Search size={14} />}
                Lookup
              </button>
            </div>
            {lookupError && <div style={{ color: '#FCA5A5', fontSize: '0.85rem', marginBottom: '0.75rem' }}>{lookupError}</div>}
            {lookupResult && (
              <div style={{ background: 'rgba(15, 23, 42, 0.6)', borderRadius: '8px', padding: '1rem', fontSize: '0.85rem', color: '#E2E8F0' }}>
                <div style={{ fontWeight: 700, color: '#7DD3FC', marginBottom: '0.5rem' }}>{lookupResult.key}</div>
                <div><strong>Summary:</strong> {lookupResult.summary}</div>
                <div><strong>Status:</strong> {lookupResult.status}</div>
                <div><strong>Type:</strong> {lookupResult.issuetype}</div>
                <div><strong>Priority:</strong> {lookupResult.priority}</div>
                <div><strong>Assignee:</strong> {lookupResult.assignee || 'Unassigned'}</div>
                <div><strong>Updated:</strong> {lookupResult.updated ? new Date(lookupResult.updated).toLocaleString() : '-'}</div>
                {canWrite() && (
                  <button
                    style={{ ...STYLES.btn, ...STYLES.btnSuccess, marginTop: '0.75rem' }}
                    onClick={() => linkExistingTicket(lookupResult)}
                    disabled={linkingSaving}
                  >
                    {linkingSaving ? <Loader size={14} className="animate-spin" /> : <Plus size={14} />}
                    Save to Dashboard
                  </button>
                )}
                {linkingError && <div style={{ color: '#FCA5A5', fontSize: '0.75rem', marginTop: '0.5rem' }}>{linkingError}</div>}
                {linkingSuccess && <div style={{ color: '#6EE7B7', fontSize: '0.75rem', marginTop: '0.5rem' }}>{linkingSuccess}</div>}
              </div>
            )}
          </div>
        </div>
      )}

      {/* Add/Edit Modal */}
      {showForm && (
        <div style={STYLES.modal}>
          <div style={STYLES.modalBackdrop} onClick={() => setShowForm(false)} />
          <div style={STYLES.modalContent}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1.25rem' }}>
              <h3 style={{ margin: 0, color: '#F8FAFC', fontSize: '1rem' }}>{editingId ? 'Edit Ticket' : 'Add Jira Ticket'}</h3>
              <button onClick={() => setShowForm(false)} style={{ background: 'none', border: 'none', color: '#94A3B8', cursor: 'pointer' }}><X size={18} /></button>
            </div>
            {formError && <div style={{ color: '#FCA5A5', fontSize: '0.85rem', marginBottom: '0.75rem' }}>{formError}</div>}
            <div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>CVE ID</label>
                <input style={STYLES.input} placeholder="CVE-2024-1234" value={form.cve_id} onChange={e => setForm(f => ({ ...f, cve_id: e.target.value }))} disabled={!!editingId} />
              </div>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>Vendor</label>
                <input style={STYLES.input} placeholder="Vendor name" value={form.vendor} onChange={e => setForm(f => ({ ...f, vendor: e.target.value }))} disabled={!!editingId} />
              </div>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>Ticket Key</label>
                <input style={STYLES.input} placeholder="PROJECT-123" value={form.ticket_key} onChange={e => setForm(f => ({ ...f, ticket_key: e.target.value.toUpperCase() }))} />
              </div>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>URL</label>
                <input style={STYLES.input} placeholder="https://jira.example.com/browse/..." value={form.url} onChange={e => setForm(f => ({ ...f, url: e.target.value }))} />
              </div>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>Summary</label>
                <input style={STYLES.input} placeholder="Brief description" value={form.summary} onChange={e => setForm(f => ({ ...f, summary: e.target.value }))} />
              </div>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>Status</label>
                <select style={{ ...STYLES.input, cursor: 'pointer' }} value={form.status} onChange={e => setForm(f => ({ ...f, status: e.target.value }))}>
                  <option value="Open">Open</option>
                  <option value="In Progress">In Progress</option>
                  <option value="Closed">Closed</option>
                  {form.status && !['Open', 'In Progress', 'Closed'].includes(form.status) && (
                    <option value={form.status}>{form.status}</option>
                  )}
                </select>
              </div>
              <button style={{ ...STYLES.btn, ...STYLES.btnSuccess, justifyContent: 'center', marginTop: '0.5rem' }} onClick={saveTicket} disabled={formSaving}>
                {formSaving ? <Loader size={14} className="animate-spin" /> : <CheckCircle size={14} />}
                {editingId ? 'Update' : 'Create'}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Create in Jira Modal */}
      {showCreateJira && (
        <div style={STYLES.modal}>
          <div style={STYLES.modalBackdrop} onClick={() => setShowCreateJira(false)} />
          <div style={STYLES.modalContent}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1.25rem' }}>
              <h3 style={{ margin: 0, color: '#F8FAFC', fontSize: '1rem' }}>Create Issue in Jira</h3>
              <button onClick={() => setShowCreateJira(false)} style={{ background: 'none', border: 'none', color: '#94A3B8', cursor: 'pointer' }}><X size={18} /></button>
            </div>
            <p style={{ fontSize: '0.8rem', color: '#94A3B8', marginTop: 0, marginBottom: '1rem' }}>
              Creates a new issue in Jira via the REST API and tracks it locally.
            </p>
            {createJiraError && <div style={{ color: '#FCA5A5', fontSize: '0.85rem', marginBottom: '0.75rem' }}>{createJiraError}</div>}
            <div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>CVE ID (optional)</label>
                <input style={STYLES.input} placeholder="e.g. CVE-2024-12345" value={createJiraForm.cve_id} onChange={e => setCreateJiraForm(f => ({ ...f, cve_id: e.target.value }))} />
              </div>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>Vendor (optional)</label>
                <input style={STYLES.input} placeholder="e.g. Microsoft" value={createJiraForm.vendor} onChange={e => setCreateJiraForm(f => ({ ...f, vendor: e.target.value }))} />
              </div>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>Summary <span style={{ color: '#F59E0B' }}>*</span></label>
                <input
                  style={{ ...STYLES.input, ...(summaryError ? { borderColor: 'rgba(239, 68, 68, 0.6)' } : {}) }}
                  placeholder="Issue summary (max 255 chars)"
                  value={createJiraForm.summary}
                  onChange={e => { setCreateJiraForm(f => ({ ...f, summary: e.target.value })); if (summaryError) setSummaryError(null); }}
                  maxLength={255}
                />
                {summaryError && <div style={{ color: '#FCA5A5', fontSize: '0.75rem', marginTop: '0.25rem' }}>{summaryError}</div>}
              </div>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>Source Context</label>
                <select
                  style={{ ...STYLES.input, cursor: createJiraLocked.source_context ? 'not-allowed' : 'pointer', opacity: createJiraLocked.source_context ? 0.7 : 1 }}
                  value={createJiraForm.source_context}
                  onChange={e => setCreateJiraForm(f => ({ ...f, source_context: e.target.value }))}
                  disabled={createJiraLocked.source_context}
                >
                  <option value="">— Select source —</option>
                  <option value="cve">CVE</option>
                  <option value="archer">Archer Request</option>
                  <option value="ivanti_queue">Ivanti Queue</option>
                  <option value="email">Email</option>
                  <option value="manual">Manual</option>
                </select>
              </div>
              <div>
                <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>Description (optional)</label>
                <textarea style={{ ...STYLES.input, minHeight: '80px', resize: 'vertical' }} placeholder="Detailed description..." value={createJiraForm.description} onChange={e => setCreateJiraForm(f => ({ ...f, description: e.target.value }))} />
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.75rem' }}>
                <div>
                  <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>Project Key (optional)</label>
                  <input style={STYLES.input} placeholder="Uses .env default" value={createJiraForm.project_key} onChange={e => setCreateJiraForm(f => ({ ...f, project_key: e.target.value.toUpperCase() }))} />
                </div>
                <div>
                  <label style={{ fontSize: '0.75rem', color: '#94A3B8', display: 'block', marginBottom: '0.25rem' }}>Issue Type</label>
                  <select style={{ ...STYLES.input, cursor: 'pointer' }} value={createJiraForm.issue_type} onChange={e => setCreateJiraForm(f => ({ ...f, issue_type: e.target.value }))}>
                    <option value="">Story (default)</option>
                    <option value="Story">Story</option>
                    <option value="Epic">Epic</option>
                    <option value="Program">Program</option>
                    <option value="Project">Project</option>
                    <option value="Reservation">Reservation</option>
                    <option value="Automation Maintenance">Automation Maintenance</option>
                  </select>
                </div>
              </div>
              <button style={{ ...STYLES.btn, ...STYLES.btnSuccess, justifyContent: 'center', marginTop: '0.5rem' }} onClick={createInJira} disabled={createJiraSaving}>
                {createJiraSaving ? <Loader size={14} className="animate-spin" /> : <Plus size={14} />}
                Create in Jira
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}