/**
 * 分类树结构测试
 * TDD: 先写测试，再实现功能
 */

const sqlite3 = require('sqlite3').verbose();
const path = require('path');

// 使用测试数据库
const TEST_DB_PATH = path.join(__dirname, '../test_company_finance.db');

// 测试数据库连接
function createTestDb() {
  return new sqlite3.Database(TEST_DB_PATH);
}

// 初始化测试数据库
async function initTestDb(db) {
  return new Promise((resolve, reject) => {
    // 读取迁移脚本
    const fs = require('fs');
    const migrationScript = fs.readFileSync(
      path.join(__dirname, '../migrations/001_create_category_tree.sql'),
      'utf8'
    );
    
    db.exec(migrationScript, (err) => {
      if (err) reject(err);
      else resolve();
    });
  });
}

// 测试套件
describe('分类树结构测试', () => {
  let db;
  
  beforeAll(async () => {
    db = createTestDb();
    await initTestDb(db);
  });
  
  afterAll((done) => {
    db.close(() => {
      // 清理测试数据库
      const fs = require('fs');
      try {
        fs.unlinkSync(TEST_DB_PATH);
      } catch (e) {
        // 忽略删除错误
      }
      done();
    });
  });
  
  // 测试1: 分类表应该存在
  test('category_tree 表应该存在', async () => {
    const result = await new Promise((resolve, reject) => {
      db.get(
        "SELECT name FROM sqlite_master WHERE type='table' AND name='category_tree'",
        (err, row) => {
          if (err) reject(err);
          else resolve(row);
        }
      );
    });
    
    expect(result).toBeTruthy();
    expect(result.name).toBe('category_tree');
  });
  
  // 测试2: 应该能创建一级分类
  test('应该能创建一级分类', async () => {
    const result = await new Promise((resolve, reject) => {
      db.run(
        'INSERT INTO category_tree (name, parent_id, level, sort_order) VALUES (?, ?, ?, ?)',
        ['测试一级分类', null, 1, 1],
        function(err) {
          if (err) reject(err);
          else resolve({ id: this.lastID });
        }
      );
    });
    
    expect(result.id).toBeGreaterThan(0);
  });
  
  // 测试3: 应该能在一级分类下创建二级分类
  test('应该能创建二级分类', async () => {
    // 先创建一级分类
    const parentResult = await new Promise((resolve, reject) => {
      db.run(
        'INSERT INTO category_tree (name, parent_id, level, sort_order) VALUES (?, ?, ?, ?)',
        ['父分类', null, 1, 1],
        function(err) {
          if (err) reject(err);
          else resolve({ id: this.lastID });
        }
      );
    });
    
    // 再创建二级分类
    const childResult = await new Promise((resolve, reject) => {
      db.run(
        'INSERT INTO category_tree (name, parent_id, level, sort_order) VALUES (?, ?, ?, ?)',
        ['子分类', parentResult.id, 2, 1],
        function(err) {
          if (err) reject(err);
          else resolve({ id: this.lastID });
        }
      );
    });
    
    expect(childResult.id).toBeGreaterThan(0);
    
    // 验证父子关系
    const childCategory = await new Promise((resolve, reject) => {
      db.get(
        'SELECT * FROM category_tree WHERE id = ?',
        [childResult.id],
        (err, row) => {
          if (err) reject(err);
          else resolve(row);
        }
      );
    });
    
    expect(childCategory.parent_id).toBe(parentResult.id);
    expect(childCategory.level).toBe(2);
  });
  
  // 测试4: 应该能获取分类树
  test('应该能获取完整的分类树', async () => {
    const categories = await new Promise((resolve, reject) => {
      db.all(
        'SELECT * FROM category_tree ORDER BY level, sort_order',
        (err, rows) => {
          if (err) reject(err);
          else resolve(rows);
        }
      );
    });
    
    expect(Array.isArray(categories)).toBe(true);
    expect(categories.length).toBeGreaterThan(0);
    
    // 验证有默认分类数据
    const defaultCategories = categories.filter(c => 
      ['电杆横担', '电缆电线', '变压器'].includes(c.name)
    );
    expect(defaultCategories.length).toBeGreaterThan(0);
  });
  
  // 测试5: 删除一级分类应该级联删除二级分类
  test('删除一级分类应该级联删除二级分类', async () => {
    // 创建测试数据
    const parent = await new Promise((resolve, reject) => {
      db.run(
        'INSERT INTO category_tree (name, parent_id, level) VALUES (?, ?, ?)',
        ['待删除父分类', null, 1],
        function(err) {
          if (err) reject(err);
          else resolve({ id: this.lastID });
        }
      );
    });
    
    const child = await new Promise((resolve, reject) => {
      db.run(
        'INSERT INTO category_tree (name, parent_id, level) VALUES (?, ?, ?)',
        ['待删除子分类', parent.id, 2],
        function(err) {
          if (err) reject(err);
          else resolve({ id: this.lastID });
        }
      );
    });
    
    // 删除父分类
    await new Promise((resolve, reject) => {
      db.run('DELETE FROM category_tree WHERE id = ?', [parent.id], function(err) {
        if (err) reject(err);
        else resolve();
      });
    });
    
    // 验证子分类也被删除
    const remainingChild = await new Promise((resolve, reject) => {
      db.get('SELECT * FROM category_tree WHERE id = ?', [child.id], (err, row) => {
        if (err) reject(err);
        else resolve(row);
      });
    });
    
    expect(remainingChild).toBeUndefined();
  });
  
  // 测试6: 应该能更新分类
  test('应该能更新分类', async () => {
    // 创建分类
    const category = await new Promise((resolve, reject) => {
      db.run(
        'INSERT INTO category_tree (name, parent_id, level) VALUES (?, ?, ?)',
        ['原名称', null, 1],
        function(err) {
          if (err) reject(err);
          else resolve({ id: this.lastID });
        }
      );
    });
    
    // 更新名称
    await new Promise((resolve, reject) => {
      db.run(
        'UPDATE category_tree SET name = ? WHERE id = ?',
        ['新名称', category.id],
        function(err) {
          if (err) reject(err);
          else resolve();
        }
      );
    });
    
    // 验证更新
    const updated = await new Promise((resolve, reject) => {
      db.get('SELECT * FROM category_tree WHERE id = ?', [category.id], (err, row) => {
        if (err) reject(err);
        else resolve(row);
      });
    });
    
    expect(updated.name).toBe('新名称');
  });
});

