import './admin.css';
import { initAuth, onAuthChange, loginWithGoogle, logout } from './auth.js';
import { db } from './firebase.js';
import { doc, getDoc, setDoc } from 'firebase/firestore';

// Hardcoded admin allowlist — used to bootstrap the Firestore config/admins document
// on first login if it doesn't exist yet.
const SEED_ADMINS = ['pcgurudm@gmail.com'];
import {
  getDonors,
  addDonorWithDate,
  addDonorsBatch,
  updateDonor,
  deleteDonor,
  calculateTotal,
} from './donors.js';

let allDonors = [];

// ===== Init =====
document.addEventListener('DOMContentLoaded', () => {
  initAuth();
  initAuthUI();
  initTabs();
  initAddForm();
  initCSVImport();
  initEditModal();
});

// ===== Auth =====
function initAuthUI() {
  document.getElementById('loginGoogle').addEventListener('click', loginWithGoogle);
  document.getElementById('logoutBtn').addEventListener('click', logout);
  document.getElementById('unauthorizedLogout').addEventListener('click', logout);
  onAuthChange(handleAuth);
}

async function handleAuth(user) {
  const authSection = document.getElementById('authSection');
  const unauthorizedSection = document.getElementById('unauthorizedSection');
  const adminContent = document.getElementById('adminContent');
  const logoutBtn = document.getElementById('logoutBtn');

  if (!user) {
    authSection.classList.remove('hidden');
    unauthorizedSection.classList.add('hidden');
    adminContent.classList.add('hidden');
    logoutBtn.style.display = 'none';
    return;
  }

  logoutBtn.style.display = '';

  // Check admin allowlist
  const isAdmin = await checkAdmin(user.email);
  if (!isAdmin) {
    authSection.classList.add('hidden');
    unauthorizedSection.classList.remove('hidden');
    adminContent.classList.add('hidden');
    return;
  }

  authSection.classList.add('hidden');
  unauthorizedSection.classList.add('hidden');
  adminContent.classList.remove('hidden');
  loadDonors();
}

async function checkAdmin(email) {
  try {
    const adminDocRef = doc(db, 'config', 'admins');
    const adminDoc = await getDoc(adminDocRef);

    if (!adminDoc.exists()) {
      // No allowlist yet — bootstrap it if this user is in the seed list
      if (SEED_ADMINS.includes(email)) {
        await setDoc(adminDocRef, { emails: SEED_ADMINS });
        console.log('Admin allowlist created with seed admins.');
        return true;
      }
      // No doc and not a seed admin — deny
      return false;
    }

    const emails = adminDoc.data()?.emails || [];
    return emails.includes(email);
  } catch (err) {
    console.error('Admin check failed:', err);
    return false;
  }
}

// ===== Tabs =====
function initTabs() {
  document.querySelectorAll('.admin-tab').forEach((btn) => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('.admin-tab').forEach((b) => b.classList.remove('active'));
      document.querySelectorAll('.admin-panel').forEach((p) => p.classList.remove('active'));
      btn.classList.add('active');
      document.getElementById(`panel-${btn.dataset.tab}`).classList.add('active');
    });
  });
}

// ===== Load Donors =====
async function loadDonors() {
  try {
    allDonors = await getDonors();
    updateStats();
    renderDonorTable();
  } catch (err) {
    console.error('Failed to load donors:', err);
    showToast('Failed to load donors.', 'error');
  }
}

function updateStats() {
  const total = calculateTotal(allDonors);
  document.getElementById('statTotal').textContent = `$${total.toLocaleString()}`;
  document.getElementById('statCount').textContent = allDonors.length;
}

