<?php
require_once __DIR__ . '/../../app/core/bootstrap.php';
require_once __DIR__ . '/../../app/core/project_permissions.php';
require_once __DIR__ . '/../../app/core/i18n.php';
auth_require_login();

$pdo = crm_pdo();
$page_title = 'Gantt Timeline';
$_lang = gp_lang($pdo);
$canEdit = gp_can_create_project($pdo);

// Load all active projects with dates
$stmt = $pdo->query("
    SELECT p.id, p.code, p.title, p.status, p.start_date, p.end_date_planned, p.end_date_actual,
           c.name AS customer_name, p.city
    FROM projects p
    LEFT JOIN customers c ON c.id = p.customer_id
    WHERE p.start_date IS NOT NULL AND p.start_date != '0000-00-00'
    ORDER BY p.start_date ASC, p.id DESC
");
$projects = $stmt->fetchAll(PDO::FETCH_ASSOC);

// Load status colors
$statusColors = [
    'new'         => '#3b82f6',
    'active'      => '#10b981',
    'in_progress' => '#f59e0b',
    'planned'     => '#8b5cf6',
    'on_hold'     => '#f97316',
    'done'        => '#10b981',
    'completed'   => '#64748b',
    'cancelled'   => '#ef4444',
];

// Group by status for filter
$allStatuses = array_unique(array_column($projects, 'status'));

include __DIR__ . '/../includes/header.php';
?>

<style>
/* ── Gantt Page ── */
.gantt-page { display: flex; flex-direction: column; gap: 0; height: calc(100vh - 120px); }

.gantt-toolbar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap; margin-bottom: 16px;
}
.gantt-toolbar-left { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.gantt-filter-btn {
  padding: 5px 14px; border-radius: 999px; font-size: 0.78rem; font-weight: 700;
  border: 1px solid var(--gp-card-border); background: var(--gp-card-bg);
  color: var(--gp-muted); cursor: pointer; transition: all 0.2s; text-decoration: none;
}
.gantt-filter-btn:hover, .gantt-filter-btn.active {
  background: var(--gp-primary); color: #fff; border-color: var(--gp-primary);
  box-shadow: 0 4px 12px rgba(37,99,235,0.25);
}
.gantt-zoom { display: flex; gap: 4px; }
.gantt-zoom-btn {
  padding: 6px 12px; border-radius: 8px; border: 1px solid var(--gp-card-border);
  background: var(--gp-card-bg); color: var(--gp-text); font-size: 0.82rem; font-weight: 700;
  cursor: pointer; transition: all 0.18s;
}
.gantt-zoom-btn:hover { background: var(--gp-primary); color: #fff; border-color: var(--gp-primary); }
.gantt-zoom-btn.active { background: var(--gp-primary); color: #fff; border-color: var(--gp-primary); }

/* ── Gantt Container ── */
.gantt-wrap {
  display: flex; background: var(--gp-card-bg); border: 1px solid var(--gp-card-border);
  border-radius: 16px; overflow: hidden; flex: 1; min-height: 0;
}

/* Left panel: project names */
.gantt-labels {
  flex-shrink: 0; width: 260px; border-right: 1px solid var(--gp-card-border);
  overflow-y: auto; overflow-x: hidden;
}
.gantt-label-header {
  height: 52px; display: flex; align-items: center; padding: 0 16px;
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--gp-muted); border-bottom: 1px solid var(--gp-card-border);
  background: var(--gp-nav-bg-2); position: sticky; top: 0; z-index: 10;
}
.gantt-label-row {
  height: 44px; display: flex; align-items: center; padding: 0 16px; gap: 8px;
  border-bottom: 1px solid rgba(0,0,0,0.04); transition: background 0.15s; cursor: pointer;
}
[data-theme='dark'] .gantt-label-row { border-bottom-color: rgba(255,255,255,0.04); }
.gantt-label-row:hover { background: var(--gp-nav-bg-2); }
.gantt-label-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.gantt-label-text { font-size: 0.82rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gantt-label-sub { font-size: 0.68rem; color: var(--gp-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Right panel: timeline */
.gantt-chart { flex: 1; overflow: auto; position: relative; }

.gantt-header-row {
  display: flex; height: 52px; position: sticky; top: 0; z-index: 9;
  background: var(--gp-nav-bg-2); border-bottom: 1px solid var(--gp-card-border);
  min-width: max-content;
}
.gantt-month-cell {
  flex-shrink: 0; display: flex; align-items: flex-end; padding: 0 0 6px 10px;
  font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--gp-muted); border-right: 1px solid var(--gp-card-border);
  position: relative;
}
.gantt-month-cell.today-month { color: var(--gp-primary); }

/* Day sub-header */
.gantt-days-row {
  display: flex; height: 22px; position: sticky; top: 52px; z-index: 8;
  background: var(--gp-nav-bg-2); border-bottom: 2px solid var(--gp-card-border);
  min-width: max-content;
}
.gantt-day-cell {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  font-size: 0.62rem; font-weight: 600; color: var(--gp-muted);
  border-right: 1px solid rgba(0,0,0,0.04);
}
.gantt-day-cell.weekend { background: rgba(0,0,0,0.02); }
[data-theme='dark'] .gantt-day-cell.weekend { background: rgba(255,255,255,0.015); }
.gantt-day-cell.today { background: rgba(37,99,235,0.12); color: var(--gp-primary); font-weight: 800; }

/* Rows */
.gantt-body { position: relative; min-width: max-content; }
.gantt-row {
  height: 44px; display: flex; align-items: center; position: relative;
  border-bottom: 1px solid rgba(0,0,0,0.04); cursor: pointer;
}
[data-theme='dark'] .gantt-row { border-bottom-color: rgba(255,255,255,0.04); }
.gantt-row:hover { background: rgba(0,0,0,0.015); }
[data-theme='dark'] .gantt-row:hover { background: rgba(255,255,255,0.015); }

/* Today line */
.gantt-today-line {
  position: absolute; top: 0; bottom: 0; width: 2px;
  background: rgba(37,99,235,0.5); pointer-events: none; z-index: 5;
  box-shadow: 0 0 8px rgba(37,99,235,0.3);
}

/* Grid lines */
.gantt-grid-line {
  position: absolute; top: 0; bottom: 0; width: 1px;
  background: rgba(0,0,0,0.04); pointer-events: none;
}
[data-theme='dark'] .gantt-grid-line { background: rgba(255,255,255,0.04); }
.gantt-grid-line.month-line { background: rgba(0,0,0,0.08); }
[data-theme='dark'] .gantt-grid-line.month-line { background: rgba(255,255,255,0.08); }

/* Bars */
.gantt-bar {
  position: absolute; height: 28px; border-radius: 8px; top: 8px;
  display: flex; align-items: center; padding: 0 10px;
  font-size: 0.73rem; font-weight: 700; color: #fff; white-space: nowrap; overflow: hidden;
  cursor: pointer; transition: filter 0.15s, transform 0.15s;
  box-shadow: 0 3px 10px rgba(0,0,0,0.15); min-width: 4px;
  text-overflow: ellipsis; z-index: 3;
}
.gantt-bar:hover { filter: brightness(1.1); transform: translateY(-1px); box-shadow: 0 6px 18px rgba(0,0,0,0.2); }
.gantt-bar.no-end { border-right: 4px dashed rgba(255,255,255,0.5); border-radius: 8px 0 0 8px; }

/* Tooltip */
.gantt-tooltip {
  position: fixed; background: var(--gp-card-bg); border: 1px solid var(--gp-card-border);
  border-radius: 12px; padding: 12px 16px; font-size: 0.82rem; z-index: 999;
  box-shadow: 0 12px 30px rgba(0,0,0,0.15); pointer-events: none; max-width: 280px;
  backdrop-filter: blur(20px); display: none;
}
.gantt-tooltip-title { font-weight: 800; font-size: 0.9rem; margin-bottom: 6px; }
.gantt-tooltip-row { display: flex; gap: 8px; color: var(--gp-muted); margin-top: 3px; }
.gantt-tooltip-row span:first-child { min-width: 70px; font-weight: 600; color: var(--gp-text); }

.gantt-empty { padding: 60px; text-align: center; color: var(--gp-muted); font-size: 1rem; }
</style>

<!-- Toolbar -->
<div class="page-header" style="margin-bottom: 16px;">
  <div class="page-header-title">
    <h1>📊 Gantt Timeline</h1>
    <span id="gantt-count-label" style="color:var(--gp-muted);font-size:.88rem;"></span>
  </div>
  <div class="page-header-actions" style="display:flex;gap:8px;align-items:center;">
    <a href="/gopools/public/projects/index.php" class="btn btn-sm btn-outline-light">☰ Λίστα</a>
    <a href="/gopools/public/projects/board.php" class="btn btn-sm btn-outline-light">🗂️ Board</a>
    <a href="/gopools/public/dashboard/index.php" class="btn btn-sm btn-outline-light">📅 Ημερολόγιο</a>
    <?php if ($canEdit): ?>
      <a href="/gopools/public/projects/edit.php" class="btn btn-sm btn-primary">+ Νέο</a>
    <?php endif; ?>
  </div>
</div>

<div class="gantt-toolbar">
  <div class="gantt-toolbar-left" id="gantt-filters">
    <button class="gantt-filter-btn active" data-filter="all">Όλα</button>
    <?php foreach ($allStatuses as $s): ?>
      <button class="gantt-filter-btn" data-filter="<?php echo h($s); ?>"
        style="--fc: <?php echo $statusColors[$s] ?? '#6b7280'; ?>">
        <span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:<?php echo $statusColors[$s] ?? '#6b7280'; ?>;margin-right:5px;"></span>
        <?php echo h(ucfirst(str_replace('_', ' ', $s))); ?>
      </button>
    <?php endforeach; ?>
  </div>
  <div style="display:flex;gap:8px;align-items:center;">
    <div class="gantt-zoom">
      <button class="gantt-zoom-btn" id="zoom-out" title="Zoom out">−</button>
      <button class="gantt-zoom-btn active" id="zoom-week" title="Week view">Εβδ.</button>
      <button class="gantt-zoom-btn" id="zoom-month" title="Month view">Μήν.</button>
      <button class="gantt-zoom-btn" id="zoom-in" title="Zoom in">+</button>
    </div>
    <button class="gantt-zoom-btn" id="gantt-today-btn">⊙ Σήμερα</button>
  </div>
</div>

<!-- Gantt wrapper -->
<div class="gantt-wrap" id="gantt-wrap">
  <!-- Labels -->
  <div class="gantt-labels" id="gantt-labels">
    <div class="gantt-label-header">Έργο</div>
    <div id="gantt-label-body"></div>
  </div>
  <!-- Chart -->
  <div class="gantt-chart" id="gantt-chart">
    <div id="gantt-header-row" class="gantt-header-row"></div>
    <div id="gantt-days-row" class="gantt-days-row"></div>
    <div id="gantt-body" class="gantt-body"></div>
  </div>
</div>

<!-- Tooltip -->
<div class="gantt-tooltip" id="gantt-tooltip"></div>

<script>
const PROJECTS = <?php echo json_encode(array_values($projects), JSON_UNESCAPED_UNICODE); ?>;
const STATUS_COLORS = <?php echo json_encode($statusColors); ?>;

let DAY_W = 24; // px per day (default: week zoom)
let activeFilter = 'all';
let filteredProjects = [...PROJECTS];

// ── Date helpers ──
const today = new Date(); today.setHours(0,0,0,0);
function parseDate(s) { if (!s || s === '0000-00-00') return null; const d = new Date(s); d.setHours(0,0,0,0); return d; }
function daysDiff(a, b) { return Math.round((b - a) / 86400000); }
function addDays(d, n) { const r = new Date(d); r.setDate(r.getDate() + n); return r; }
function fmtDate(d) { if (!d) return '—'; return d.toLocaleDateString('el-GR', {day:'2-digit',month:'2-digit',year:'numeric'}); }
function fmtMonth(d) { return d.toLocaleDateString('el-GR', {month:'short', year:'numeric'}); }

// ── Compute range from projects ──
function computeRange() {
  let min = null, max = null;
  for (const p of filteredProjects) {
    const s = parseDate(p.start_date);
    const e = parseDate(p.end_date_planned || p.end_date_actual);
    if (s) { if (!min || s < min) min = s; }
    if (e) { if (!max || e > max) max = e; }
  }
  // Fallback
  if (!min) min = addDays(today, -30);
  if (!max || max <= min) max = addDays(min, 120);
  // Padding
  const start = addDays(min, -14);
  const end   = addDays(max, 30);
  return { start, end, days: daysDiff(start, end) + 1 };
}

let RANGE = null;

function build() {
  RANGE = computeRange();
  const totalW = RANGE.days * DAY_W;

  // ── Header (months) ──
  const headerRow = document.getElementById('gantt-header-row');
  const daysRow   = document.getElementById('gantt-days-row');
  const body      = document.getElementById('gantt-body');
  const labelBody = document.getElementById('gantt-label-body');

  headerRow.innerHTML = '';
  daysRow.innerHTML = '';
  body.innerHTML = '';
  labelBody.innerHTML = '';

  // Month cells
  let cursor = new Date(RANGE.start);
  while (cursor <= RANGE.end) {
    const monthStart = new Date(cursor);
    const year = cursor.getFullYear(), month = cursor.getMonth();
    // Find last day of this month in range
    const nextMonth = new Date(year, month + 1, 1);
    const monthEndInRange = nextMonth > RANGE.end ? RANGE.end : addDays(nextMonth, -1);
    const daysInSegment = daysDiff(monthStart, monthEndInRange) + 1;
    const w = daysInSegment * DAY_W;
    const isToday = (monthStart.getFullYear() === today.getFullYear() && monthStart.getMonth() === today.getMonth());
    const cell = document.createElement('div');
    cell.className = 'gantt-month-cell' + (isToday ? ' today-month' : '');
    cell.style.width = w + 'px';
    const label = monthStart.toLocaleDateString('el-GR', {month: 'long', year: '2-digit'});
    cell.textContent = label;
    headerRow.appendChild(cell);
    cursor = nextMonth;
  }
  headerRow.style.width = totalW + 'px';

  // Day cells + grid lines
  const gridFrag = document.createDocumentFragment();
  for (let i = 0; i < RANGE.days; i++) {
    const d = addDays(RANGE.start, i);
    const dow = d.getDay();
    const isWeekend = dow === 0 || dow === 6;
    const isTodayDay = daysDiff(today, d) === 0;

    const dayCell = document.createElement('div');
    dayCell.className = 'gantt-day-cell' + (isWeekend ? ' weekend' : '') + (isTodayDay ? ' today' : '');
    dayCell.style.width = DAY_W + 'px';
    if (DAY_W >= 18) dayCell.textContent = d.getDate();
    daysRow.appendChild(dayCell);

    // Grid line
    const line = document.createElement('div');
    const isMonthStart = d.getDate() === 1;
    line.className = 'gantt-grid-line' + (isMonthStart ? ' month-line' : '');
    line.style.left = (i * DAY_W) + 'px';
    gridFrag.appendChild(line);
  }
  daysRow.style.width = totalW + 'px';

  // Today line
  const todayOffset = daysDiff(RANGE.start, today);
  if (todayOffset >= 0 && todayOffset < RANGE.days) {
    const todayLine = document.createElement('div');
    todayLine.className = 'gantt-today-line';
    todayLine.style.left = (todayOffset * DAY_W + DAY_W / 2) + 'px';
    body.appendChild(todayLine);
  }
  body.appendChild(gridFrag);
  body.style.width = totalW + 'px';

  // ── Rows ──
  document.getElementById('gantt-count-label').textContent = filteredProjects.length + ' έργα';
  const tooltip = document.getElementById('gantt-tooltip');

  filteredProjects.forEach(p => {
    const start = parseDate(p.start_date);
    if (!start) return;
    const end = parseDate(p.end_date_planned) || parseDate(p.end_date_actual) || addDays(start, 1);
    const color = STATUS_COLORS[p.status] || '#6b7280';

    // Label row
    const labelRow = document.createElement('div');
    labelRow.className = 'gantt-label-row';
    labelRow.title = p.title + (p.customer_name ? ' — ' + p.customer_name : '');
    labelRow.innerHTML = `
      <div class="gantt-label-dot" style="background:${color};"></div>
      <div style="min-width:0;">
        <div class="gantt-label-text">${escH(p.title)}</div>
        <div class="gantt-label-sub">${escH(p.customer_name || p.code || '')}</div>
      </div>`;
    labelRow.onclick = () => window.location = '/gopools/public/projects/view.php?id=' + p.id;
    labelBody.appendChild(labelRow);

    // Chart row
    const row = document.createElement('div');
    row.className = 'gantt-row';
    row.style.width = totalW + 'px';

    const startOff = Math.max(0, daysDiff(RANGE.start, start));
    const endOff   = Math.min(RANGE.days, daysDiff(RANGE.start, end) + 1);
    const barW     = Math.max(4, (endOff - startOff) * DAY_W - 4);
    const hasEnd   = !!(p.end_date_planned || p.end_date_actual);
    const duration = daysDiff(start, end);

    const bar = document.createElement('div');
    bar.className = 'gantt-bar' + (!hasEnd ? ' no-end' : '');
    bar.style.left   = (startOff * DAY_W + 2) + 'px';
    bar.style.width  = barW + 'px';
    bar.style.background = `linear-gradient(135deg, ${color}, ${lighten(color, 20)})`;
    if (barW > 60) bar.textContent = p.title;

    // Tooltip
    bar.addEventListener('mouseenter', (e) => {
      tooltip.style.display = 'block';
      tooltip.innerHTML = `
        <div class="gantt-tooltip-title" style="color:${color}">${escH(p.title)}</div>
        ${p.customer_name ? `<div class="gantt-tooltip-row"><span>Πελάτης</span>${escH(p.customer_name)}</div>` : ''}
        ${p.city ? `<div class="gantt-tooltip-row"><span>Πόλη</span>${escH(p.city)}</div>` : ''}
        <div class="gantt-tooltip-row"><span>Έναρξη</span>${fmtDate(start)}</div>
        <div class="gantt-tooltip-row"><span>Λήξη</span>${hasEnd ? fmtDate(end) : '—'}</div>
        <div class="gantt-tooltip-row"><span>Διάρκεια</span>${hasEnd ? duration + ' ημέρες' : 'Αόριστη'}</div>
        <div class="gantt-tooltip-row"><span>Status</span>${escH(p.status)}</div>`;
      positionTooltip(e);
    });
    bar.addEventListener('mousemove', positionTooltip);
    bar.addEventListener('mouseleave', () => tooltip.style.display = 'none');
    bar.onclick = () => window.location = '/gopools/public/projects/view.php?id=' + p.id;

    row.appendChild(bar);
    body.appendChild(row);
  });

  // Sync scroll between labels and chart body
  const chartEl = document.getElementById('gantt-chart');
  const labelsEl = document.getElementById('gantt-labels');

  chartEl.removeEventListener('scroll', syncScroll);
  chartEl.addEventListener('scroll', syncScroll);
  function syncScroll() { labelsEl.scrollTop = chartEl.scrollTop; }

  // Scroll to today
  scrollToToday();
}

function scrollToToday() {
  if (!RANGE) return;
  const chartEl = document.getElementById('gantt-chart');
  const todayOffset = daysDiff(RANGE.start, today);
  // If today is within range, center on it; otherwise scroll to start of first project
  if (todayOffset >= 0 && todayOffset < RANGE.days) {
    const targetScroll = Math.max(0, todayOffset * DAY_W - chartEl.clientWidth / 3);
    chartEl.scrollLeft = targetScroll;
  } else {
    chartEl.scrollLeft = 0;
  }
}

function positionTooltip(e) {
  const tt = document.getElementById('gantt-tooltip');
  let x = e.clientX + 16, y = e.clientY + 16;
  if (x + 300 > window.innerWidth) x = e.clientX - 300;
  if (y + 200 > window.innerHeight) y = e.clientY - 200;
  tt.style.left = x + 'px';
  tt.style.top  = y + 'px';
}

function escH(s) {
  if (!s) return '';
  return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}

function lighten(hex, pct) {
  const n = parseInt(hex.slice(1), 16);
  const r = Math.min(255, (n >> 16) + pct), g = Math.min(255, ((n >> 8) & 0xFF) + pct), b = Math.min(255, (n & 0xFF) + pct);
  return '#' + [r,g,b].map(x => x.toString(16).padStart(2,'0')).join('');
}

// ── Filters ──
document.getElementById('gantt-filters').addEventListener('click', e => {
  const btn = e.target.closest('.gantt-filter-btn');
  if (!btn) return;
  document.querySelectorAll('.gantt-filter-btn').forEach(b => b.classList.remove('active'));
  btn.classList.add('active');
  activeFilter = btn.dataset.filter;
  filteredProjects = activeFilter === 'all' ? [...PROJECTS] : PROJECTS.filter(p => p.status === activeFilter);
  build();
});

// ── Zoom ──
const zoomLevels = [8, 14, 24, 36, 56];
let zoomIndex = 2;
function applyZoom() {
  DAY_W = zoomLevels[zoomIndex];
  document.getElementById('zoom-week').classList.toggle('active', zoomIndex === 2);
  document.getElementById('zoom-month').classList.toggle('active', zoomIndex === 1);
  build();
}
document.getElementById('zoom-in').onclick = () => { if (zoomIndex < zoomLevels.length - 1) { zoomIndex++; applyZoom(); } };
document.getElementById('zoom-out').onclick = () => { if (zoomIndex > 0) { zoomIndex--; applyZoom(); } };
document.getElementById('zoom-week').onclick = () => { zoomIndex = 2; applyZoom(); };
document.getElementById('zoom-month').onclick = () => { zoomIndex = 1; applyZoom(); };
document.getElementById('gantt-today-btn').onclick = scrollToToday;

// Scroll labels & chart together via keyboard
document.getElementById('gantt-chart').addEventListener('wheel', (e) => {
  if (e.shiftKey) {
    e.preventDefault();
    document.getElementById('gantt-chart').scrollLeft += e.deltaY;
  }
}, { passive: false });

// ── Initial build ──
build();
</script>

<?php include __DIR__ . '/../includes/footer.php'; ?>
