const express = require("express");
const { Pool } = require("pg");
const os = require("os");
const multer = require('multer');
const path = require('path');
const fs = require('fs');

const cors = require('cors');
const app = express();
const port = process.env.PORT || 3000;

const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');

const JWT_SECRET = "supergeheimes_tg_cms_secret";

// Bodyparser für JSON aktivieren
app.use(cors({
  origin: ["http://localhost:8080", "http://192.168.50.65:8080"],
  methods: ["GET", "POST", "PUT", "DELETE"],
  credentials: true
}));

app.use(express.json());
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));


// PostgreSQL Verbindung aufbauen
const pool = new Pool({
  user: "tgadmin",
  host: "db", // Docker Container Name!
  database: "tg-cms",
  password: "secretpass",
  port: 5432,
});

// Testroute API-Check
app.get("/api/hello", (req, res) => {
  res.send("Hello World from TG CMS API! 🚀");
});

// Testroute DB-Check
app.get("/api/test-db", async (req, res) => {
  try {
    const result = await pool.query("SELECT NOW()");
    res.json({ time: result.rows[0].now });
  } catch (err) {
    console.error(err);
    res.status(500).send("Fehler bei DB-Verbindung");
  }
});

// Alle News abrufen
app.get("/api/news", async (req, res) => {
  try {
    const result = await pool.query('SELECT * FROM news ORDER BY created_at DESC');
    res.json(result.rows);
  } catch (err) {
    console.error(err);
    res.status(500).send("Fehler beim Abrufen der News");
  }
});

// Neue News anlegen
app.post("/api/news", async (req, res) => {
  const { title, description, image_url, team } = req.body;

  if (!title || !description) {
    return res.status(400).send("Titel und Beschreibung sind Pflichtfelder");
  }

  try {
    const result = await pool.query(
      'INSERT INTO news (title, description, image_url, team) VALUES ($1, $2, $3, $4) RETURNING *',
      [title, description, image_url, team]
    );
    res.status(201).json(result.rows[0]);
  } catch (err) {
    console.error(err);
    res.status(500).send("Fehler beim Anlegen der News");
  }
});

// News bearbeiten
app.put("/api/news/:id", async (req, res) => {
  const { id } = req.params;
  const { title, description, image_url, team } = req.body;

  try {
    const result = await pool.query(
      'UPDATE news SET title = $1, description = $2, image_url = $3, team = $4 WHERE id = $5 RETURNING *',
      [title, description, image_url, team, id]
    );

    if (result.rowCount === 0) {
      return res.status(404).send("News-Eintrag nicht gefunden");
    }

    res.json(result.rows[0]);
  } catch (err) {
    console.error(err);
    res.status(500).send("Fehler beim Aktualisieren der News");
  }
});

// News löschen
app.delete("/api/news/:id", async (req, res) => {
  const { id } = req.params;

  try {
    const result = await pool.query(
      'DELETE FROM news WHERE id = $1',
      [id]
    );

    if (result.rowCount === 0) {
      return res.status(404).send("News-Eintrag nicht gefunden");
    }

    res.send("News-Eintrag erfolgreich gelöscht");
  } catch (err) {
    console.error(err);
    res.status(500).send("Fehler beim Löschen der News");
  }
});

// Neuen Benutzer anlegen
app.post("/api/users", async (req, res) => {
  const { username, password, role, email } = req.body;

  if (!username || !password || !email) {
    return res.status(400).send("Username, Email & Passwort sind Pflicht");
  }

  try {
    // Passwort hashen
    const hashedPassword = await bcrypt.hash(password, 10);

    // In DB speichern
    const result = await pool.query(
      'INSERT INTO users (username, password, role, email) VALUES ($1, $2, $3, $4) RETURNING id, username, role, email, created_at',
      [username, hashedPassword, role ||'user', email]
    );

    res.status(201).json(result.rows[0]);
  } catch (err) {
    console.error(err);
    res.status(500).send("Fehler beim Anlegen des Benutzers");
  }
});

