// ═══════════════════════════════════════════════════════════════════════════
// APP.JS - Main application entry point
// ═══════════════════════════════════════════════════════════════════════════

import { 
  GROUP_KEYS, 
  DEFAULT_FACILITIES, 
  DEFAULT_GROUPS, 
  DEFAULT_GROUP_NAMES 
} from './data.js';

import { 
  state,
  addFacility as stateAddFacility,
  removeFacility as stateRemoveFacility,
  addAddress as stateAddAddress,
  removeAddress as stateRemoveAddress,
  setGroupName,
  clearRouteData,
  setRouteData,
  saveRouteData,
  clearAll as stateClearAll,
  loadState,
  hasSavedState
} from './state.js';

import { geocode, getDirections } from './api.js';
import { showStatus, hideStatus, showStatusTimed, makeAddressFerpaCompliant } from './utils.js';
import { initMap, updateMap, goToLocation, getMap } from './map.js';

import { 
  renderFacilities, 
  renderList, 
  renderAllLists,
  updateGroupNames,
  switchTab,
  togglePanel,
  toggleBulk,
  updateDistances
} from './ui.js';

import {
  switchMobileView,
  switchMobileTab,
  renderMobileContent,
  updateMobileResults,
  updateMobileMap,
  updateMobileTabNames
} from './mobile.js';

// Census/Demographics imports
import {
  fetchCountyTracts,
  fetchMultipleCounties,
  scoreAllTracts,
  TEXAS_FIPS,
  DFW_COUNTY_FIPS,
  saveCensusCache,
  loadCensusCache
} from './census.js';

import {
  fetchMultipleCountyBoundaries,
  mergeCensusDataToGeoJSON,
  addCentroidsToFeatures,
  saveBoundaryCache,
  loadBoundaryCache
} from './boundaries.js';

import {
  addChoroplethLayer,
  removeChoroplethLayer,
  createMetricSelector,
  METRIC_CONFIG
} from './choropleth.js';

// ─── Demographics State ───
let demographicsLoaded = false;
let censusData = null;
let boundaryData = null;
let currentMetric = 'schoolScore';
let demographicsVisible = false;
let heatmapVisible = true;

// ─── Initialization ───

async function init() {
  // Try to load saved state first
  const hasState = loadState();
  
  if (hasState && state.facilities.length > 0) {
    // We have saved data - just render it
    console.log('Loaded saved state');
    
    // Set group name inputs
    const nameA = document.getElementById('nameA');
    const nameB = document.getElementById('nameB');
    const nameC = document.getElementById('nameC');
    
    if (nameA) nameA.value = state.groupNames.A;
    if (nameB) nameB.value = state.groupNames.B;
    if (nameC) nameC.value = state.groupNames.C;
    
    updateGroupNames();
    updateMobileTabNames();
    
    // Initialize map and render
    initMap();
    renderAllLists();
    updateMap();
    renderMobileContent();
    
    // If we have route data, show it
    if (Object.keys(state.routeData.A).length > 0 || 
        Object.keys(state.routeData.B).length > 0 || 
        Object.keys(state.routeData.C).length > 0) {
      updateDistances();
    }
  } else {
    // No saved state - load defaults
    console.log('No saved state, loading defaults');
    
    // Set up group names
    Object.assign(state.groupNames, DEFAULT_GROUP_NAMES);
    
    const nameA = document.getElementById('nameA');
    const nameB = document.getElementById('nameB');
    const nameC = document.getElementById('nameC');
    
    if (nameA) nameA.value = DEFAULT_GROUP_NAMES.A;
    if (nameB) nameB.value = DEFAULT_GROUP_NAMES.B;
    if (nameC) nameC.value = DEFAULT_GROUP_NAMES.C;
    
    updateGroupNames();
    updateMobileTabNames();
    
    // Initialize map
    initMap();
    
    // Load defaults
    await loadDefaults();
    
    // Initialize mobile content
    renderMobileContent();
  }
  
  // Check for cached demographics
  const cachedCensus = loadCensusCache();
  const cachedBoundaries = loadBoundaryCache('dfw');
  
  if (cachedCensus && cachedBoundaries) {
    console.log('Loading cached demographics');
    censusData = cachedCensus;
    boundaryData = cachedBoundaries;
    demographicsLoaded = true;
    updateDemographicsButton(true);
  }
}

// ─── Load Default Data ───

