import { Router } from 'express';
import db from '../db.js';
import { authMiddleware } from '../middleware/auth.js';
import { sendMail, buildCardNotificationHtml, buildCardUrl, getEmailConfig } from '../email/transporter.js';
import { v4 as uuidv4 } from 'uuid';

const router = Router();
router.use(authMiddleware);

function canAccessCard(userId, cardId) {
  const card = db.prepare(`
    SELECT 1 FROM cards c
    JOIN lists l ON l.id = c.list_id
    JOIN board_members bm ON bm.board_id = l.board_id AND bm.user_id = ?
    WHERE c.id = ?
  `).get(userId, cardId);
  return !!card;
}

function getBoardIdForCard(cardId) {
  const r = db.prepare(`SELECT l.board_id FROM cards c JOIN lists l ON l.id = c.list_id WHERE c.id = ?`).get(cardId);
  return r?.board_id;
}

async function notifyCard({ cardId, userId, action, comment }) {
  const card = db.prepare(`
    SELECT c.*, l.board_id, b.title as board_title,
      u.name as user_name, u2.email as assignee_email, u2.name as assignee_name
    FROM cards c
    JOIN lists l ON l.id = c.list_id
    JOIN boards b ON b.id = l.board_id
    LEFT JOIN users u ON u.id = ?
    LEFT JOIN users u2 ON u2.id = c.assigned_to
    WHERE c.id = ?
  `).get(userId, cardId);
  if (!card || !card.assignee_email) return;
  if (card.assigned_to === userId) return;
  const config = getEmailConfig();
  if (!config) return;
  const token = uuidv4();
  db.prepare('INSERT INTO email_tokens (card_id, user_id, token, expires_at) VALUES (?, ?, ?, datetime("now", "+30 days"))')
    .run(cardId, card.assigned_to, token);
  db.prepare(`INSERT INTO notifications (user_id, type, title, message, card_id, board_id) VALUES (?, ?, ?, ?, ?, ?)`)
    .run(card.assigned_to, action, card.title, `${card.user_name} ${action}`, cardId, card.board_id);
  try {
    await sendMail({
      to: card.assignee_email,
      subject: `[TeamFlow] ${card.user_name} ${action} — ${card.title}`,
      html: buildCardNotificationHtml({
        userName: card.user_name,
        boardTitle: card.board_title,
        cardTitle: card.title,
        action,
        cardUrl: buildCardUrl(cardId, card.board_id),
        comment,
      }),
      replyTo: config.email,
    });
  } catch {}
}

// Lists
router.post('/:boardId/lists', (req, res) => {
  const { title, position } = req.body;
  if (!title) return res.status(400).json({ error: 'Title required' });
  const maxPos = db.prepare('SELECT MAX(position) as p FROM lists WHERE board_id = ?').get(req.params.boardId);
  const result = db.prepare('INSERT INTO lists (board_id, title, position) VALUES (?, ?, ?)')
    .run(req.params.boardId, title, position ?? (maxPos.p || 0) + 65536);
  const list = db.prepare('SELECT * FROM lists WHERE id = ?').get(result.lastInsertRowid);
  res.json(list);
});

router.put('/lists/:id/reorder', (req, res) => {
  const { position } = req.body;
  db.prepare('UPDATE lists SET position = ? WHERE id = ?').run(position, req.params.id);
  res.json({ success: true });
});

router.put('/lists/:id', (req, res) => {
  const { title, is_archived } = req.body;
  if (title !== undefined) db.prepare('UPDATE lists SET title = ? WHERE id = ?').run(title, req.params.id);
  if (is_archived !== undefined) db.prepare('UPDATE lists SET is_archived = ? WHERE id = ?').run(is_archived ? 1 : 0, req.params.id);
  res.json({ success: true });
});

