const express = require("express");
const router = express.Router();
const { query } = require("../db");
const { v4: uuidv4 } = require("uuid");
const {
  success,
  error,
  notFound,
  badRequest,
} = require("../utils/responseHandler");
const { authenticate } = require("../middleware/auth");

// Reusable SQL fragments
const SELECT_LIST_WITH_COUNT = `
  SELECT p.*, pr.name as profile_name,
    (SELECT COUNT(*) FROM plan_songs WHERE plan_id = p.id) as song_count
  FROM plans p
  LEFT JOIN profiles pr ON p.profile_id = pr.id
`;

const SELECT_LIST_SONGS = `
  SELECT s.*, s.chords as key_chord, ps.order_index
  FROM songs s
  INNER JOIN plan_songs ps ON s.id = ps.song_id
  WHERE ps.plan_id = $1
  ORDER BY ps.order_index ASC
`;

/**
 * Helper to add songs to a worship list
 */
const addSongsToList = async (planId, songs) => {
  if (!songs || !Array.isArray(songs) || songs.length === 0) return;

  const values = songs
    .map(
      (songId, index) => `('${uuidv4()}', '${planId}', '${songId}', ${index})`,
    )
    .join(", ");

  await query(`
    INSERT INTO plan_songs (id, plan_id, song_id, order_index)
    VALUES ${values}
  `);
};

/**
 * Helper to get next order index for a list
 */
const getNextOrderIndex = async (planId) => {
  const result = await query(
    "SELECT COALESCE(MAX(order_index), -1) + 1 as next_order FROM plan_songs WHERE plan_id = $1",
    [planId],
  );
  return result.rows[0].next_order;
};

// GET all worship lists (plans)
router.get("/", async (req, res) => {
  try {
    const result = await query(`
      ${SELECT_LIST_WITH_COUNT}
      ORDER BY p.date DESC
    `);
    success(res, { lists: result.rows });
  } catch (err) {
    error(res, "Failed to fetch worship lists");
  }
});

// GET single worship list by ID with songs
router.get("/:id", async (req, res) => {
  try {
    const [listResult, songsResult] = await Promise.all([
      query(`${SELECT_LIST_WITH_COUNT} WHERE p.id = $1`, [req.params.id]),
      query(SELECT_LIST_SONGS, [req.params.id]),
    ]);

    if (listResult.rows.length === 0) {
      return notFound(res, "Worship list");
    }

    success(res, {
      list: listResult.rows[0],
      songs: songsResult.rows,
    });
  } catch (err) {
    error(res, "Failed to fetch worship list");
  }
});

// POST create new worship list
router.post("/", authenticate, async (req, res) => {
  try {
    const { date, profile_id, notes, songs } = req.body;

    if (!date) {
      return badRequest(res, "Date is required");
    }

    const id = uuidv4();
    const now = Math.floor(Date.now() / 1000);

    const result = await query(
      `INSERT INTO plans (id, date, profile_id, notes, created_at)
       VALUES ($1, $2, $3, $4, $5)
       RETURNING *`,
      [id, date, profile_id || null, notes || "", now],
    );

    await addSongsToList(id, songs);

    success(res, { list: result.rows[0] }, 201);
  } catch (err) {
    error(res, "Failed to create worship list");
  }
});