// Benutzer Login
app.post("/api/login", async (req, res) => {
  const { username, password } = req.body;

  if (!username || !password) {
    return res.status(400).send("Username und Passwort erforderlich");
  }

  try {
    const result = await pool.query(
      'SELECT * FROM users WHERE username = $1',
      [username]
    );

    const user = result.rows[0];

    if (!user) {
      return res.status(400).send("Benutzer existiert nicht");
    }

    // Passwort prüfen
    const validPassword = await bcrypt.compare(password, user.password);

    if (!validPassword) {
      return res.status(401).send("Passwort falsch");
    }

    await pool.query(
      'UPDATE users SET last_logged = NOW() WHERE id = $1',
      [user.id]
    );

    // JWT Token erzeugen
    const token = jwt.sign(
      { id: user.id, username: user.username, role: user.role },
      JWT_SECRET,
      { expiresIn: "6h" }
    );

    res.json({ token });
  } catch (err) {
    console.error(err);
    res.status(500).send("Fehler beim Login");
  }
});


// Alle Benutzer abrufen
app.get("/api/users", async (req, res) => {
  try {
    const result = await pool.query(
      'SELECT id, username, role, email, created_at FROM users ORDER BY created_at DESC'
    );
    res.json(result.rows);
  } catch (err) {
    console.error(err);
    res.status(500).send("Fehler beim Abrufen der Benutzer");
  }
});

// Benutzer l�loeschen
app.delete("/api/users/:id", async (req, res) => {
  const { id } = req.params;

  try {
    // Prüfen, ob der Benutzer existiert
    const checkResult = await pool.query('SELECT * FROM users WHERE id = $1', [id]);
    if (checkResult.rowCount === 0) {
      return res.status(404).send("Benutzer nicht gefunden");
    }

    // Benutzer löschen
    await pool.query('DELETE FROM users WHERE id = $1', [id]);

    res.send("Benutzer erfolgreich gelöscht");
  } catch (err) {
    console.error(err);
    res.status(500).send("Fehler beim Löschen des Benutzers");
  }
});

// Benutzer bearbeiten
app.put("/api/users/:id", async (req, res) => {
  const { id } = req.params;
  const { username, password, role } = req.body;

  try {
    // Passwort optional neu setzen
    let query = 'UPDATE users SET username = $1, role = $2';
    let params = [username, role, id];

    if (password) {
      const hashedPassword = await bcrypt.hash(password, 10);
      query = 'UPDATE users SET username = $1, password = $2, role = $3 WHERE id = $4';
      params = [username, hashedPassword, role, id];
    } else {
      query += ' WHERE id = $3';
    }

    const result = await pool.query(query, params);

    if (result.rowCount === 0) {
      return res.status(404).send("Benutzer nicht gefunden");
    }

    res.send("Benutzer erfolgreich aktualisiert");
  } catch (err) {
    console.error(err);
    res.status(500).send("Fehler beim Aktualisieren des Benutzers");
  }
});


// Speicherort definieren
const newsStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    const dir = "./uploads/news";
    fs.mkdirSync(dir, { recursive: true });
    cb(null, dir);
  },
  filename: (req, file, cb) => {
    const ext = path.extname(file.originalname);
    const filename = Date.now() + ext;
    cb(null, filename);
  },
});

const playerStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    const dir = "./uploads/players";
    fs.mkdirSync(dir, { recursive: true });
    cb(null, dir);
  },
  filename: (req, file, cb) => {
    const ext = path.extname(file.originalname);
    const filename = Date.now() + ext;
    cb(null, filename);
  },
});

const uploadNewsImage = multer({ storage: newsStorage });
const uploadPlayerImage = multer({ storage: playerStorage });





//Neues Bild zu den News hinzufügen
app.post("/api/upload-news-image", uploadNewsImage.single("image"), (req, res) => {
  if (!req.file) {
    return res.status(400).send("Kein Bild hochgeladen");
  }
  const imageUrl = `/uploads/news/${req.file.filename}`;
  res.json({ imageUrl });
});