// Cards
router.post('/lists/:listId/cards', async (req, res) => {
  const { title, description, due_date, priority, assigned_to, labels } = req.body;
  if (!title) return res.status(400).json({ error: 'Title required' });
  const maxPos = db.prepare('SELECT MAX(position) as p FROM cards WHERE list_id = ?').get(req.params.listId);
  const result = db.prepare('INSERT INTO cards (list_id, title, description, position, due_date, priority, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)')
    .run(req.params.listId, title, description || '', (maxPos.p || 0) + 65536, due_date || null, priority || 'none', assigned_to || null, req.user.id);
  if (labels?.length) {
    const ins = db.prepare('INSERT OR IGNORE INTO card_labels (card_id, label_id) VALUES (?, ?)');
    labels.forEach(lid => ins.run(result.lastInsertRowid, lid));
  }
  db.prepare('INSERT INTO card_activity (card_id, user_id, action) VALUES (?, ?, ?)').run(result.lastInsertRowid, req.user.id, 'created');
  const card = db.prepare('SELECT c.*, u.name as creator_name FROM cards c LEFT JOIN users u ON u.id = c.created_by WHERE c.id = ?').get(result.lastInsertRowid);
  if (assigned_to) notifyCard({ cardId: result.lastInsertRowid, userId: req.user.id, action: 'assigned you to a card' });
  res.json(card);
});

router.get('/cards/:id', (req, res) => {
  if (!canAccessCard(req.user.id, req.params.id)) return res.status(403).json({ error: 'Access denied' });
  const card = db.prepare(`
    SELECT c.*, u1.name as creator_name, u2.name as assignee_name, u2.avatar_color as assignee_color
    FROM cards c
    LEFT JOIN users u1 ON u1.id = c.created_by
    LEFT JOIN users u2 ON u2.id = c.assigned_to
    WHERE c.id = ?
  `).get(req.params.id);
  const labels = db.prepare(`SELECT l.* FROM card_labels cl JOIN labels l ON l.id = cl.label_id WHERE cl.card_id = ?`).all(req.params.id);
  const comments = db.prepare(`
    SELECT cc.*, u.name, u.avatar_color FROM card_comments cc
    LEFT JOIN users u ON u.id = cc.user_id WHERE cc.card_id = ? ORDER BY cc.created_at
  `).all(req.params.id);
  const activity = db.prepare(`
    SELECT ca.*, u.name, u.avatar_color FROM card_activity ca
    LEFT JOIN users u ON u.id = ca.user_id WHERE ca.card_id = ? ORDER BY ca.created_at DESC LIMIT 50
  `).all(req.params.id);
  const checklists = db.prepare(`
    SELECT cl.*, 
      (SELECT COUNT(*) FROM checklist_items WHERE checklist_id = cl.id) as total_items,
      (SELECT COUNT(*) FROM checklist_items WHERE checklist_id = cl.id AND is_checked = 1) as done_items
    FROM checklists cl WHERE cl.card_id = ? ORDER BY cl.position
  `).all(req.params.id);
  const checklistItems = {};
  for (const cl of checklists) {
    checklistItems[cl.id] = db.prepare('SELECT * FROM checklist_items WHERE checklist_id = ? ORDER BY position').all(cl.id);
  }
  res.json({ ...card, labels, comments, activity, checklists, checklistItems });
});

router.put('/cards/:id', async (req, res) => {
  if (!canAccessCard(req.user.id, req.params.id)) return res.status(403).json({ error: 'Access denied' });
  const { title, description, due_date, priority, color, assigned_to, list_id, position, estimated_hours, time_spent } = req.body;
  const old = db.prepare('SELECT * FROM cards WHERE id = ?').get(req.params.id);
  if (!old) return res.status(404).json({ error: 'Not found' });

  const updates = [];
  const params = [];
  if (title !== undefined) { updates.push('title = ?'); params.push(title); }
  if (description !== undefined) { updates.push('description = ?'); params.push(description); }
  if (due_date !== undefined) { updates.push('due_date = ?'); params.push(due_date); }
  if (priority !== undefined) { updates.push('priority = ?'); params.push(priority); }
  if (color !== undefined) { updates.push('color = ?'); params.push(color); }
  if (assigned_to !== undefined) { updates.push('assigned_to = ?'); params.push(assigned_to); }
  if (list_id !== undefined) { updates.push('list_id = ?'); params.push(list_id); }
  if (position !== undefined) { updates.push('position = ?'); params.push(position); }
  if (estimated_hours !== undefined) { updates.push('estimated_hours = ?'); params.push(estimated_hours); }
  if (time_spent !== undefined) { updates.push('time_spent = ?'); params.push(time_spent); }
  updates.push("updated_at = datetime('now')");
  params.push(req.params.id);

  if (updates.length > 1) {
    db.prepare(`UPDATE cards SET ${updates.join(', ')} WHERE id = ?`).run(...params);
  }

  if (assigned_to && assigned_to !== old.assigned_to) {
    db.prepare('INSERT INTO card_activity (card_id, user_id, action, details) VALUES (?, ?, ?, ?)')
      .run(req.params.id, req.user.id, 'assigned', `Assigned to ${assigned_to}`);
    notifyCard({ cardId: req.params.id, userId: req.user.id, action: 'assigned you to a card' });
  }
  if (list_id && list_id !== old.list_id) {
    const newList = db.prepare('SELECT title FROM lists WHERE id = ?').get(list_id);
    db.prepare('INSERT INTO card_activity (card_id, user_id, action, details) VALUES (?, ?, ?, ?)')
      .run(req.params.id, req.user.id, 'moved', `Moved to ${newList?.title || 'Unknown'}`);
    const assignee = db.prepare('SELECT assigned_to FROM cards WHERE id = ?').get(req.params.id);
    if (assignee?.assigned_to && assignee.assigned_to !== req.user.id) {
      notifyCard({ cardId: req.params.id, userId: req.user.id, action: 'moved a card' });
    }
  }

  const card = db.prepare('SELECT * FROM cards WHERE id = ?').get(req.params.id);
  res.json(card);
});