async function loadDefaults() {
  // Geocode facilities for exact placement
  showStatus('Loading facilities...');
  
  for (let i = 0; i < DEFAULT_FACILITIES.length; i++) {
    const addr = DEFAULT_FACILITIES[i];
    const coords = await geocode(addr);
    if (coords) {
      state.facilities.push({ address: addr, ...coords });
    }
  }
  renderFacilities();
  
  // Load groups with hardcoded coordinates (instant)
  GROUP_KEYS.forEach(g => {
    DEFAULT_GROUPS[g].forEach(p => {
      state.groups[g].push({ ...p });
    });
    renderList(g);
  });
  
  hideStatus();
  updateMap();
}

// ─── Facility Management ───

async function addFacility() {
  const input = document.getElementById('inputF');
  const addr = input?.value.trim();
  if (!addr) return;
  input.value = '';
  
  showStatus('Geocoding: ' + addr);
  const coords = await geocode(addr);
  hideStatus();
  
  if (!coords) {
    showStatusTimed('Not found: "' + addr + '"', 3000);
    return;
  }
  
  stateAddFacility({ address: addr, ...coords });
  renderFacilities();
  updateMap();
}

function removeFacility(index) {
  stateRemoveFacility(index);
  renderFacilities();
  updateMap();
  renderMobileContent();
}

async function bulkAddFacilities() {
  const ta = document.getElementById('bulkTextF');
  const lines = ta?.value.split('\n').map(l => l.trim()).filter(Boolean);
  if (!lines?.length) return;
  ta.value = '';
  
  for (let i = 0; i < lines.length; i++) {
    showStatus(`Geocoding facility ${i + 1}/${lines.length}: ${lines[i]}`);
    const coords = await geocode(lines[i]);
    if (coords) {
      state.facilities.push({ address: lines[i], ...coords });
    }
  }
  
  hideStatus();
  renderFacilities();
  updateMap();
}

// ─── Address Management (FERPA Compliant) ───

async function addAddress(group) {
  const input = document.getElementById('input' + group);
  const addr = input?.value.trim();
  if (!addr) return;
  input.value = '';
  
  showStatus('Geocoding: ' + addr);
  const coords = await geocode(addr);
  hideStatus();
  
  if (!coords) {
    showStatusTimed('Not found: "' + addr + '" — include city, state, zip', 4000);
    return;
  }
  
  // FERPA: De-identify address and fuzz coordinates
  console.log('Original address:', addr);
  console.log('Original coords:', coords);
  const ferpaData = makeAddressFerpaCompliant(addr, coords.lat, coords.lng);
  console.log('FERPA data:', ferpaData);
  
  stateAddAddress(group, ferpaData);
  renderList(group);
  updateMap();
}

function removeAddress(group, index) {
  stateRemoveAddress(group, index);
  renderList(group);
  updateMap();
  renderMobileContent();
}

async function bulkAdd(group) {
  const ta = document.getElementById('bulkText' + group);
  const lines = ta?.value.split('\n').map(l => l.trim()).filter(Boolean);
  if (!lines?.length) return;
  ta.value = '';
  
  for (let i = 0; i < lines.length; i++) {
    showStatus(`Geocoding ${i + 1}/${lines.length}: ${lines[i]}`);
    const coords = await geocode(lines[i]);
    if (coords) {
      // FERPA: De-identify address and fuzz coordinates
      const ferpaData = makeAddressFerpaCompliant(lines[i], coords.lat, coords.lng);
      state.groups[group].push(ferpaData);
    }
  }
  
  clearRouteData();
  hideStatus();
  renderList(group);
  updateMap();
}

// ─── Mobile Add Functions ───

async function mobileAddFacility() {
  const input = document.getElementById('mobileInputF');
  const addr = input?.value.trim();
  if (!addr) return;
  input.value = '';
  
  showStatus('Geocoding: ' + addr);
  const coords = await geocode(addr);
  hideStatus();
  
  if (!coords) {
    showStatusTimed('Not found', 2000);
    return;
  }
  
  state.facilities.push({ address: addr, ...coords });
  clearRouteData();
  renderMobileContent();
  renderFacilities();
  updateMap();
}

async function mobileAddAddress(group) {
  const input = document.getElementById('mobileInput' + group);
  const addr = input?.value.trim();
  if (!addr) return;
  input.value = '';
  
  showStatus('Geocoding: ' + addr);
  const coords = await geocode(addr);
  hideStatus();
  
  if (!coords) {
    showStatusTimed('Not found', 2000);
    return;
  }
  
  // FERPA: De-identify address and fuzz coordinates
  const ferpaData = makeAddressFerpaCompliant(addr, coords.lat, coords.lng);
  state.groups[group].push(ferpaData);
  clearRouteData();
  renderMobileContent();
  renderList(group);
  updateMap();
}

