#!/usr/bin/env node
/**
 * Seed Tuxedo Corn 2026 tour: locations + stops.
 *
 * Uses sql`...` tagged template from @neondatabase/serverless (WebSocket mode)
 * for INSERTs — this is the only Neon serverless API that actually executes writes.
 *
 * Run with:
 *   node scripts/seed-tuxedo-2026.js
 *
 * Requires DATABASE_URL in .env.local (or pass explicitly).
 */
require("dotenv").config({ path: ".env.local" });
const { neon } = require("@neondatabase/serverless");
const ExcelJS = require("exceljs");
const path = require("path");

const TUXEDO_BRAND_ID = "64294306-5f42-463d-a5e8-2ad6c81a96de";
const YEAR = 2026;

const url = process.env.DATABASE_URL;
if (!url) {
  console.error("❌ DATABASE_URL not set in .env.local");
  process.exit(1);
}

const cleanUrl = url.replace(/[?&]channel_binding=require/gi, "").trim();
// Use direct compute endpoint with WebSocket for full DDL + DML support
const directUrl = cleanUrl.replace("-pooler.", ".");
const sql = neon(directUrl, { webSocket: true });

const MONTH_MAP = {
  Jan: "01", Feb: "02", Mar: "03", Apr: "04", May: "05", Jun: "06",
  Jul: "07", Aug: "08", Sep: "09", Oct: "10", Nov: "11", Dec: "12",
};

function parseExcelDate(s) {
  if (!s) return null;
  const m = /^([A-Za-z]{3})\s+(\d{1,2})$/.exec(String(s).trim());
  if (!m) return null;
  const mm = MONTH_MAP[m[1]];
  if (!mm) return null;
  return `${YEAR}-${mm}-${parseInt(m[2], 10).toString().padStart(2, "0")}`;
}

function parseTimeRange(s) {
  if (!s) return "";
  return String(s).replace(/[–—]/g, "-").replace(/\s+/g, " ").trim();
}

async function parseXlsx(xlsxPath) {
  const workbook = new ExcelJS.Workbook();
  await workbook.xlsx.readFile(xlsxPath);

  // --- Locations from Stop Directory ---
  const locSheet = workbook.getWorksheet("Stop Directory");
  const locations = [];
  const seenLoc = new Set();

  if (locSheet) {
    locSheet.eachRow((row, rowNum) => {
      if (rowNum === 1) return;
      // Column mapping via getCell():
      // col1=Truck, col2=City, col3=State, col4=Host(venue name), col5=Address, col6=Phone, col7=Contact, col12=Notes
      const rawCity = String(row.getCell(2).value || "").trim();
      const rawState = String(row.getCell(3).value || "").trim();
      const rawName = String(row.getCell(4).value || "").trim();
      const rawAddress = String(row.getCell(5).value || "").trim();
      if (!rawCity || !rawName) return;
      const key = `${rawName}|${rawCity}|${rawState}`;
      if (seenLoc.has(key)) return;
      seenLoc.add(key);
      locations.push({
        name: rawName,
        address: rawAddress || null,
        city: rawCity,
        state: rawState,
        zip: null,
        phone: String(row.getCell(6).value || "").trim() || null,
        contact_name: String(row.getCell(7).value || "").trim() || null,
        contact_email: null,
        notes: String(row.getCell(12).value || "").trim() || null,
        active: true,
      });
    });
  }
  console.log(`Parsed ${locations.length} locations`);

  // --- Stops from Full Schedule ---
  const schedSheet = workbook.getWorksheet("Full Schedule");
  const stops = [];
  const venueAddressMap = new Map();

  if (locSheet) {
    locSheet.eachRow((row, rowNum) => {
      if (rowNum === 1) return;
      const name = String(row.getCell(4).value || "").trim();
      const address = String(row.getCell(5).value || "").trim();
      if (name && address) venueAddressMap.set(name, address);
    });
  }

  if (schedSheet) {
    schedSheet.eachRow((row) => {
      const rowValues = row.values || [];
      // Column mapping (1-indexed, col1=null):
      // col2=Wk, col3=Type, col4=Date, col5=Day, col6=City/Location, col7=Host/Venue, col8=Time, col9=Truck, col10=Status, col11=Notes
      const firstCell = String(rowValues[1] || "").trim();
      // Skip title rows, week headers ("Wk 1"), OFF, Cross-Dock
      if (!firstCell || /^Wk\s*\d+/i.test(firstCell) || firstCell === "OFF" || firstCell === "Cross-Dock") return;

      const dateStr = parseExcelDate(rowValues[3]);
      if (!dateStr) return;

      const cityStateRaw = String(rowValues[5] || "").trim();
      const cityParts = cityStateRaw.split(",").map((s) => s.trim());
      const city = cityParts[0] || "";
      const state = cityParts[1] || "";
      const location = String(rowValues[6] || "").trim();
      if (!city || !state || !location) return;

      const rawTime = rowValues[7];
      const time = rawTime ? parseTimeRange(rawTime) : "";
      const truck = String(rowValues[8] || "").trim();
      const statusText = String(rowValues[9] || "").trim();
      const notesText = String(rowValues[10] || "").trim();

      const venueAddress = venueAddressMap.get(location) || null;
      const notes = [truck ? `Truck: ${truck}` : "", statusText, notesText].filter(Boolean).join(" | ");

      stops.push({
        name: `${location} - ${city}, ${state}`,
        location,
        address: venueAddress,
        city,
        state,
        zip: null,
        date: dateStr,
        time,
        cutoff_date: null,
        status: "active",
        is_public: true,
        notes: notes || null,
      });
    });
  }
  console.log(`Parsed ${stops.length} stops`);
  return { locations, stops };
}