router.delete('/cards/:id', (req, res) => {
  if (!canAccessCard(req.user.id, req.params.id)) return res.status(403).json({ error: 'Access denied' });
  db.prepare('DELETE FROM cards WHERE id = ?').run(req.params.id);
  res.json({ success: true });
});

// Card reorder (batch)
router.put('/cards/reorder', (req, res) => {
  const { cards } = req.body;
  if (!Array.isArray(cards)) return res.status(400).json({ error: 'Cards array required' });
  const update = db.prepare('UPDATE cards SET list_id = ?, position = ? WHERE id = ?');
  const moveActivity = db.prepare('INSERT INTO card_activity (card_id, user_id, action, details) VALUES (?, ?, ?, ?)');
  for (const c of cards) {
    update.run(c.list_id, c.position, c.id);
    if (c.moved && c.old_list_id !== c.list_id) {
      const listName = db.prepare('SELECT title FROM lists WHERE id = ?').get(c.list_id)?.title || '';
      moveActivity.run(c.id, req.user.id, 'moved', `Moved to ${listName}`);
    }
  }
  res.json({ success: true });
});

// Comments
router.post('/cards/:id/comments', async (req, res) => {
  if (!canAccessCard(req.user.id, req.params.id)) return res.status(403).json({ error: 'Access denied' });
  const { content } = req.body;
  if (!content) return res.status(400).json({ error: 'Content required' });
  const result = db.prepare('INSERT INTO card_comments (card_id, user_id, content) VALUES (?, ?, ?)').run(req.params.id, req.user.id, content);
  db.prepare('INSERT INTO card_activity (card_id, user_id, action, details) VALUES (?, ?, ?, ?)').run(req.params.id, req.user.id, 'commented', '');
  notifyCard({ cardId: req.params.id, userId: req.user.id, action: 'commented on a card', comment: content });
  const comment = db.prepare('SELECT cc.*, u.name, u.avatar_color FROM card_comments cc LEFT JOIN users u ON u.id = cc.user_id WHERE cc.id = ?').get(result.lastInsertRowid);
  res.json(comment);
});

// Labels
router.post('/:boardId/labels', (req, res) => {
  const { name, color } = req.body;
  if (!name || !color) return res.status(400).json({ error: 'Name and color required' });
  const result = db.prepare('INSERT INTO labels (board_id, name, color) VALUES (?, ?, ?)').run(req.params.boardId, name, color);
  const label = db.prepare('SELECT * FROM labels WHERE id = ?').get(result.lastInsertRowid);
  res.json(label);
});

router.put('/labels/:id', (req, res) => {
  const { name, color } = req.body;
  if (name !== undefined) db.prepare('UPDATE labels SET name = ? WHERE id = ?').run(name, req.params.id);
  if (color !== undefined) db.prepare('UPDATE labels SET color = ? WHERE id = ?').run(color, req.params.id);
  const label = db.prepare('SELECT * FROM labels WHERE id = ?').get(req.params.id);
  res.json(label);
});

