const express = require('express');
const Database = require('better-sqlite3');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const cors = require('cors');
const path = require('path');

const app = express();
const PORT = 3501;
const JWT_SECRET = process.env.JWT_SECRET || 'accountbook_secret_key_2024';

// 中间件
app.use(cors({
  origin: ['http://localhost:3500', 'http://127.0.0.1:3500'],
  credentials: true
}));
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'frontend/.next')));
app.use(express.static(path.join(__dirname, 'frontend/.next/server/pages')));

// 数据库初始化
const db = new Database('accountbook.db');

// 创建表
db.exec(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT UNIQUE NOT NULL,
    password TEXT NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  );

  CREATE TABLE IF NOT EXISTS records (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    type TEXT NOT NULL CHECK(type IN ('income', 'expense')),
    amount REAL NOT NULL,
    category TEXT NOT NULL,
    date DATETIME NOT NULL,
    note TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
  );

  CREATE TABLE IF NOT EXISTS recurring_bills (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    type TEXT NOT NULL CHECK(type IN ('income', 'expense')),
    amount REAL NOT NULL,
    category TEXT NOT NULL,
    day INTEGER NOT NULL,
    note TEXT,
    is_active INTEGER DEFAULT 1,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
  );

  CREATE TABLE IF NOT EXISTS categories (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    type TEXT NOT NULL CHECK(type IN ('income', 'expense')),
    name TEXT NOT NULL,
    icon TEXT NOT NULL,
    is_default INTEGER DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
  );
