const express = require("express");
const pool = require("../db"); // PostgreSQL-Datenbankverbindung
const { requireAuth, requireRole } = require("../middleware/auth"); // Auth-Middleware

const router = express.Router();

// **Trainings abrufen (mit Geräten & Leitern)**
router.get(
  "/:key1?/:value1?/:key2?/:value2?",
  requireAuth,
  async (req, res) => {
    const { key1, value1, key2, value2 } = req.params;
    let result;
    try {
      if (key1 === "year") {
        const year = value1;

        if (key2 && key2 === "kw") {
          const kw = value2;
          const abteilung = req.abteilung; // Abteilung aus Middleware

          if (!abteilung) {
            return res
              .status(400)
              .json({ error: "Abteilung ist erforderlich" });
          }

          let query;
          let values = [abteilung];

          if (year && kw) {
            // **Trainings einer bestimmten Woche abrufen**
            query = `
                SELECT * FROM trainings 
                WHERE abteilung = $1 AND year = $2 AND kw = $3
                ORDER BY year DESC, kw DESC
            `;
            values.push(year, kw);
          } else if (year) {
            // **Alle Trainings eines yeares abrufen**
            query = `
                SELECT * FROM trainings 
                WHERE abteilung = $1 AND year = $2
                ORDER BY kw ASC
            `;
            values.push(year);
          } else {
            // **Alle Trainings der Abteilung abrufen**
            query = `
                SELECT * FROM trainings 
                WHERE abteilung = $1
                ORDER BY year DESC, kw DESC
            `;
          }
          result = await pool.query(query, values);
        }

        if (result.rows.length === 0) {
          return res.status(404).json({ error: "Keine Trainings gefunden" });
        }

        return res.json(result.rows);
      } else if (key1 === "geraete") {
        id = value1;
        if (value1) {
          try {
            const result = await pool.query(
              `
      SELECT
        i AS riege_nr,
        'Riege ' || i AS riege_name,
        g.name AS geraet
      FROM (
        SELECT geraete[i] AS id, i
        FROM geraeteplan, generate_subscripts(geraete, 1) AS i
        WHERE fid_training = $1
      ) AS gp
      JOIN Geraete g ON g.id = gp.id
      ORDER BY i
      `,
              [id]
            );

            const geraeteArray = result.rows.map((row) => ({
              riege: row.riege_name,
              geraet: row.geraet,
              nr: row.riege_nr,
            }));

            res.json(geraeteArray);
          } catch (err) {
            console.error("Fehler beim Abrufen des Geräteplans:", err);
            res
              .status(500)
              .json({ error: "Fehler beim Abrufen des Geräteplans" });
          }
        } else {
          res.status(400).json({ error: "TrainingsID muss übergeben werden" });
        }
      }
    } catch (err) {
      console.error(err);
      res.status(500).json({ error: "Interner Serverfehler" });
    }
  }
);

router.post("/leiten/:id", requireAuth, requireRole(3), async (req, res) => {
  const { id } = req.params; // Trainings-ID
  const abteilung = req.abteilung; // Abteilung aus Middleware
  const { fid_helfer, fid_spiel, typ, action } = req.body; // Daten aus POST-Body

  if (!action || !["new", "update"].includes(action)) {
    return res.status(400).json({
      error: 'Es muss "new" oder "update" als action angegeben werden',
    });
  }
  if (!fid_helfer || !typ) {
    return res
      .status(400)
      .json({ error: "fid_helfer und typ sind erforderlich" });
  }
  if (typ !== "a" && typ !== "s") {
    return res
      .status(400)
      .json({ error: 'Typ muss "a" (Aufwärmen) oder "s" (Spiel) sein' });
  }

  try {
    if (action === "new") {
      // **Neuen Eintrag erstellen**
      const result = await pool.query(
        `INSERT INTO leiten (fid_training, fid_helfer, fid_spiel, typ) 
                 VALUES ($1, $2, $3, $4) 
                 RETURNING *`,
        [id, fid_helfer, fid_spiel || null, typ]
      );

      return res.status(201).json({
        message: "Leiten erfolgreich hinzugefügt",
        leiten: result.rows[0],
      });
    } else {
      // **Vorhandenen Eintrag aktualisieren**
      const checkLeiten = await pool.query(
        `SELECT * FROM leiten WHERE fid_training = $1 AND fid_helfer = $2 AND typ = $3`,
        [id, fid_helfer, typ]
      );

      if (checkLeiten.rows.length === 0) {
        return res
          .status(404)
          .json({ error: "Kein passender Leiten-Eintrag gefunden" });
      }

      const updateResult = await pool.query(
        `UPDATE leiten 
                 SET fid_spiel = $1 
                 WHERE fid_training = $2 AND fid_helfer = $3 AND typ = $4 
                 RETURNING *`,
        [fid_spiel || null, id, fid_helfer, typ]
      );

      return res.json({
        message: "Leiten erfolgreich aktualisiert",
        leiten: updateResult.rows[0],
      });
    }
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: "Interner Serverfehler" });
  }
});