// ===== Add Donor Form =====
function initAddForm() {
  const form = document.getElementById('addDonorForm');
  form.addEventListener('submit', async (e) => {
    e.preventDefault();
    const btn = document.getElementById('addDonorBtn');
    btn.disabled = true;
    btn.textContent = 'Adding...';

    try {
      await addDonorWithDate({
        name: document.getElementById('donorName').value.trim(),
        amount: document.getElementById('donorAmount').value,
        classYear: document.getElementById('donorClassYear').value.trim(),
        message: document.getElementById('donorMessage').value.trim(),
        anonymous: document.getElementById('donorAnonymous').checked,
        date: document.getElementById('donorDate').value || null,
      });
      showToast('Donor added!', 'success');
      form.reset();
      await loadDonors();
    } catch (err) {
      console.error('Failed to add donor:', err);
      showToast('Failed to add donor.', 'error');
    } finally {
      btn.disabled = false;
      btn.textContent = 'Add Donor';
    }
  });
}

// ===== CSV Import =====
let csvRows = [];
let csvHeaders = [];

function initCSVImport() {
  const fileInput = document.getElementById('csvFile');
  fileInput.addEventListener('change', handleFileSelect);

  document.getElementById('importBtn').addEventListener('click', runImport);
  document.getElementById('csvCancelBtn').addEventListener('click', resetCSV);

  // Update preview when mappings change
  document.querySelectorAll('.mapping-grid select').forEach((sel) => {
    sel.addEventListener('change', updatePreview);
  });
}

function handleFileSelect(e) {
  const file = e.target.files[0];
  if (!file) return;

  const reader = new FileReader();
  reader.onload = (evt) => {
    const text = evt.target.result;
    const parsed = parseCSV(text);
    if (parsed.length < 2) {
      showToast('CSV file appears empty or has no data rows.', 'error');
      return;
    }
    csvHeaders = parsed[0];
    csvRows = parsed.slice(1);
    setupMapping();
    document.getElementById('csvMapping').classList.remove('hidden');
  };
  reader.readAsText(file);
}

function parseCSV(text) {
  const rows = [];
  let current = [];
  let field = '';
  let inQuotes = false;

  for (let i = 0; i < text.length; i++) {
    const ch = text[i];
    const next = text[i + 1];

    if (inQuotes) {
      if (ch === '"' && next === '"') {
        field += '"';
        i++;
      } else if (ch === '"') {
        inQuotes = false;
      } else {
        field += ch;
      }
    } else {
      if (ch === '"') {
        inQuotes = true;
      } else if (ch === ',') {
        current.push(field.trim());
        field = '';
      } else if (ch === '\n' || (ch === '\r' && next === '\n')) {
        current.push(field.trim());
        if (current.some((c) => c !== '')) rows.push(current);
        current = [];
        field = '';
        if (ch === '\r') i++;
      } else {
        field += ch;
      }
    }
  }
  // Last field/row
  current.push(field.trim());
  if (current.some((c) => c !== '')) rows.push(current);

  return rows;
}

function setupMapping() {
  const fields = ['mapName', 'mapAmount', 'mapClassYear', 'mapMessage', 'mapDate', 'mapAnonymous'];
  const hints = {
    mapName: ['name', 'donor', 'first', 'full'],
    mapAmount: ['amount', 'donation', 'gift', 'total', 'sum'],
    mapClassYear: ['class', 'year', 'grad'],
    mapMessage: ['message', 'note', 'comment'],
    mapDate: ['date', 'time', 'when'],
    mapAnonymous: ['anonymous', 'anon'],
  };

  for (const fieldId of fields) {
    const select = document.getElementById(fieldId);
    select.innerHTML = '<option value="">-- skip --</option>';
    csvHeaders.forEach((h, i) => {
      const opt = document.createElement('option');
      opt.value = i;
      opt.textContent = h;
      select.appendChild(opt);
    });

    // Auto-map by fuzzy match
    const keywords = hints[fieldId];
    const match = csvHeaders.findIndex((h) =>
      keywords.some((k) => h.toLowerCase().includes(k))
    );
    if (match !== -1) select.value = match;
  }

  updatePreview();
}