async function seedLocations(locs) {
  if (locs.length === 0) return;
  await sql`DELETE FROM locations WHERE brand_id = ${TUXEDO_BRAND_ID}::uuid`;
  for (const loc of locs) {
    await sql`INSERT INTO locations (brand_id, name, address, city, state, zip, phone, contact_name, contact_email, notes, active)
              VALUES (${TUXEDO_BRAND_ID}::uuid, ${loc.name}, ${loc.address}, ${loc.city}, ${loc.state}, ${loc.zip}, ${loc.phone}, ${loc.contact_name}, ${loc.contact_email}, ${loc.notes}, ${loc.active})`;
  }
  console.log(`Seeded ${locs.length} locations`);
}

async function seedStops(stops) {
  if (stops.length === 0) return;
  const minDate = `${YEAR}-07-01`;
  const maxDate = `${YEAR}-09-30`;
  await sql`DELETE FROM stops WHERE brand_id = ${TUXEDO_BRAND_ID}::uuid AND date >= ${minDate} AND date <= ${maxDate}`;
  for (const stop of stops) {
    await sql`INSERT INTO stops (brand_id, name, location, address, city, state, zip, date, "time", cutoff_date, status, is_public, notes)
              VALUES (${TUXEDO_BRAND_ID}::uuid, ${stop.name}, ${stop.location}, ${stop.address}, ${stop.city}, ${stop.state}, ${stop.zip}, ${stop.date}, ${stop.time}, ${stop.cutoff_date}, ${stop.status}, ${stop.is_public}, ${stop.notes})`;
  }
  console.log(`Seeded ${stops.length} stops`);
}

async function main() {
  const xlsxPath = path.join(__dirname, "..", "Tuxedo_Corn_2026_Tour_Schedule-3.xlsx");
  console.log("Parsing:", xlsxPath);
  const { locations, stops } = await parseXlsx(xlsxPath);
  if (locations.length === 0 && stops.length === 0) {
    console.error("❌ No data parsed from xlsx");
    process.exit(1);
  }
  console.log(`Seeding ${locations.length} locations + ${stops.length} stops for Tuxedo Corn...`);
  await seedLocations(locations);
  await seedStops(stops);
  const locCount = await sql.query(`SELECT COUNT(*) FROM locations WHERE brand_id = '${TUXEDO_BRAND_ID}'`);
  const stopCount = await sql.query(`SELECT COUNT(*) FROM stops WHERE brand_id = '${TUXEDO_BRAND_ID}'`);
  console.log(`\n✅ Done — ${locCount[0].count} locations, ${stopCount[0].count} stops in DB`);
}

main().catch((e) => {
  console.error("❌ Seed failed:", e.message);
  process.exit(1);
});