router.delete('/labels/:id', (req, res) => {
  db.prepare('DELETE FROM labels WHERE id = ?').run(req.params.id);
  res.json({ success: true });
});

router.put('/cards/:id/labels', (req, res) => {
  if (!canAccessCard(req.user.id, req.params.id)) return res.status(403).json({ error: 'Access denied' });
  const { labels } = req.body;
  db.prepare('DELETE FROM card_labels WHERE card_id = ?').run(req.params.id);
  if (labels?.length) {
    const ins = db.prepare('INSERT OR IGNORE INTO card_labels (card_id, label_id) VALUES (?, ?)');
    labels.forEach(lid => ins.run(req.params.id, lid));
  }
  res.json({ success: true });
});

// Checklists
router.post('/cards/:id/checklists', (req, res) => {
  if (!canAccessCard(req.user.id, req.params.id)) return res.status(403).json({ error: 'Access denied' });
  const { title } = req.body;
  const maxPos = db.prepare('SELECT MAX(position) as p FROM checklists WHERE card_id = ?').get(req.params.id);
  const result = db.prepare('INSERT INTO checklists (card_id, title, position) VALUES (?, ?, ?)')
    .run(req.params.id, title || 'Checklist', (maxPos?.p || 0) + 65536);
  const cl = db.prepare('SELECT * FROM checklists WHERE id = ?').get(result.lastInsertRowid);
  res.json({ ...cl, items: [] });
});

router.post('/checklists/:id/items', (req, res) => {
  const checklist = db.prepare('SELECT * FROM checklists WHERE id = ?').get(req.params.id);
  if (!checklist) return res.status(404).json({ error: 'Not found' });
  if (!canAccessCard(req.user.id, checklist.card_id)) return res.status(403).json({ error: 'Access denied' });
  const { text } = req.body;
  if (!text) return res.status(400).json({ error: 'Text required' });
  const maxPos = db.prepare('SELECT MAX(position) as p FROM checklist_items WHERE checklist_id = ?').get(req.params.id);
  const result = db.prepare('INSERT INTO checklist_items (checklist_id, text, position) VALUES (?, ?, ?)')
    .run(req.params.id, text, (maxPos?.p || 0) + 65536);
  const item = db.prepare('SELECT * FROM checklist_items WHERE id = ?').get(result.lastInsertRowid);
  res.json(item);
});

router.put('/checklist-items/:id', (req, res) => {
  const item = db.prepare('SELECT ci.*, cl.card_id FROM checklist_items ci JOIN checklists cl ON cl.id = ci.checklist_id WHERE ci.id = ?').get(req.params.id);
  if (!item) return res.status(404).json({ error: 'Not found' });
  if (!canAccessCard(req.user.id, item.card_id)) return res.status(403).json({ error: 'Access denied' });
  const { text, is_checked } = req.body;
  if (text !== undefined) db.prepare('UPDATE checklist_items SET text = ? WHERE id = ?').run(text, req.params.id);
  if (is_checked !== undefined) db.prepare('UPDATE checklist_items SET is_checked = ? WHERE id = ?').run(is_checked ? 1 : 0, req.params.id);
  const updated = db.prepare('SELECT * FROM checklist_items WHERE id = ?').get(req.params.id);
  res.json(updated);
});

router.delete('/checklist-items/:id', (req, res) => {
  const item = db.prepare('SELECT ci.*, cl.card_id FROM checklist_items ci JOIN checklists cl ON cl.id = ci.checklist_id WHERE ci.id = ?').get(req.params.id);
  if (!item) return res.status(404).json({ error: 'Not found' });
  if (!canAccessCard(req.user.id, item.card_id)) return res.status(403).json({ error: 'Access denied' });
  db.prepare('DELETE FROM checklist_items WHERE id = ?').run(req.params.id);
  res.json({ success: true });
});

router.delete('/checklists/:id', (req, res) => {
  const cl = db.prepare('SELECT * FROM checklists WHERE id = ?').get(req.params.id);
  if (!cl) return res.status(404).json({ error: 'Not found' });
  if (!canAccessCard(req.user.id, cl.card_id)) return res.status(403).json({ error: 'Access denied' });
  db.prepare('DELETE FROM checklists WHERE id = ?').run(req.params.id);
  res.json({ success: true });
});

export default router;