async function mobileGoToLocation() {
  const input = document.getElementById('mobileMapLocationInput');
  const loc = input?.value.trim();
  if (!loc) return;
  
  showStatus('Finding: ' + loc);
  const coords = await geocode(loc);
  hideStatus();
  
  if (coords && state.mobileMap) {
    state.mobileMap.setView([coords.lat, coords.lng], 11);
  }
}

// ─── Route Calculation ───

async function calculateAllRoutes() {
  if (!state.facilities.length) {
    showStatusTimed('Add facilities first', 2500);
    return;
  }
  
  const hasAddresses = GROUP_KEYS.some(g => state.groups[g].length > 0);
  if (!hasAddresses) {
    showStatusTimed('Add addresses first', 2500);
    return;
  }
  
  clearRouteData();
  
  let total = 0;
  GROUP_KEYS.forEach(g => {
    total += state.groups[g].length * state.facilities.length;
  });
  
  let done = 0;
  
  for (const g of GROUP_KEYS) {
    for (let ai = 0; ai < state.groups[g].length; ai++) {
      for (let fi = 0; fi < state.facilities.length; fi++) {
        done++;
        showStatus(`Calculating route ${done}/${total}...`);
        
        const p = state.groups[g][ai];
        const f = state.facilities[fi];
        const result = await getDirections(p.lat, p.lng, f.lat, f.lng);
        
        setRouteData(g, ai, fi, result);
        
        // Small delay to avoid rate limits
        await new Promise(r => setTimeout(r, 120));
      }
    }
  }
  
  hideStatus();
  saveRouteData(); // Save all routes to localStorage
  updateMap();
  updateDistances();
  updateMobileResults();
  
  // Switch to distances tab on desktop
  const distTab = document.getElementById('tabDist');
  if (distTab) switchTab('distances', distTab);
}

// ─── Demographics Loading ───

async function loadDemographics() {
  const map = getMap();
  if (!map) {
    showStatusTimed('Map not initialized', 2000);
    return;
  }
  
  // Check cache first
  const cachedCensus = loadCensusCache();
  const cachedBoundaries = loadBoundaryCache('dfw');
  
  if (cachedCensus && cachedBoundaries) {
    console.log('Using cached demographics data');
    censusData = cachedCensus;
    boundaryData = cachedBoundaries;
    
    showDemographicsLayer();
    
    // Show overlay controls
    showOverlayControls();
    
    demographicsLoaded = true;
    updateDemographicsButton(true);
    showStatusTimed('Demographics loaded from cache', 2000);
    return;
  }
  
  // Fetch fresh data
  showStatus('Loading demographics (this may take a moment)...');
  
  try {
    // Get county FIPS codes for full DFW area (11 counties)
    // Get county FIPS codes for full DFW area (11 counties)
    const countyFips = Object.values(DFW_COUNTY_FIPS);
    
    // Fetch census data
    showStatus('Fetching census data...');
    const rawCensusData = await fetchMultipleCounties(TEXAS_FIPS, countyFips);
    
    if (!rawCensusData || rawCensusData.length === 0) {
      hideStatus();
      showStatusTimed('Failed to load census data', 3000);
      return;
    }
    
    // Score all tracts
    censusData = scoreAllTracts(rawCensusData);
    console.log(`Loaded ${censusData.length} census tracts`);
    
    // Fetch boundaries
    showStatus('Fetching tract boundaries...');
    const rawBoundaries = await fetchMultipleCountyBoundaries(TEXAS_FIPS, countyFips);
    
    if (!rawBoundaries || !rawBoundaries.features || rawBoundaries.features.length === 0) {
      hideStatus();
      showStatusTimed('Failed to load boundaries', 3000);
      return;
    }
    
    // Merge data and add centroids
    boundaryData = mergeCensusDataToGeoJSON(rawBoundaries, censusData);
    boundaryData = addCentroidsToFeatures(boundaryData);
    
    console.log(`Loaded ${boundaryData.features.length} tract boundaries`);
    
    // Cache the data
    saveCensusCache(censusData);
    saveBoundaryCache(boundaryData, 'dfw');
    
    // Show on map
    showDemographicsLayer();
    
    // Show overlay controls
    showOverlayControls();
    
    demographicsLoaded = true;
    updateDemographicsButton(true);
    hideStatus();
    showStatusTimed(`Loaded ${censusData.length} census tracts`, 2000);
    
  } catch (error) {
    console.error('Demographics loading error:', error);
    hideStatus();
    showStatusTimed('Error loading demographics', 3000);
  }
}