//Teams abfragen
app.get("/api/teams", async (req, res) => {
  try {
    const result = await pool.query(`
      SELECT
        t.id,
        t.name,
        t.liga,
        t.sucht_spieler,
        t.social_media,
        t.trainer_name,
        t.karussell_bilder, -- 👉 Hier angepasst!
        COUNT(pt.player_id) AS player_count
      FROM teams t
      LEFT JOIN player_teams pt ON pt.team_id = t.id
      GROUP BY
        t.id,
        t.name,
        t.liga,
        t.sucht_spieler,
        t.social_media,
        t.trainer_name,
        t.karussell_bilder -- 👉 Hier auch
      ORDER BY t.name ASC
    `);
    res.json(result.rows);
  } catch (err) {
    console.error("Fehler beim Abrufen der Teams:", err);
    res.status(500).send("Fehler beim Abrufen der Teams");
  }
});


// Team aktualisieren
app.put("/api/teams/:id", async (req, res) => {
  const { id } = req.params;
  const {
    name,
    liga,
    sucht_spieler,
    social_media,
    karussell_bilder,
    trainer_name,
    trainingszeiten,
    trainingsort,
    kontakt_name,
    kontakt_email,
    teamfarben,
    beschreibung,
    tabellenlink
  } = req.body;

  try {
    const result = await pool.query(
      `UPDATE teams SET
        name = $1,
        liga = $2,
        sucht_spieler = $3,
        social_media = $4,
        karussell_bilder = $5,
        trainer_name = $6,
        trainingszeiten = $7,
        trainingsort = $8,
        kontakt_name = $9,
        kontakt_email = $10,
        teamfarben = $11,
        beschreibung = $12,
        tabellenlink = $13
      WHERE id = $14
      RETURNING *`,
      [
        name,
        liga,
        sucht_spieler,
        social_media,
        karussell_bilder,
        trainer_name,
        trainingszeiten,
        trainingsort,
        kontakt_name,
        kontakt_email,
        teamfarben,
        beschreibung,
        tabellenlink,
        id
      ]
    );

    if (result.rowCount === 0) {
      return res.status(404).send("Team nicht gefunden");
    }

    res.json(result.rows[0]);
  } catch (err) {
    console.error("Fehler beim Aktualisieren des Teams:", err);
    res.status(500).send("Fehler beim Aktualisieren des Teams");
  }
});





//Teams anlegen
app.post("/api/teams", async (req, res) => {
  const {
    name,
    liga,
    sucht_spieler,
    social_media,
    karussell_bilder,
    trainer_name,
    trainingszeiten,
    trainingsort,
    kontakt_name,
    kontakt_email,
    teamfarben,
    beschreibung,
    tabellenlink
  } = req.body;

  if (!name) return res.status(400).send("Teamname ist erforderlich");

  try {
    const result = await pool.query(
      `INSERT INTO teams (
        name, liga, sucht_spieler, social_media, karussell_bilder,
        trainer_name, trainingszeiten, trainingsort, kontakt_name,
        kontakt_email, teamfarben, beschreibung, tabellenlink
      ) VALUES (
        $1, $2, $3, $4, $5,
        $6, $7, $8, $9,
        $10, $11, $12, $13
      ) RETURNING *`,
      [
        name,
        liga,
        sucht_spieler,
        social_media,
        karussell_bilder,
        trainer_name,
        trainingszeiten,
        trainingsort,
        kontakt_name,
        kontakt_email,
        teamfarben,
        beschreibung,
        tabellenlink
      ]
    );

    res.status(201).json(result.rows[0]);
  } catch (err) {
    console.error("Fehler beim Anlegen des Teams:", err);
    res.status(500).send("Fehler beim Anlegen des Teams");
  }
});



//Team loeschen
app.delete("/api/teams/:id", async (req, res) => {
  const { id } = req.params;

  try {
    const result = await pool.query("DELETE FROM teams WHERE id = $1", [id]);

    if (result.rowCount === 0) {
      return res.status(404).send("Team nicht gefunden");
    }

    res.send("Team gelöscht");
  } catch (err) {
    console.error("Fehler beim Löschen:", err);
    res.status(500).send("Fehler beim Löschen");
  }
});


