const express = require("express");
const router = express.Router();
const { query } = require("../db");
const multer = require("multer");

// Configure multer for file uploads
const storage = multer.memoryStorage();
const upload = multer({
  storage,
  limits: { fileSize: 10 * 1024 * 1024 }, // 10MB max
  fileFilter: (req, file, cb) => {
    if (
      file.mimetype === "application/json" ||
      file.originalname.endsWith(".json")
    ) {
      cb(null, true);
    } else {
      cb(new Error("Only JSON files are allowed"), false);
    }
  },
});

// =====================
// EXPORT DATA
// =====================

// Export all songs as JSON
router.get("/export/songs", async (req, res) => {
  try {
    const result = await query("SELECT * FROM songs ORDER BY title");
    res.setHeader("Content-Type", "application/json");
    res.setHeader(
      "Content-Disposition",
      "attachment; filename=songs-export.json",
    );
    res.json({
      success: true,
      exportedAt: new Date().toISOString(),
      count: result.rows.length,
      songs: result.rows,
    });
  } catch (err) {
    console.error("Export songs error:", err);
    res.status(500).json({ success: false, message: "Failed to export songs" });
  }
});

// Export all profiles as JSON
router.get("/export/profiles", async (req, res) => {
  try {
    const result = await query("SELECT * FROM profiles ORDER BY name");
    res.setHeader("Content-Type", "application/json");
    res.setHeader(
      "Content-Disposition",
      "attachment; filename=profiles-export.json",
    );
    res.json({
      success: true,
      exportedAt: new Date().toISOString(),
      count: result.rows.length,
      profiles: result.rows,
    });
  } catch (err) {
    console.error("Export profiles error:", err);
    res
      .status(500)
      .json({ success: false, message: "Failed to export profiles" });
  }
});

// Export all worship lists as JSON
router.get("/export/lists", async (req, res) => {
  try {
    const result = await query(`
      SELECT p.*, 
             COALESCE(json_agg(
               json_build_object(
                 'song_id', ps.song_id,
                 'order_index', ps.order_index,
                 'song_title', s.title
               ) ORDER BY ps.order_index
             ) FILTER (WHERE ps.song_id IS NOT NULL), '[]') as songs
      FROM plans p
      LEFT JOIN plan_songs ps ON p.id = ps.plan_id
      LEFT JOIN songs s ON ps.song_id = s.id
      GROUP BY p.id
      ORDER BY p.date DESC
    `);
    res.setHeader("Content-Type", "application/json");
    res.setHeader(
      "Content-Disposition",
      "attachment; filename=worship-lists-export.json",
    );
    res.json({
      success: true,
      exportedAt: new Date().toISOString(),
      count: result.rows.length,
      lists: result.rows,
    });
  } catch (err) {
    console.error("Export lists error:", err);
    res
      .status(500)
      .json({ success: false, message: "Failed to export worship lists" });
  }
});

// Export everything (full database backup)
router.get("/export/all", async (req, res) => {
  try {
    const [songs, profiles, lists, users] = await Promise.all([
      query("SELECT * FROM songs ORDER BY title"),
      query("SELECT * FROM profiles ORDER BY name"),
      query(`
        SELECT p.*, 
               COALESCE(json_agg(
                 json_build_object(
                   'song_id', ps.song_id,
                   'order_index', ps.order_index
                 ) ORDER BY ps.order_index
               ) FILTER (WHERE ps.song_id IS NOT NULL), '[]') as songs
        FROM plans p
        LEFT JOIN plan_songs ps ON p.id = ps.plan_id
        GROUP BY p.id
        ORDER BY p.date DESC
      `),
      query(
        "SELECT id, username, role, created_at FROM users ORDER BY username",
      ),
    ]);

    res.setHeader("Content-Type", "application/json");
    res.setHeader(
      "Content-Disposition",
      "attachment; filename=full-backup.json",
    );
    res.json({
      success: true,
      exportedAt: new Date().toISOString(),
      data: {
        songs: { count: songs.rows.length, items: songs.rows },
        profiles: { count: profiles.rows.length, items: profiles.rows },
        worshipLists: { count: lists.rows.length, items: lists.rows },
        users: { count: users.rows.length, items: users.rows },
      },
    });
  } catch (err) {
    console.error("Full export error:", err);
    res
      .status(500)
      .json({ success: false, message: "Failed to export database" });
  }
});

// =====================
// IMPORT DATA
// =====================