`);

const VALID_RECORD_TYPES = ['income', 'expense'];
const VALID_STATS_PERIODS = ['week', 'month', 'year'];
const VALID_STATS_TYPES = ['income', 'expense', 'all'];
const MONTH_PATTERN = /^\d{4}-\d{2}$/;
const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}( \d{2}:\d{2})?$/;

function isNonEmptyString(value) {
  return typeof value === 'string' && value.trim().length > 0;
}

function isValidMonth(value) {
  return typeof value === 'string' && MONTH_PATTERN.test(value);
}

function isValidDateTime(value) {
  return typeof value === 'string' && DATE_TIME_PATTERN.test(value);
}

function normalizeNote(value) {
  return value === undefined || value === null ? '' : value;
}

function validateRecordPayload(payload) {
  if (!payload || typeof payload !== 'object') {
    return '请求数据格式错误';
  }

  const { type, amount, category, date, note } = payload;

  if (!VALID_RECORD_TYPES.includes(type)) {
    return '账目类型错误';
  }

  if (!Number.isFinite(amount) || amount <= 0) {
    return '金额需大于0';
  }

  if (!isNonEmptyString(category)) {
    return '请填写分类';
  }

  if (!isValidDateTime(date)) {
    return '日期格式错误';
  }

  if (note !== undefined && note !== null && typeof note !== 'string') {
    return '备注格式错误';
  }

  return null;
}

function validateRecurringPayload(payload) {
  if (!payload || typeof payload !== 'object') {
    return '请求数据格式错误';
  }

  const { type, amount, category, day, note, is_active } = payload;

  if (!VALID_RECORD_TYPES.includes(type)) {
    return '账单类型错误';
  }

  if (!Number.isFinite(amount) || amount <= 0) {
    return '金额需大于0';
  }

  if (!isNonEmptyString(category)) {
    return '请填写分类';
  }

  if (!Number.isInteger(day) || day < 1 || day > 28) {
    return '日期需在1到28之间';
  }

  if (note !== undefined && note !== null && typeof note !== 'string') {
    return '备注格式错误';
  }

  if (is_active !== undefined && ![0, 1, true, false].includes(is_active)) {
    return '启用状态错误';
  }

  return null;
}

function validateCategoryPayload(payload) {
  if (!payload || typeof payload !== 'object') {
    return '请求数据格式错误';
  }

  const { type, name, icon } = payload;

  if (!VALID_RECORD_TYPES.includes(type)) {
    return '分类类型错误';
  }

  if (!isNonEmptyString(name)) {
    return '请填写分类名称';
  }

  if (!isNonEmptyString(icon)) {
    return '请选择分类图标';
  }

  return null;
}

function validateImportPayload(payload) {
  if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
    return '导入数据格式错误';
  }

  const { records, recurring, customCategories } = payload;

  if (records !== undefined) {
    if (!Array.isArray(records)) {
      return 'records 必须是数组';
    }

    for (const record of records) {
      const error = validateRecordPayload(record);
      if (error) {
        return `records 数据错误: ${error}`;
      }
    }
  }

  if (recurring !== undefined) {
    if (!Array.isArray(recurring)) {
      return 'recurring 必须是数组';
    }

    for (const bill of recurring) {
      const error = validateRecurringPayload(bill);
      if (error) {
        return `recurring 数据错误: ${error}`;
      }
    }
  }

  if (customCategories !== undefined) {
    if (!Array.isArray(customCategories)) {
      return 'customCategories 必须是数组';
    }

    for (const category of customCategories) {
      const error = validateCategoryPayload(category);
      if (error) {
        return `customCategories 数据错误: ${error}`;
      }
    }
  }

  return null;
}

// 认证中间件
const authenticate = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) {
    return res.status(401).json({ error: '请先登录' });
  }
  try {
    const decoded = jwt.verify(token, JWT_SECRET);
    req.userId = decoded.userId;
    next();
  } catch (err) {
    return res.status(401).json({ error: '登录已过期' });
  }
};

// ============ 认证接口 ============

// 注册
app.post('/api/auth/register', async (req, res) => {
  const { username, password } = req.body;

  if (!username || !password) {
    return res.status(400).json({ error: '请填写用户名和密码' });
  }

  if (username.length < 3 || username.length > 20) {
    return res.status(400).json({ error: '用户名需3-20个字符' });
  }

  if (password.length < 6 || password.length > 20) {
    return res.status(400).json({ error: '密码需6-20个字符' });
  }

  try {
    const hashedPassword = await bcrypt.hash(password, 10);
    const stmt = db.prepare('INSERT INTO users (username, password) VALUES (?, ?)');
    const result = stmt.run(username, hashedPassword);

    const token = jwt.sign({ userId: result.lastInsertRowid }, JWT_SECRET, { expiresIn: '7d' });
    res.json({ token, username });
  } catch (err) {
    if (err.code === 'SQLITE_CONSTRAINT_UNIQUE') {
      return res.status(400).json({ error: '用户名已存在' });
    }
    res.status(500).json({ error: '服务器错误' });
  }
});

// 登录
app.post('/api/auth/login', async (req, res) => {
  const { username, password } = req.body;

  if (!username || !password) {
    return res.status(400).json({ error: '请填写用户名和密码' });
  }

  const stmt = db.prepare('SELECT * FROM users WHERE username = ?');
  const user = stmt.get(username);

  if (!user) {
    return res.status(400).json({ error: '用户名或密码错误' });
  }

  const validPassword = await bcrypt.compare(password, user.password);
  if (!validPassword) {
    return res.status(400).json({ error: '用户名或密码错误' });
  }

  const token = jwt.sign({ userId: user.id }, JWT_SECRET, { expiresIn: '7d' });
  res.json({ token, username: user.username });
});

// ============ 账目接口 ============

// 获取账目列表
app.get('/api/records', authenticate, (req, res) => {
  const { month, type } = req.query;

  let query = 'SELECT * FROM records WHERE user_id = ?';
  const params = [req.userId];

  if (month) {
    query += ' AND date LIKE ?';
    params.push(`${month}%`);
  }

  if (type && type !== 'all') {
    query += ' AND type = ?';
    params.push(type);
  }

  query += ' ORDER BY date DESC, id DESC';

  const stmt = db.prepare(query);
  const records = stmt.all(...params);

  res.json(records);
});

// 新增账目
app.post('/api/records', authenticate, (req, res) => {
  const { type, amount, category, date, note } = req.body;

  const validationError = validateRecordPayload(req.body);
  if (validationError) {
    return res.status(400).json({ error: validationError });
  }

  const stmt = db.prepare(`
    INSERT INTO records (user_id, type, amount, category, date, note)
    VALUES (?, ?, ?, ?, ?, ?)
  `);

  const result = stmt.run(req.userId, type, amount, category.trim(), date, normalizeNote(note));

  res.json({ id: result.lastInsertRowid, message: '添加成功' });
});

// 更新账目
app.put('/api/records/:id', authenticate, (req, res) => {
  const { id } = req.params;
  const { type, amount, category, date, note } = req.body;

  const checkStmt = db.prepare('SELECT * FROM records WHERE id = ? AND user_id = ?');
  const record = checkStmt.get(id, req.userId);

  if (!record) {
    return res.status(404).json({ error: '记录不存在' });
  }

  const validationError = validateRecordPayload(req.body);
  if (validationError) {
    return res.status(400).json({ error: validationError });
  }

  const stmt = db.prepare(`
    UPDATE records SET type = ?, amount = ?, category = ?, date = ?, note = ?
    WHERE id = ? AND user_id = ?
  `);

  stmt.run(type, amount, category.trim(), date, normalizeNote(note), id, req.userId);

  res.json({ message: '更新成功' });
});

// 删除账目
app.delete('/api/records/:id', authenticate, (req, res) => {
  const { id } = req.params;

  const checkStmt = db.prepare('SELECT * FROM records WHERE id = ? AND user_id = ?');
  const record = checkStmt.get(id, req.userId);

  if (!record) {
    return res.status(404).json({ error: '记录不存在' });
  }

  const stmt = db.prepare('DELETE FROM records WHERE id = ? AND user_id = ?');
  stmt.run(id, req.userId);

  res.json({ message: '删除成功' });
});

// 批量删除指定分类的记录
app.delete('/api/records/by-category/:category', authenticate, (req, res) => {
  const { category } = req.params;

  if (!category || typeof category !== 'string' || !category.trim()) {
    return res.status(400).json({ error: '分类不能为空' });
  }

  const stmt = db.prepare('DELETE FROM records WHERE category = ? AND user_id = ?');
  const result = stmt.run(category.trim(), req.userId);

  res.json({ message: `已删除 ${result.changes} 条记录` });
});

// 获取月度统计
app.get('/api/stats', authenticate, (req, res) => {
  const { month } = req.query;

  if (!month) {
    return res.status(400).json({ error: '请指定月份' });
  }

  const stmt = db.prepare(`
    SELECT
      SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) as totalIncome,
      SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) as totalExpense
    FROM records
    WHERE user_id = ? AND date LIKE ?
  `);

  const result = stmt.get(req.userId, `${month}%`);

  res.json({
    income: result.totalIncome || 0,
    expense: result.totalExpense || 0,
    balance: (result.totalIncome || 0) - (result.totalExpense || 0)
  });
});

// ============ 搜索接口 ============

// 搜索账目
app.get('/api/records/search', authenticate, (req, res) => {
  const { q } = req.query;

  if (!q) {
    return res.status(400).json({ error: '请输入搜索关键词' });
  }

  const stmt = db.prepare(`
    SELECT * FROM records
    WHERE user_id = ? AND (category LIKE ? OR note LIKE ?)
    ORDER BY date DESC, id DESC
    LIMIT 50
  `);

  const records = stmt.all(req.userId, `%${q}%`, `%${q}%`);
  res.json(records);
});

// ============ 统计接口 ============

// 收支趋势统计
app.get('/api/stats/trend', authenticate, (req, res) => {
  const { period = 'month', month } = req.query;

  if (!VALID_STATS_PERIODS.includes(period)) {
    return res.status(400).json({ error: '统计周期错误' });
  }

  if (month && !isValidMonth(month)) {
    return res.status(400).json({ error: '月份格式错误' });
  }

  let dateGroup;
  if (period === 'year') {
    dateGroup = "strftime('%Y', date)";
  } else if (period === 'week') {
    dateGroup = "strftime('%Y-%W', date)";
  } else {
    dateGroup = "strftime('%Y-%m', date)";
  }

  let query = `
    SELECT
      ${dateGroup} as period,
      SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) as income,
      SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) as expense
    FROM records
    WHERE user_id = ?
  `;
  const params = [req.userId];

  if (month) {
    query += ' AND date LIKE ?';
    params.push(`${month}%`);
  }

  query += `
    GROUP BY ${dateGroup}
    ORDER BY period DESC
    LIMIT 12
  `;

  const stmt = db.prepare(query);
  const result = stmt.all(...params);
  res.json(result.reverse());
});

// 分类统计
app.get('/api/stats/category', authenticate, (req, res) => {
  const { month, type = 'all' } = req.query;

  if (!VALID_STATS_TYPES.includes(type)) {
    return res.status(400).json({ error: '统计类型错误' });
  }

  if (month && !isValidMonth(month)) {
    return res.status(400).json({ error: '月份格式错误' });
  }

  let query = `
    SELECT
      category,
      SUM(amount) as total,
      type
    FROM records
    WHERE user_id = ?
  `;
  const params = [req.userId];

  if (month) {
    query += ' AND date LIKE ?';
    params.push(`${month}%`);
  }

  if (type !== 'all') {
    query += ' AND type = ?';
    params.push(type);
  }

  query += `
    GROUP BY category, type
    ORDER BY total DESC
  `;

  const stmt = db.prepare(query);
  const result = stmt.all(...params);
  res.json(result);
});

// ============ 周期性账单接口 ============

// 获取周期性账单
app.get('/api/recurring', authenticate, (req, res) => {
  const stmt = db.prepare('SELECT * FROM recurring_bills WHERE user_id = ? ORDER BY day ASC');
  const bills = stmt.all(req.userId);
  res.json(bills);
});

// 新增周期性账单
app.post('/api/recurring', authenticate, (req, res) => {
  const { type, amount, category, day, note } = req.body;

  const validationError = validateRecurringPayload(req.body);
  if (validationError) {
    return res.status(400).json({ error: validationError });
  }

  const stmt = db.prepare(`
    INSERT INTO recurring_bills (user_id, type, amount, category, day, note)
    VALUES (?, ?, ?, ?, ?, ?)
  `);

  const result = stmt.run(req.userId, type, amount, category.trim(), day, normalizeNote(note));
  res.json({ id: result.lastInsertRowid, message: '添加成功' });
});

// 更新周期性账单
app.put('/api/recurring/:id', authenticate, (req, res) => {
  const { id } = req.params;
  const { type, amount, category, day, note, is_active } = req.body;

  const checkStmt = db.prepare('SELECT * FROM recurring_bills WHERE id = ? AND user_id = ?');
  const bill = checkStmt.get(id, req.userId);

  if (!bill) {
    return res.status(404).json({ error: '账单不存在' });
  }

  const validationError = validateRecurringPayload(req.body);
  if (validationError) {
    return res.status(400).json({ error: validationError });
  }

  const stmt = db.prepare(`
    UPDATE recurring_bills SET type = ?, amount = ?, category = ?, day = ?, note = ?, is_active = ?
    WHERE id = ? AND user_id = ?
  `);

  stmt.run(type, amount, category.trim(), day, normalizeNote(note), is_active !== undefined ? is_active : 1, id, req.userId);
  res.json({ message: '更新成功' });
});

// 删除周期性账单
app.delete('/api/recurring/:id', authenticate, (req, res) => {
  const { id } = req.params;

  const checkStmt = db.prepare('SELECT * FROM recurring_bills WHERE id = ? AND user_id = ?');
  const bill = checkStmt.get(id, req.userId);

  if (!bill) {
    return res.status(404).json({ error: '账单不存在' });
  }

  const stmt = db.prepare('DELETE FROM recurring_bills WHERE id = ? AND user_id = ?');
  stmt.run(id, req.userId);
  res.json({ message: '删除成功' });
});

// 应用周期性账单
app.post('/api/recurring/:id/apply', authenticate, (req, res) => {
  const { id } = req.params;

  const checkStmt = db.prepare('SELECT * FROM recurring_bills WHERE id = ? AND user_id = ? AND is_active = 1');
  const bill = checkStmt.get(id, req.userId);

  if (!bill) {
    return res.status(404).json({ error: '账单不存在或已禁用' });
  }

  // 创建当前日期的账目
  const today = new Date();
  const dateStr = today.toISOString().split('T')[0] + ' ' + today.toTimeString().slice(0, 5);

  const insertStmt = db.prepare(`
    INSERT INTO records (user_id, type, amount, category, date, note)
    VALUES (?, ?, ?, ?, ?, ?)
  `);

  insertStmt.run(req.userId, bill.type, bill.amount, bill.category, dateStr, bill.note || '');
  res.json({ message: '应用成功' });
});

// ============ 分类接口 ============

// 获取分类列表
app.get('/api/categories', authenticate, (req, res) => {
  const stmt = db.prepare('SELECT * FROM categories WHERE user_id = ? ORDER BY type, id');
  const customCategories = stmt.all(req.userId);

  const defaultCategories = {
    expense: [
      { name: '餐饮', icon: '🍜' },
      { name: '买菜', icon: '🥬' },
      { name: '交通', icon: '🚗' },
      { name: '购物', icon: '🛒' },
      { name: '娱乐', icon: '🎮' },
      { name: '房租', icon: '🏠' },
      { name: '房贷', icon: '🏦' },
      { name: '水电', icon: '💧' },
      { name: '衣服', icon: '👔' },
      { name: '通讯', icon: '📱' },
      { name: '日用品', icon: '🧴' },
      { name: '美妆', icon: '💄' },
      { name: '医疗', icon: '🏥' },
      { name: '养娃', icon: '👶' },
      { name: '家电', icon: '📺' },
      { name: '家具', icon: '🛋️' },
      { name: '装修', icon: '🔨' },
      { name: '宠物', icon: '🐕' },
      { name: '其他', icon: '📝' }
    ],
    income: [
      { name: '工资', icon: '💰' },
      { name: '奖金', icon: '🎁' },
      { name: '理财', icon: '📈' },
      { name: '红包', icon: '🧧' },
      { name: '其他', icon: '📝' }
    ]
  };

  // 合并默认分类和自定义分类
  const categories = {
    expense: [
      ...defaultCategories.expense.map(c => ({ ...c, is_default: true })),
      ...customCategories.filter(c => c.type === 'expense')
    ],
    income: [
      ...defaultCategories.income.map(c => ({ ...c, is_default: true })),
      ...customCategories.filter(c => c.type === 'income')
    ]
  };

  res.json(categories);
});

// 新增自定义分类
app.post('/api/categories', authenticate, (req, res) => {
  const { type, name, icon } = req.body;

  const validationError = validateCategoryPayload(req.body);
  if (validationError) {
    return res.status(400).json({ error: validationError });
  }

  const stmt = db.prepare(`
    INSERT INTO categories (user_id, type, name, icon, is_default)
    VALUES (?, ?, ?, ?, 0)
  `);

  const result = stmt.run(req.userId, type, name.trim(), icon.trim());
  res.json({ id: result.lastInsertRowid, message: '添加成功' });
});

// 删除自定义分类
app.delete('/api/categories/:id', authenticate, (req, res) => {
  const { id } = req.params;

  const checkStmt = db.prepare('SELECT * FROM categories WHERE id = ? AND user_id = ? AND is_default = 0');
  const category = checkStmt.get(id, req.userId);

  if (!category) {
    return res.status(404).json({ error: '分类不存在或无法删除' });
  }

  const stmt = db.prepare('DELETE FROM categories WHERE id = ? AND user_id = ?');
  stmt.run(id, req.userId);
  res.json({ message: '删除成功' });
});

// ============ 数据导入导出接口 ============

// 导出数据
app.get('/api/export', authenticate, (req, res) => {
  const recordsStmt = db.prepare('SELECT * FROM records WHERE user_id = ? ORDER BY date DESC');
  const records = recordsStmt.all(req.userId);

  const recurringStmt = db.prepare('SELECT * FROM recurring_bills WHERE user_id = ?');
  const recurring = recurringStmt.all(req.userId);

  const categoriesStmt = db.prepare('SELECT * FROM categories WHERE user_id = ?');
  const categories = categoriesStmt.all(req.userId);

  res.json({
    version: '1.0',
    exportDate: new Date().toISOString(),
    records,
    recurring,
    customCategories: categories
  });
});

// 导入数据
app.post('/api/import', authenticate, (req, res) => {
  const { records: importRecords, recurring: importRecurring, customCategories: importCategories } = req.body;

  const validationError = validateImportPayload(req.body);
  if (validationError) {
    return res.status(400).json({ error: validationError });
  }

  try {
    if (importRecords && Array.isArray(importRecords)) {
      const insertRecord = db.prepare(`
        INSERT INTO records (user_id, type, amount, category, date, note, created_at)
        VALUES (?, ?, ?, ?, ?, ?, ?)
      `);

      const insertMany = db.transaction((records) => {
        for (const r of records) {
          insertRecord.run(req.userId, r.type, r.amount, r.category.trim(), r.date, normalizeNote(r.note), r.created_at || new Date().toISOString());
        }
      });
      insertMany(importRecords);
    }

    if (importRecurring && Array.isArray(importRecurring)) {
      const insertRecurring = db.prepare(`
        INSERT INTO recurring_bills (user_id, type, amount, category, day, note, is_active, created_at)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
      `);

      const insertRecurringMany = db.transaction((bills) => {
        for (const b of bills) {
          insertRecurring.run(req.userId, b.type, b.amount, b.category.trim(), b.day, normalizeNote(b.note), b.is_active !== undefined ? b.is_active : 1, b.created_at || new Date().toISOString());
        }
      });
      insertRecurringMany(importRecurring);
    }

    if (importCategories && Array.isArray(importCategories)) {
      const insertCategory = db.prepare(`
        INSERT INTO categories (user_id, type, name, icon, is_default, created_at)
        VALUES (?, ?, ?, ?, 0, ?)
      `);

      const insertCategoryMany = db.transaction((cats) => {
        for (const c of cats) {
          insertCategory.run(req.userId, c.type, c.name.trim(), c.icon.trim(), c.created_at || new Date().toISOString());
        }
      });
      insertCategoryMany(importCategories);
    }

    res.json({ message: '导入成功' });
  } catch (err) {
    res.status(500).json({ error: '导入失败: ' + err.message });
  }
});

// 前端路由 - 优先处理 Next.js 静态文件
app.get('/_next/static/:path(*)', (req, res) => {
  const filePath = path.join(__dirname, 'frontend/.next/static', req.params.path);
  res.sendFile(filePath, (err) => {
    if (err) res.status(404).send('Not found');
  });
});

app.get('*', (req, res) => {
  // 检查是否是 Next.js 预渲染的页面
  let pagePath = req.path === '/' ? '/index.html' : req.path + '.html';
  const nextPagePath = path.join(__dirname, 'frontend/.next/server/pages', pagePath);

  res.sendFile(nextPagePath, (err) => {
    if (err) {
      // 如果找不到，返回首页
      res.sendFile(path.join(__dirname, 'frontend/.next/server/pages/index.html'));
    }
  });
});

app.listen(PORT, '0.0.0.0', () => {
  console.log(`记账本服务已启动: http://0.0.0.0:${PORT}`);
});