//Spieler anlegen
app.post("/api/players", async (req, res) => {
  const { name, nickname, birthdate, position, jersey_number, favorite_food, image_url, status, team_ids } = req.body;

  if (!name || !position) {
    return res.status(400).send("Name und Position sind Pflichtfelder");
  }

  const client = await pool.connect();
  try {
    await client.query("BEGIN");

    const result = await client.query(
      `INSERT INTO players (name, nickname, birthdate, position, jersey_number, favorite_food, image_url, status)
       VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id`,
      [name, nickname, birthdate, position, jersey_number, favorite_food, image_url, status || "aktiv"]
    );

    const playerId = result.rows[0].id;

    if (team_ids && team_ids.length > 0) {
      const teamInsert = team_ids.map((teamId) => `(${playerId}, ${teamId})`).join(",");
      await client.query(`INSERT INTO player_teams (player_id, team_id) VALUES ${teamInsert}`);
    }

    await client.query("COMMIT");
    res.status(201).json({ id: playerId });
  } catch (err) {
    await client.query("ROLLBACK");
    console.error("Fehler beim Anlegen des Spielers:", err);
    res.status(500).send("Fehler beim Anlegen des Spielers");
  } finally {
    client.release();
  }
});


// Einzelnes Team inkl. Metadaten + Spieler laden
app.get("/api/teams/:id", async (req, res) => {
  const { id } = req.params;

  try {
    // Team-Daten holen
    const teamResult = await pool.query(
      `SELECT
        id,
        name,
        liga,
        sucht_spieler,
        social_media,
        trainer_name,
        karussell_bilder,
        trainingszeiten,
        trainingsort,
        kontakt_name,
        kontakt_email,
        teamfarben,
        beschreibung,
        tabellenlink
      FROM teams
      WHERE id = $1`,
      [id]
    );

    if (teamResult.rowCount === 0) {
      return res.status(404).send("Team nicht gefunden");
    }

    // Spieler für dieses Team holen
    const playerResult = await pool.query(`
      SELECT
        p.id,
        p.name,
        p.nickname,
        p.position,
        p.jersey_number,
        p.image_url
      FROM players p
      INNER JOIN player_teams pt ON p.id = pt.player_id
      WHERE pt.team_id = $1
      ORDER BY p.name ASC
    `, [id]);

    res.json({
      ...teamResult.rows[0],
      players: playerResult.rows,
    });
  } catch (err) {
    console.error("Fehler beim Laden des Teams:", err);
    res.status(500).send("Fehler beim Laden des Teams");
  }
});




//Alle Spieler abrufen
app.get("/api/players", async (req, res) => {
  try {
    const result = await pool.query("SELECT * FROM players ORDER BY name ASC");
    res.json(result.rows);
  } catch (err) {
    console.error("Fehler beim Abrufen der Spieler:", err);
    res.status(500).send("Fehler beim Abrufen der Spieler");
  }
});


//Upload Player Image
app.post("/api/upload-player-image", uploadPlayerImage.single("image"), (req, res) => {
  if (!req.file) {
    return res.status(400).send("Kein Bild hochgeladen");
  }
  const imageUrl = `/uploads/players/${req.file.filename}`;
  res.json({ imageUrl });
});


//Spieler bearbeiten
// Spieler aktualisieren
app.put("/api/players/:id", async (req, res) => {
  const { id } = req.params;
  const {
    name,
    nickname,
    birthdate,
    position,
    jersey_number,
    favorite_food,
    status,
    image_url,
  } = req.body;

  if (!name || !position) {
    return res.status(400).send("Name und Position sind Pflichtfelder");
  }

  try {
    const result = await pool.query(
      `UPDATE players 
       SET 
         name = $1,
         nickname = $2,
         birthdate = $3,
         position = $4,
         jersey_number = $5,
         favorite_food = $6,
         status = $7,
         image_url = $8
       WHERE id = $9
       RETURNING *`,
      [
        name,
        nickname || null,
        birthdate || null,
        position,
        jersey_number ? Number(jersey_number) : null,
        favorite_food || null,
        status || "aktiv",
        image_url || null,
        id,
      ]
    );

    if (result.rowCount === 0) {
      return res.status(404).send("Spieler nicht gefunden");
    }

    res.json(result.rows[0]);
  } catch (err) {
    console.error("Fehler beim Aktualisieren des Spielers:", err);
    res.status(500).send("Fehler beim Aktualisieren des Spielers");
  }
});