// Import songs from JSON
router.post("/import/songs", upload.single("file"), async (req, res) => {
  try {
    if (!req.file) {
      return res
        .status(400)
        .json({ success: false, message: "No file uploaded" });
    }

    const data = JSON.parse(req.file.buffer.toString());
    const songs = data.songs || data;

    if (!Array.isArray(songs)) {
      return res
        .status(400)
        .json({
          success: false,
          message: "Invalid format: expected array of songs",
        });
    }

    let imported = 0;
    let skipped = 0;
    const errors = [];

    for (const song of songs) {
      try {
        // Check if song exists by title
        const existing = await query(
          "SELECT id FROM songs WHERE LOWER(title) = LOWER($1)",
          [song.title],
        );

        if (existing.rows.length > 0) {
          skipped++;
          continue;
        }

        await query(
          `INSERT INTO songs (title, artist, lyrics, chords, tempo, time_signature, category, notes)
           VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,
          [
            song.title,
            song.artist || null,
            song.lyrics || "",
            song.chords || song.key_chord || null,
            song.tempo || null,
            song.time_signature || null,
            song.category || null,
            song.notes || null,
          ],
        );
        imported++;
      } catch (err) {
        errors.push({ title: song.title, error: err.message });
      }
    }

    res.json({
      success: true,
      message: `Imported ${imported} songs, skipped ${skipped} duplicates`,
      imported,
      skipped,
      errors: errors.length > 0 ? errors : undefined,
    });
  } catch (err) {
    console.error("Import songs error:", err);
    res
      .status(500)
      .json({
        success: false,
        message: "Failed to import songs: " + err.message,
      });
  }
});

// =====================
// USER MANAGEMENT
// =====================

// Get all users
router.get("/users", async (req, res) => {
  try {
    const result = await query(
      "SELECT id, username, role, created_at FROM users ORDER BY username",
    );
    // Add biometric_enabled as false since column may not exist
    const users = result.rows.map((user) => ({
      ...user,
      biometric_enabled: false,
    }));
    res.json({ success: true, users });
  } catch (err) {
    console.error("Get users error:", err);
    res.status(500).json({ success: false, message: "Failed to fetch users" });
  }
});

// Create new user
router.post("/users", async (req, res) => {
  const { username, password, role = "user" } = req.body;

  if (!username || !password) {
    return res
      .status(400)
      .json({ success: false, message: "Username and password are required" });
  }

  try {
    // Check if username exists
    const existing = await query(
      "SELECT id FROM users WHERE LOWER(username) = LOWER($1)",
      [username],
    );
    if (existing.rows.length > 0) {
      return res
        .status(400)
        .json({ success: false, message: "Username already exists" });
    }

    // Hash password (simple for now - should use bcrypt in production)
    const bcrypt = require("bcrypt");
    const hashedPassword = await bcrypt.hash(password, 10);

    const result = await query(
      `INSERT INTO users (username, password, role) VALUES ($1, $2, $3) RETURNING id, username, role, created_at`,
      [username, hashedPassword, role],
    );

    res.json({ success: true, user: result.rows[0] });
  } catch (err) {
    console.error("Create user error:", err);
    res.status(500).json({ success: false, message: "Failed to create user" });
  }
});

// Update user
router.put("/users/:id", async (req, res) => {
  const { id } = req.params;
  const { username, password, role } = req.body;

  try {
    const updates = [];
    const values = [];
    let paramCount = 1;

    if (username) {
      updates.push(`username = $${paramCount++}`);
      values.push(username);
    }

    if (password) {
      const bcrypt = require("bcrypt");
      const hashedPassword = await bcrypt.hash(password, 10);
      updates.push(`password = $${paramCount++}`);
      values.push(hashedPassword);
    }

    if (role) {
      updates.push(`role = $${paramCount++}`);
      values.push(role);
    }

    if (updates.length === 0) {
      return res
        .status(400)
        .json({ success: false, message: "No updates provided" });
    }

    values.push(id);
    const result = await query(
      `UPDATE users SET ${updates.join(", ")} WHERE id = $${paramCount} 
       RETURNING id, username, role, created_at`,
      values,
    );

    if (result.rows.length === 0) {
      return res
        .status(404)
        .json({ success: false, message: "User not found" });
    }

    res.json({ success: true, user: result.rows[0] });
  } catch (err) {
    console.error("Update user error:", err);
    res.status(500).json({ success: false, message: "Failed to update user" });
  }
});

// Delete user
router.delete("/users/:id", async (req, res) => {
  const { id } = req.params;

  try {
    const result = await query(
      "DELETE FROM users WHERE id = $1 RETURNING id, username",
      [id],
    );

    if (result.rows.length === 0) {
      return res
        .status(404)
        .json({ success: false, message: "User not found" });
    }

    res.json({ success: true, message: "User deleted", user: result.rows[0] });
  } catch (err) {
    console.error("Delete user error:", err);
    res.status(500).json({ success: false, message: "Failed to delete user" });
  }
});

// Enable biometric authentication for user
router.post("/users/:id/biometric", async (req, res) => {
  const { id } = req.params;
  const { enable = true } = req.body;

  try {
    // Check if user exists first
    const userCheck = await query(
      "SELECT id, username FROM users WHERE id = $1",
      [id],
    );

    if (userCheck.rows.length === 0) {
      return res
        .status(404)
        .json({ success: false, message: "User not found" });
    }

    // Note: biometric_enabled column may not exist yet - this is a placeholder
    // In production, you would add the column to the database first
    res.json({
      success: true,
      message: `Biometric authentication ${enable ? "enabled" : "disabled"} (feature pending database migration)`,
      user: { ...userCheck.rows[0], biometric_enabled: enable },
    });
  } catch (err) {
    console.error("Biometric update error:", err);
    res
      .status(500)
      .json({ success: false, message: "Failed to update biometric settings" });
  }
});

// =====================
// SYSTEM SETTINGS
// =====================

// Get system settings
router.get("/settings", async (req, res) => {
  try {
    const result = await query("SELECT * FROM settings ORDER BY key");
    const settings = {};
    result.rows.forEach((row) => {
      settings[row.key] = row.value;
    });
    res.json({ success: true, settings });
  } catch (err) {
    // If settings table doesn't exist, return defaults
    res.json({
      success: true,
      settings: {
        church_name: "House of Prayer",
        default_tempo: "120",
        default_time_signature: "4/4",
        auto_transpose: "false",
        show_chord_diagrams: "true",
      },
    });
  }
});

// Update system setting
router.put("/settings/:key", async (req, res) => {
  const { key } = req.params;
  const { value } = req.body;

  try {
    // Try upsert
    await query(
      `INSERT INTO settings (key, value) VALUES ($1, $2)
       ON CONFLICT (key) DO UPDATE SET value = $2, updated_at = NOW()`,
      [key, value],
    );
    res.json({ success: true, message: "Setting updated" });
  } catch (err) {
    console.error("Update setting error:", err);
    res
      .status(500)
      .json({ success: false, message: "Failed to update setting" });
  }
});

module.exports = router;
