/**
 * SEED JSON - App Recolección Inteligente
 * Uso: npm run seed
 */

require('dotenv').config();
const { Pool } = require('pg');
const fs   = require('fs');
const path = require('path');

const pool = new Pool({
  host:     process.env.DB_HOST     || 'localhost',
  port:     parseInt(process.env.DB_PORT || '5433'),
  database: process.env.DB_NAME     || 'recoleccion_db',
  user:     process.env.DB_USER     || 'recoleccion',
  password: process.env.DB_PASSWORD || 'recoleccion123',
});

function readJson(filename) {
  const filepath = path.join(__dirname, '..', 'data', filename);
  return JSON.parse(fs.readFileSync(filepath, 'utf-8'));
}

function parseHorario(str) {
  const match = str.match(/^(\w+)\s*\((\d{2}:\d{2})\s*-\s*(\d{2}:\d{2})\)/);
  if (!match) throw new Error(`Horario no reconocido: "${str}"`);
  return { turno: match[1], inicio: match[2], fin: match[3] };
}

async function seed() {
  const client = await pool.connect();

  try {
    await client.query('BEGIN');

    const rutas    = readJson('rutas.json');
    const colonias = readJson('colonias-rutas.json');

    console.log(`\n📦 Sembrando ${rutas.length} rutas...`);

    for (const ruta of rutas) {
      const pos1 = ruta.positions.find(p => p.positionId === 1);
      const pos8 = ruta.positions.find(p => p.positionId === 8);

      const horaInicio = new Date(pos1.timestamp).toISOString().substring(11, 16);
      const horaFin    = new Date(pos8.timestamp).toISOString().substring(11, 16);

      // ── Insertar ruta ──────────────────────────────────────
      const { rows: [rutaRow] } = await client.query(
        `INSERT INTO rutas (route_id, nombre, truck_id, hora_inicio, hora_fin_ref)
         VALUES ($1, $2, $3, $4::TIME, $5::TIME)
         ON CONFLICT (route_id) DO UPDATE
           SET nombre       = EXCLUDED.nombre,
               truck_id     = EXCLUDED.truck_id,
               hora_inicio  = EXCLUDED.hora_inicio,
               hora_fin_ref = EXCLUDED.hora_fin_ref
         RETURNING id`,
        [ruta.routeId, ruta.name, ruta.truckId, horaInicio, horaFin]
      );
      const rutaId = rutaRow.id;

      // ── Estado inicial ─────────────────────────────────────
      await client.query(
        `INSERT INTO estado_ruta (ruta_id, estado, position_id_actual)
         VALUES ($1, 'INACTIVA', 1)
         ON CONFLICT (ruta_id) DO NOTHING`,
        [rutaId]
      );

      // ── Posiciones ─────────────────────────────────────────
      const tsBase = new Date(pos1.timestamp).getTime();

      for (const pos of ruta.positions) {
        const offsetSeg = Math.round((new Date(pos.timestamp).getTime() - tsBase) / 1000);

        // IMPORTANTE: punto va al final ($8) para que los parámetros
        // sean estrictamente secuenciales $1..$8 sin saltos
        const wkt = `SRID=4326;POINT(${pos.lng} ${pos.lat})`;

        await client.query(
          `INSERT INTO ruta_posiciones
               (ruta_id, position_id, lat, lng, speed_kmh, ts_referencia, offset_seg, punto)
           VALUES
               ($1,      $2,          $3,  $4,  $5,        $6::timestamptz,$7,         $8::geography)
           ON CONFLICT (ruta_id, position_id) DO UPDATE
             SET lat           = EXCLUDED.lat,
                 lng           = EXCLUDED.lng,
                 speed_kmh     = EXCLUDED.speed_kmh,
                 ts_referencia = EXCLUDED.ts_referencia,
                 offset_seg    = EXCLUDED.offset_seg,
                 punto         = EXCLUDED.punto`,
          [rutaId, pos.positionId, pos.lat, pos.lng,
           pos.speed, pos.timestamp, offsetSeg, wkt]
        );
      }

      console.log(`  ✓ ${ruta.routeId} — ${ruta.name}`);
    }

    // ── Colonias ───────────────────────────────────────────────
    console.log(`\n🗺️  Sembrando ${colonias.length} colonias...`);

    for (const col of colonias) {
      const { rows: [rutaRow] } = await client.query(
        'SELECT id FROM rutas WHERE route_id = $1',
        [col.routeId]
      );

      if (!rutaRow) {
        console.warn(`  ⚠️  ${col.routeId} no encontrada para "${col.colonia}". Omitida.`);
        continue;
      }

      const h = parseHorario(col.horarioEstimado);

      await client.query(
        `INSERT INTO colonias (nombre, ruta_id, horario_turno, hora_inicio_est, hora_fin_est)
         VALUES ($1, $2, $3, $4::TIME, $5::TIME)
         ON CONFLICT (nombre) DO UPDATE
           SET ruta_id         = EXCLUDED.ruta_id,
               horario_turno   = EXCLUDED.horario_turno,
               hora_inicio_est = EXCLUDED.hora_inicio_est,
               hora_fin_est    = EXCLUDED.hora_fin_est`,
        [col.colonia, rutaRow.id, h.turno, h.inicio, h.fin]
      );

      console.log(`  ✓ ${col.colonia} → ${col.routeId} (${h.turno} ${h.inicio}-${h.fin})`);
    }

    await client.query('COMMIT');
    console.log('\n✅ Seed completado exitosamente.\n');

  } catch (err) {
    await client.query('ROLLBACK');
    console.error('\n❌ Error en el seed, se hizo ROLLBACK:', err.message);
    throw err;
  } finally {
    client.release();
    await pool.end();
  }
}

seed().catch((err) => {
  console.error('💥 Error fatal:', err.message);
  process.exit(1);
});