function getMappedRow(row) {
  const get = (id) => {
    const val = document.getElementById(id).value;
    return val !== '' ? (row[Number(val)] || '') : '';
  };
  return {
    name: get('mapName'),
    amount: get('mapAmount'),
    classYear: get('mapClassYear'),
    message: get('mapMessage'),
    date: get('mapDate'),
    anonymous: get('mapAnonymous'),
  };
}

function updatePreview() {
  const head = document.getElementById('csvPreviewHead');
  const body = document.getElementById('csvPreviewBody');

  head.innerHTML = '<tr><th>Name</th><th>Amount</th><th>Class Year</th><th>Date</th><th>Message</th><th>Anon</th></tr>';

  const previewRows = csvRows.slice(0, 5);
  body.innerHTML = previewRows
    .map((row) => {
      const m = getMappedRow(row);
      return `<tr>
        <td>${esc(m.name)}</td>
        <td>${esc(m.amount)}</td>
        <td>${esc(m.classYear)}</td>
        <td>${esc(m.date)}</td>
        <td>${esc(m.message)}</td>
        <td>${normBool(m.anonymous) ? 'Yes' : 'No'}</td>
      </tr>`;
    })
    .join('');

  document.getElementById('previewCount').textContent = `(${csvRows.length} rows total)`;
}

function normBool(val) {
  if (!val) return false;
  const v = val.toString().toLowerCase().trim();
  return v === 'true' || v === 'yes' || v === '1';
}

async function runImport() {
  const importBtn = document.getElementById('importBtn');
  const progressEl = document.getElementById('importProgress');
  const progressFill = document.getElementById('progressFill');
  const progressText = document.getElementById('progressText');

  const donors = csvRows
    .map((row) => {
      const m = getMappedRow(row);
      const amount = parseFloat(m.amount.replace(/[^0-9.\-]/g, ''));
      if (!m.name && !normBool(m.anonymous)) return null;
      if (isNaN(amount) || amount <= 0) return null;
      return {
        name: m.name || 'Anonymous',
        amount,
        classYear: m.classYear,
        message: m.message,
        date: m.date || null,
        anonymous: normBool(m.anonymous),
      };
    })
    .filter(Boolean);

  if (donors.length === 0) {
    showToast('No valid rows to import. Check your column mapping.', 'error');
    return;
  }

  if (!confirm(`Import ${donors.length} donors? (${csvRows.length - donors.length} rows will be skipped due to missing name/amount)`)) {
    return;
  }

  importBtn.disabled = true;
  progressEl.classList.remove('hidden');

  try {
    // Process in chunks of 500 with progress
    const chunkSize = 500;
    let imported = 0;
    for (let i = 0; i < donors.length; i += chunkSize) {
      const chunk = donors.slice(i, i + chunkSize);
      await addDonorsBatch(chunk);
      imported += chunk.length;
      const pct = Math.round((imported / donors.length) * 100);
      progressFill.style.width = pct + '%';
      progressText.textContent = `Imported ${imported} of ${donors.length}...`;
    }

    showToast(`Successfully imported ${imported} donors!`, 'success');
    resetCSV();
    await loadDonors();
  } catch (err) {
    console.error('Import failed:', err);
    showToast('Import failed. Some rows may have been imported.', 'error');
  } finally {
    importBtn.disabled = false;
    progressEl.classList.add('hidden');
    progressFill.style.width = '0%';
  }
}

function resetCSV() {
  csvRows = [];
  csvHeaders = [];
  document.getElementById('csvFile').value = '';
  document.getElementById('csvMapping').classList.add('hidden');
}