// PUT update worship list
router.put("/:id", authenticate, async (req, res) => {
  try {
    const { date, profile_id, notes, songs } = req.body;
    console.log(`[PUT /lists/${req.params.id}] Request:`, {
      date,
      profile_id,
      notes,
      songCount: songs?.length,
      songIds: songs?.slice(0, 3),
    });

    const result = await query(
      `UPDATE plans 
       SET date = COALESCE($1, date),
           profile_id = $2,
           notes = COALESCE($3, notes)
       WHERE id = $4
       RETURNING *`,
      [date, profile_id, notes, req.params.id],
    );

    if (result.rows.length === 0) {
      console.log(`[PUT /lists/${req.params.id}] NOT FOUND`);
      return notFound(res, "Worship list");
    }

    console.log(
      `[PUT /lists/${req.params.id}] Plan updated, now updating songs...`,
    );

    // Update songs if provided
    if (songs && Array.isArray(songs)) {
      await query("DELETE FROM plan_songs WHERE plan_id = $1", [req.params.id]);
      console.log(
        `[PUT /lists/${req.params.id}] Deleted old songs, adding ${songs.length} new songs`,
      );
      await addSongsToList(req.params.id, songs);
      console.log(`[PUT /lists/${req.params.id}] Songs added successfully`);
    }

    console.log(`[PUT /lists/${req.params.id}] SUCCESS`);
    success(res, { list: result.rows[0] });
  } catch (err) {
    console.error(`[PUT /lists/:id] ERROR:`, err.message);
    console.error(err.stack);
    error(res, "Failed to update worship list: " + err.message);
  }
});

// DELETE worship list
router.delete("/:id", authenticate, async (req, res) => {
  try {
    // plan_songs will be deleted via CASCADE
    const result = await query("DELETE FROM plans WHERE id = $1 RETURNING id", [
      req.params.id,
    ]);

    if (result.rows.length === 0) {
      return notFound(res, "Worship list");
    }

    success(res, { message: "Worship list deleted" });
  } catch (err) {
    error(res, "Failed to delete worship list");
  }
});

// POST add song to worship list
router.post("/:id/songs/:songId", authenticate, async (req, res) => {
  try {
    const { id, songId } = req.params;
    const nextOrder = await getNextOrderIndex(id);
    const psId = uuidv4();

    const result = await query(
      `INSERT INTO plan_songs (id, plan_id, song_id, order_index)
       VALUES ($1, $2, $3, $4)
       ON CONFLICT (plan_id, song_id) DO NOTHING
       RETURNING *`,
      [psId, id, songId, nextOrder],
    );

    success(res, {
      message: "Song added to worship list",
      added: result.rowCount > 0,
    });
  } catch (err) {
    error(res, "Failed to add song to worship list", 500, {
      error: err.message,
    });
  }
});

// DELETE remove song from worship list
router.delete("/:id/songs/:songId", authenticate, async (req, res) => {
  try {
    const { id, songId } = req.params;

    const result = await query(
      "DELETE FROM plan_songs WHERE plan_id = $1 AND song_id = $2 RETURNING *",
      [id, songId],
    );

    success(res, {
      message: "Song removed from worship list",
      deleted: result.rowCount,
    });
  } catch (err) {
    error(res, "Failed to remove song from worship list", 500, {
      error: err.message,
    });
  }
});

// PUT reorder songs in worship list
router.put("/:id/reorder", authenticate, async (req, res) => {
  try {
    const { songs } = req.body;

    if (!songs || !Array.isArray(songs)) {
      return badRequest(res, "Songs array is required");
    }

    // Batch update using CASE statement for better performance
    if (songs.length > 0) {
      const cases = songs
        .map((songId, index) => `WHEN song_id = '${songId}' THEN ${index}`)
        .join(" ");

      const songIds = songs.map((id) => `'${id}'`).join(", ");

      await query(
        `
        UPDATE plan_songs
        SET order_index = CASE ${cases} END
        WHERE plan_id = $1 AND song_id IN (${songIds})
      `,
        [req.params.id],
      );
    }

    success(res, { message: "Songs reordered" });
  } catch (err) {
    error(res, "Failed to reorder songs", 500, { error: err.message });
  }
});

// GET worship list count
router.get("/stats/count", async (req, res) => {
  try {
    const result = await query("SELECT COUNT(*) as count FROM plans");
    success(res, { count: parseInt(result.rows[0].count) });
  } catch (err) {
    error(res, "Failed to count worship lists");
  }
});

module.exports = router;