router.post("/new/:jahr/:kw", requireAuth, requireRole(2), async (req, res) => {
  const { jahr, kw } = req.params;
  const abteilung = req.abteilung; // Abteilung aus Middleware

  if (!abteilung) {
    return res.status(400).json({ error: "Abteilung ist erforderlich" });
  }

  try {
    await pool.query("BEGIN"); // Transaktion starten

    // **1. Prüfen, ob bereits ein Training in dieser Woche existiert**
    const existingTraining = await pool.query(
      `SELECT id FROM trainings WHERE year = $1 AND kw = $2 AND abteilung = $3`,
      [jahr, kw, abteilung]
    );

    if (existingTraining.rows.length > 0) {
      await pool.query("ROLLBACK");
      return res
        .status(400)
        .json({ error: "Training für diese Woche existiert bereits" });
    }

    // **2. Prüfen, ob die Abteilung Riegen hat**
    const abteilungResult = await pool.query(
      `SELECT riegen, geraete FROM abteilungen WHERE id = $1`,
      [abteilung]
    );

    if (abteilungResult.rows.length === 0) {
      return res.status(404).json({ error: "Abteilung nicht gefunden" });
    }

    const { riegen, geraete } = abteilungResult.rows[0]; // `riegen = true/false`, `geraete` = int[]

    // **3. Neues Training anlegen**
    const trainingResult = await pool.query(
      `INSERT INTO trainings (year, kw, abteilung) VALUES ($1, $2, $3) RETURNING id`,
      [jahr, kw, abteilung]
    );

    const trainingId = trainingResult.rows[0].id;

    let geraeteplan = [];

    if (riegen) {
      // **4. Die letzten zwei Trainings abrufen**
      const lastTrainings = await pool.query(
        `SELECT g.geraete 
                 FROM trainings t
                 JOIN geraeteplan g ON t.id = g.fid_training
                 WHERE t.abteilung = $1 
                 ORDER BY t.year DESC, t.kw DESC 
                 LIMIT 2`,
        [abteilung]
      );

      let lastUsed1 =
        lastTrainings.rows.length > 0 ? lastTrainings.rows[0].geraete : [];
      let lastUsed2 =
        lastTrainings.rows.length > 1 ? lastTrainings.rows[1].geraete : [];

      // **5. Falls eines der letzten beiden Trainings Geräte 11–13 enthielt → Letztes gültiges Training nehmen**
      if (lastUsed1.some((g) => g >= 11 && g <= 13)) {
        lastUsed1 = [];
      }
      if (lastUsed2.some((g) => g >= 11 && g <= 13)) {
        lastUsed2 = [];
      }

      // **6. Bestimmen, ob hochgezählt werden soll**
      let nextGeraete = [];

      if (
        lastUsed1.length > 0 &&
        JSON.stringify(lastUsed1) === JSON.stringify(lastUsed2)
      ) {
        // Hochzählen, weil die letzten beiden Trainings identisch waren
        let lastDeviceIndex = geraete.findIndex((g) => g === lastUsed1[0]);

        // Falls letztes Gerät 10 war, dann zurück auf 1
        let nextDevice = geraete[(lastDeviceIndex + 1) % geraete.length];
        if (lastUsed1[0] === 10) {
          nextDevice = 1;
        }

        nextGeraete = [nextDevice, ...lastUsed1.slice(0, 4)];
      } else if (lastUsed1.length > 0) {
        // Letztes Training wiederholen
        nextGeraete = lastUsed1;
      } else {
        // Erstes Training → Starte mit den ersten fünf Geräten
        nextGeraete = geraete.slice(0, 5);
      }

      // **7. Geräteplan speichern als int[]**
      await pool.query(
        `INSERT INTO geraeteplan (fid_training, geraete) VALUES ($1, $2)`,
        [trainingId, nextGeraete]
      );

      geraeteplan = nextGeraete;
    }

    await pool.query("COMMIT"); // Transaktion abschließen

    res.status(201).json({
      message: "Training erfolgreich erstellt",
      training: { id: trainingId, year: jahr, kw, abteilung },
      geraeteplan,
    });
  } catch (err) {
    await pool.query("ROLLBACK"); // Falls Fehler, Transaktion rückgängig machen
    console.error(err);
    res.status(500).json({ error: "Interner Serverfehler" });
  }
});

module.exports = router;