//Einzelnen Spieler abrufen
app.get("/api/players/:id", async (req, res) => {
  const { id } = req.params;

  try {
    const result = await pool.query(
      "SELECT * FROM players WHERE id = $1",
      [id]
    );

    if (result.rowCount === 0) {
      return res.status(404).send("Spieler nicht gefunden");
    }

    const player = result.rows[0];

    // 🔥 Team-IDs abfragen
    const teamResult = await pool.query(
      "SELECT team_id FROM player_teams WHERE player_id = $1",
      [id]
    );

    const team_ids = teamResult.rows.map(r => r.team_id);

    res.json({ ...player, team_ids });
  } catch (err) {
    console.error("Fehler beim Abrufen des Spielers:", err);
    res.status(500).send("Fehler beim Abrufen des Spielers");
  }
});



// Spieler aus einem Team entfernen
app.delete("/api/teams/:teamId/players/:playerId", async (req, res) => {
  const { teamId, playerId } = req.params;

  try {
    const result = await pool.query(
      "DELETE FROM player_teams WHERE team_id = $1 AND player_id = $2",
      [teamId, playerId]
    );

    if (result.rowCount === 0) {
      return res.status(404).send("Spieler nicht im Team gefunden");
    }

    res.send("Spieler erfolgreich aus dem Team entfernt");
  } catch (err) {
    console.error("Fehler beim Entfernen des Spielers:", err);
    res.status(500).send("Fehler beim Entfernen des Spielers");
  }
});


// Existierenden Spieler einem Team hinzufügen
app.post("/api/teams/:teamId/players", async (req, res) => {
  const { teamId } = req.params;
  const { playerId } = req.body;

  if (!playerId) {
    return res.status(400).send("playerId ist erforderlich");
  }

  try {
    const result = await pool.query(
      "INSERT INTO player_teams (player_id, team_id) VALUES ($1, $2)",
      [playerId, teamId]
    );
    res.status(201).send("Spieler erfolgreich dem Team zugeordnet");
  } catch (err) {
    if (err.code === "23505") {
      return res.status(400).send("Spieler ist bereits im Team");
    }
    console.error("Fehler beim Hinzufügen des Spielers zum Team:", err);
    res.status(500).send("Fehler beim Hinzufügen des Spielers");
  }
});


// Alle Teams abrufen
app.get("/api/all-teams", async (req, res) => {
  try {
    const result = await pool.query("SELECT id, name FROM teams ORDER BY name ASC");
    res.json(result.rows);
  } catch (err) {
    console.error("Fehler beim Laden der Teams:", err);
    res.status(500).send("Fehler beim Laden der Teams");
  }
});

//Spieler einem Team zuweisen
app.post("/api/players/:id/assign-team", async (req, res) => {
  const { id } = req.params;
  const { team_id } = req.body;

  if (!team_id) return res.status(400).send("team_id erforderlich");

  try {
    await pool.query("DELETE FROM player_teams WHERE player_id = $1", [id]);
    await pool.query("INSERT INTO player_teams (player_id, team_id) VALUES ($1, $2)", [id, team_id]);

    res.send("Teamzugehörigkeit aktualisiert");
  } catch (err) {
    console.error("Fehler beim Aktualisieren der Teamzugehörigkeit:", err);
    res.status(500).send("Fehler beim Aktualisieren");
  }
});


//Carousell Bilder für Teams hochladen
const multer = require("multer");
const path = require("path");

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "uploads/carousel");
  },
  filename: function (req, file, cb) {
    const uniqueName = Date.now() + "-" + file.originalname;
    cb(null, uniqueName);
  },
});

const upload = multer({ storage });

router.post("/api/teams/:id/carousel-upload", upload.single("image"), (req, res) => {
  if (!req.file) return res.status(400).json({ error: "Keine Datei hochgeladen" });

  // z. B. /uploads/carousel/171654543-name.jpg
  const filePath = `/uploads/carousel/${req.file.filename}`;
  res.json({ path: filePath });
});



// Server starten
app.listen(port, () => {
  const nets = os.networkInterfaces();
  const addresses = [];

  for (const name of Object.keys(nets)) {
    for (const net of nets[name]) {
      if (net.family === 'IPv4' && !net.internal) {
        addresses.push(net.address);
      }
    }
  }

  console.log("Backend erreichbar unter:");
  addresses.forEach(ip => {
    console.log(`http://${ip}:${port}`);
  });
});