function showDemographicsLayer() {
  const map = getMap();
  if (!map || !boundaryData) return;
  
  // Add choropleth layer
  addChoroplethLayer(map, boundaryData, currentMetric);
  demographicsVisible = true;
  
  // Update toggle button
  const toggleBtn = document.getElementById('toggleDemographics');
  if (toggleBtn) toggleBtn.classList.add('active');
  
  // Enable metric dropdown
  const dropdown = document.getElementById('metricDropdown');
  if (dropdown) dropdown.disabled = false;
}

function hideDemographicsLayer() {
  const map = getMap();
  if (!map) return;
  
  removeChoroplethLayer(map);
  demographicsVisible = false;
  
  // Update toggle button
  const toggleBtn = document.getElementById('toggleDemographics');
  if (toggleBtn) toggleBtn.classList.remove('active');
}

function toggleDemographicsLayer() {
  if (!demographicsLoaded) {
    // Load demographics first time
    loadDemographics();
    return;
  }
  
  if (demographicsVisible) {
    hideDemographicsLayer();
  } else {
    showDemographicsLayer();
  }
}

function toggleHeatmapLayer() {
  heatmapVisible = !heatmapVisible;
  
  // Update toggle button
  const toggleBtn = document.getElementById('toggleHeatmap');
  if (toggleBtn) {
    if (heatmapVisible) {
      toggleBtn.classList.add('active');
    } else {
      toggleBtn.classList.remove('active');
    }
  }
  
  // Re-render map (updateMap respects heatmapVisible)
  updateMapWithLayers();
}

function changeMetric(metric) {
  if (!demographicsLoaded || !boundaryData) return;
  
  currentMetric = metric;
  const map = getMap();
  if (map && demographicsVisible) {
    addChoroplethLayer(map, boundaryData, metric);
  }
}

function updateMapWithLayers() {
  // Import and call updateMap, passing heatmap visibility
  updateMap(heatmapVisible);
}

function showOverlayControls() {
  console.log('showOverlayControls called');
  const controls = document.getElementById('mapOverlayControls');
  console.log('controls element:', controls);
  if (controls) {
    controls.style.display = 'flex';
    console.log('Controls should now be visible');
  }
}

function toggleDemographics() {
  const map = getMap();
  if (!map) return;
  
  if (!demographicsLoaded) {
    loadDemographics();
  } else {
    toggleDemographicsLayer();
  }
}

function updateDemographicsButton(loaded) {
  const btn = document.getElementById('btnDemographics');
  if (btn) {
    if (loaded) {
      btn.textContent = '📊 Demographics ✓';
      btn.classList.add('loaded');
    } else {
      btn.textContent = '📊 Load Demographics';
      btn.classList.remove('loaded');
    }
  }
  
  const mobileBtn = document.getElementById('mobileBtnDemographics');
  if (mobileBtn) {
    if (loaded) {
      mobileBtn.textContent = '📊 Demographics ✓';
      mobileBtn.classList.add('loaded');
    } else {
      mobileBtn.textContent = '📊 Load Demographics';
      mobileBtn.classList.remove('loaded');
    }
  }
}

// ─── Group Name Handling ───

function onGroupRename() {
  GROUP_KEYS.forEach(g => {
    const input = document.getElementById('name' + g);
    setGroupName(g, input?.value.trim());
  });
  
  updateGroupNames();
  updateMobileTabNames();
  updateDistances();
}

// ─── Clear All ───

function clearAll() {
  stateClearAll();
  renderAllLists();
  updateMap();
  renderMobileContent();
}

// ─── Desktop Go To Location ───

async function handleGoToLocation() {
  const input = document.getElementById('mapLocationInput');
  await goToLocation(input?.value.trim());
}

// ─── Export Public API ───

window.app = {
  // Initialization
  init,
  
  // Facilities
  addFacility,
  removeFacility,
  bulkAddFacilities,
  
  // Addresses
  addAddress,
  removeAddress,
  bulkAdd,
  
  // Mobile
  mobileAddFacility,
  mobileAddAddress,
  mobileGoToLocation,
  switchMobileView,
  switchMobileTab,
  renderMobileContent,
  
  // Routes
  calculateAllRoutes,
  
  // Demographics
  loadDemographics,
  toggleDemographics,
  toggleDemographicsLayer,
  toggleHeatmapLayer,
  changeMetric,
  hideDemographicsLayer,
  
  // UI
  switchTab,
  togglePanel,
  toggleBulk,
  onGroupRename,
  goToLocation: handleGoToLocation,
  clearAll,
  updateMap
};

// ─── Initialize on DOM Ready ───

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', init);
} else {
  init();
}