// ===== Donor Table =====
function renderDonorTable(filter = '') {
  const tbody = document.getElementById('donorTableBody');
  const emptyState = document.getElementById('donorListEmpty');
  const filtered = filter
    ? allDonors.filter((d) => d.name.toLowerCase().includes(filter.toLowerCase()))
    : allDonors;

  if (filtered.length === 0) {
    tbody.innerHTML = '';
    emptyState.classList.remove('hidden');
    return;
  }

  emptyState.classList.add('hidden');
  tbody.innerHTML = filtered
    .map((d) => {
      const date = d.date?.toDate ? d.date.toDate().toLocaleDateString() : '';
      return `<tr>
        <td>${esc(d.name)}${d.anonymous ? ' <span class="anon-badge">Anon</span>' : ''}</td>
        <td>$${(d.amount || 0).toLocaleString()}</td>
        <td>${esc(d.classYear)}</td>
        <td>${date}</td>
        <td class="msg-cell">${esc(d.message)}</td>
        <td class="action-cell">
          <button class="btn-icon btn-edit" data-id="${d.id}" title="Edit">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
          </button>
          <button class="btn-icon btn-delete" data-id="${d.id}" title="Delete">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>
          </button>
        </td>
      </tr>`;
    })
    .join('');

  // Attach handlers
  tbody.querySelectorAll('.btn-edit').forEach((btn) => {
    btn.addEventListener('click', () => openEditModal(btn.dataset.id));
  });
  tbody.querySelectorAll('.btn-delete').forEach((btn) => {
    btn.addEventListener('click', () => handleDelete(btn.dataset.id));
  });

  // Search
  const searchInput = document.getElementById('donorSearch');
  searchInput.removeEventListener('input', searchHandler);
  searchInput.addEventListener('input', searchHandler);
}

function searchHandler(e) {
  renderDonorTable(e.target.value.trim());
}

async function handleDelete(id) {
  if (!confirm('Delete this donor? This cannot be undone.')) return;
  try {
    await deleteDonor(id);
    showToast('Donor deleted.', 'success');
    await loadDonors();
  } catch (err) {
    console.error('Delete failed:', err);
    showToast('Failed to delete donor.', 'error');
  }
}

// ===== Edit Modal =====
function initEditModal() {
  const modal = document.getElementById('editModal');
  document.getElementById('editModalClose').addEventListener('click', () => modal.classList.add('hidden'));
  modal.addEventListener('click', (e) => {
    if (e.target === modal) modal.classList.add('hidden');
  });

  document.getElementById('editDonorForm').addEventListener('submit', async (e) => {
    e.preventDefault();
    const id = document.getElementById('editDonorId').value;
    const btn = e.target.querySelector('button[type="submit"]');
    btn.disabled = true;
    btn.textContent = 'Saving...';

    try {
      await updateDonor(id, {
        name: document.getElementById('editAnonymous').checked
          ? 'Anonymous'
          : document.getElementById('editName').value.trim(),
        amount: Number(document.getElementById('editAmount').value),
        classYear: document.getElementById('editClassYear').value.trim(),
        message: document.getElementById('editMessage').value.trim(),
        anonymous: document.getElementById('editAnonymous').checked,
      });
      showToast('Donor updated!', 'success');
      modal.classList.add('hidden');
      await loadDonors();
    } catch (err) {
      console.error('Update failed:', err);
      showToast('Failed to update donor.', 'error');
    } finally {
      btn.disabled = false;
      btn.textContent = 'Save Changes';
    }
  });
}

function openEditModal(id) {
  const donor = allDonors.find((d) => d.id === id);
  if (!donor) return;

  document.getElementById('editDonorId').value = id;
  document.getElementById('editName').value = donor.name || '';
  document.getElementById('editAmount').value = donor.amount || '';
  document.getElementById('editClassYear').value = donor.classYear || '';
  document.getElementById('editMessage').value = donor.message || '';
  document.getElementById('editAnonymous').checked = !!donor.anonymous;
  document.getElementById('editModal').classList.remove('hidden');
}

// ===== Utilities =====
function esc(str) {
  const div = document.createElement('div');
  div.textContent = str || '';
  return div.innerHTML;
}

function showToast(message, type = 'info') {
  const existing = document.querySelector('.toast');
  if (existing) existing.remove();

  const toast = document.createElement('div');
  toast.className = `toast ${type}`;
  toast.textContent = message;
  document.body.appendChild(toast);
  setTimeout(() => toast.remove(), 4000);
}