// 商品表测试
describe('商品表测试', () => {
  let db;
  
  beforeAll(async () => {
    db = createTestDb();
    await initTestDb(db);
  });
  
  afterAll((done) => {
    db.close(done);
  });
  
  // 测试1: 商品表应该存在
  test('products 表应该存在', async () => {
    const result = await new Promise((resolve, reject) => {
      db.get(
        "SELECT name FROM sqlite_master WHERE type='table' AND name='products'",
        (err, row) => {
          if (err) reject(err);
          else resolve(row);
        }
      );
    });
    
    expect(result).toBeTruthy();
    expect(result.name).toBe('products');
  });
  
  // 测试2: 应该能创建商品
  test('应该能创建商品', async () => {
    // 先获取一个分类ID
    const category = await new Promise((resolve, reject) => {
      db.get('SELECT id FROM category_tree LIMIT 1', (err, row) => {
        if (err) reject(err);
        else resolve(row);
      });
    });
    
    const result = await new Promise((resolve, reject) => {
      db.run(
        `INSERT INTO products (
          name, model, category_id, category_name, unit, 
          cost_price, price, brand, specification, source, remark
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          '测试商品', 'Model-001', category.id, '测试分类', '件',
          100.00, 150.00, '测试品牌', '规格参数', '中国', '测试备注'
        ],
        function(err) {
          if (err) reject(err);
          else resolve({ id: this.lastID });
        }
      );
    });
    
    expect(result.id).toBeGreaterThan(0);
  });
  
  // 测试3: 商品应该有默认值
  test('商品字段应该有正确的默认值', async () => {
    const category = await new Promise((resolve, reject) => {
      db.get('SELECT id FROM category_tree LIMIT 1', (err, row) => {
        if (err) reject(err);
        else resolve(row);
      });
    });
    
    const result = await new Promise((resolve, reject) => {
      db.run(
        'INSERT INTO products (name, category_id) VALUES (?, ?)',
        ['最小化商品', category.id],
        function(err) {
          if (err) reject(err);
          else resolve({ id: this.lastID });
        }
      );
    });
    
    const product = await new Promise((resolve, reject) => {
      db.get('SELECT * FROM products WHERE id = ?', [result.id], (err, row) => {
        if (err) reject(err);
        else resolve(row);
      });
    });
    
    expect(product.unit).toBe('件');
    expect(product.source).toBe('老挝');
    expect(product.status).toBe('active');
    expect(product.stock_quantity).toBe(0);
  });
  
  // 测试4: cost_price 可以为空
  test('cost_price 应该可以为空', async () => {
    const category = await new Promise((resolve, reject) => {
      db.get('SELECT id FROM category_tree LIMIT 1', (err, row) => {
        if (err) reject(err);
        else resolve(row);
      });
    });
    
    const result = await new Promise((resolve, reject) => {
      db.run(
        'INSERT INTO products (name, category_id, cost_price) VALUES (?, ?, ?)',
        ['无成本商品', category.id, null],
        function(err) {
          if (err) reject(err);
          else resolve({ id: this.lastID });
        }
      );
    });
    
    expect(result.id).toBeGreaterThan(0);
  });
});

// 运行测试
if (require.main === module) {
  const { execSync } = require('child_process');
  try {
    execSync('npx jest test-category-tree.spec.js --verbose', {
      cwd: __dirname,
      stdio: 'inherit'
    });
  } catch (e) {
    process.exit(1);
  }
}

module.exports = { createTestDb, initTestDb };
