import initSqlJs from 'sql.js';
import path from 'path';
import fs from 'fs';
import bcrypt from 'bcryptjs';

const DB_PATH = path.join(process.cwd(), 'data', 'database.sqlite');

let db = null;
let SQL = null;
let initPromise = null;
let transactionDepth = 0;

function saveDb() {
  if (transactionDepth > 0) {
    return;
  }
  if (db) {
    const data = db.export();
    const buffer = Buffer.from(data);
    const dir = path.dirname(DB_PATH);
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
    fs.writeFileSync(DB_PATH, buffer);
  }
}

async function ensureInit() {
  if (db) return;
  if (initPromise) {
    await initPromise;
    return;
  }
  initPromise = (async () => {
    SQL = await initSqlJs();
    const dir = path.dirname(DB_PATH);
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }
    try {
      if (fs.existsSync(DB_PATH)) {
        const fileBuffer = fs.readFileSync(DB_PATH);
        db = new SQL.Database(fileBuffer);
      } else {
        db = new SQL.Database();
      }
    } catch {
      db = new SQL.Database();
    }
    initializeDatabase(db);
    saveDb();
  })();
  await initPromise;
}

// 异步获取 db 代理 - 所有 API 路由使用这个
export default async function getDb() {
  await ensureInit();
  return {
    prepare(sql) {
      return {
        get(...params) {
          const stmt = db.prepare(sql);
          if (params.length > 0) stmt.bind(params);
          if (stmt.step()) {
            const result = stmt.getAsObject();
            stmt.free();
            return result;
          }
          stmt.free();
          return undefined;
        },
        all(...params) {
          const results = [];
          const stmt = db.prepare(sql);
          if (params.length > 0) stmt.bind(params);
          while (stmt.step()) {
            results.push(stmt.getAsObject());
          }
          stmt.free();
          return results;
        },
        run(...params) {
          db.run(sql, params);
          const lastId = db.exec('SELECT last_insert_rowid() as id');
          const changes = db.getRowsModified();
          saveDb();
          return {
            lastInsertRowid: lastId[0]?.values[0]?.[0] || 0,
            changes
          };
        }
      };
    },
    exec(sql) {
      db.exec(sql);
      saveDb();
    },
    transaction(fn) {
      return (...args) => {
        transactionDepth++;
        db.run('BEGIN TRANSACTION');
        try {
          const result = fn(...args);
          transactionDepth--;
          db.run('COMMIT');
          saveDb();
          return result;
        } catch (error) {
          transactionDepth--;
          console.error("TRANSACTION ERROR:", error);
          try {
            db.run('ROLLBACK');
          } catch (rollbackError) {
            console.error("ROLLBACK ERROR:", rollbackError);
          }
          throw error;
        }
      };
    }
  };
}

function initializeDatabase(database) {
  database.run(`CREATE TABLE IF NOT EXISTS departments (
    id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP)`);
  database.run(`CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE,
    password TEXT NOT NULL, real_name TEXT NOT NULL,
    role TEXT NOT NULL DEFAULT 'employee', department_id INTEGER,
    status INTEGER DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (department_id) REFERENCES departments(id))`);
  database.run(`CREATE TABLE IF NOT EXISTS partners (
    id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL,
    short_name TEXT, english_name TEXT, website TEXT, logo TEXT,
    address TEXT, description TEXT, is_deleted INTEGER DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP)`);
  database.run(`CREATE TABLE IF NOT EXISTS contracts (
    id INTEGER PRIMARY KEY AUTOINCREMENT, project_name TEXT NOT NULL,
    partner_id INTEGER, partner_name TEXT NOT NULL, contract_content TEXT,
    contract_years INTEGER, contract_amount REAL DEFAULT 0,
    estimated_profit REAL DEFAULT 0, payment_type TEXT DEFAULT 'receive',
    sign_date TEXT, status TEXT DEFAULT 'pending_supervisor',
    creator_id INTEGER NOT NULL, creator_name TEXT NOT NULL,
    department_id INTEGER, department_name TEXT, project_leader TEXT,
    supervisor_opinion TEXT, supervisor_approved INTEGER,
    supervisor_id INTEGER, supervisor_name TEXT, supervisor_time DATETIME,
    finance_opinion TEXT, finance_approved INTEGER,
    finance_id INTEGER, finance_name TEXT, finance_time DATETIME,
    secretary_opinion TEXT, secretary_approved INTEGER,
    secretary_id INTEGER, secretary_name TEXT, secretary_time DATETIME,
    reject_reason TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (creator_id) REFERENCES users(id),
    FOREIGN KEY (partner_id) REFERENCES partners(id),
    FOREIGN KEY (department_id) REFERENCES departments(id))`);
  database.run(`CREATE TABLE IF NOT EXISTS contract_attachments (
    id INTEGER PRIMARY KEY AUTOINCREMENT, contract_id INTEGER NOT NULL,
    file_name TEXT NOT NULL, file_path TEXT NOT NULL,
    file_size INTEGER DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (contract_id) REFERENCES contracts(id))`);
  database.run(`CREATE TABLE IF NOT EXISTS system_config (
    id INTEGER PRIMARY KEY AUTOINCREMENT, config_key TEXT NOT NULL UNIQUE,
    config_value TEXT, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP)`);
  database.run(`CREATE TABLE IF NOT EXISTS role_permissions (
    id INTEGER PRIMARY KEY AUTOINCREMENT, role TEXT NOT NULL,
    menu_key TEXT NOT NULL, visible INTEGER DEFAULT 1,
    UNIQUE(role, menu_key))`);
  initDefaultData(database);
}

function initDefaultData(database) {
  const dc = database.exec('SELECT COUNT(*) FROM departments');
  if ((dc[0]?.values[0]?.[0] || 0) === 0) {
    for (const n of ['技术部', '市场部', '销售部', '财务部', '行政部']) {
      database.run('INSERT INTO departments (name) VALUES (?)', [n]);
    }
  }
  const uc = database.exec('SELECT COUNT(*) FROM users');
  if ((uc[0]?.values[0]?.[0] || 0) === 0) {
    const s = bcrypt.genSaltSync(10);
    const users = [
      ['admin', bcrypt.hashSync('admin123', s), '系统管理员', 'admin', null],
      ['zhangsan', bcrypt.hashSync('123456', s), '张三', 'employee', 1],
      ['lisi', bcrypt.hashSync('123456', s), '李四', 'supervisor', 1],
      ['wangwu_emp', bcrypt.hashSync('123456', s), '王五', 'employee', 2],
      ['maqi', bcrypt.hashSync('123456', s), '马七', 'supervisor', 2],
      ['wangwu', bcrypt.hashSync('123456', s), '赵六', 'finance', 4],
      ['qianba', bcrypt.hashSync('123456', s), '钱八', 'secretary', null],
    ];
    for (const u of users) {
      database.run('INSERT INTO users (username, password, real_name, role, department_id) VALUES (?,?,?,?,?)', u);
    }
  }
  const cc = database.exec('SELECT COUNT(*) FROM system_config');
  if ((cc[0]?.values[0]?.[0] || 0) === 0) {
    database.run("INSERT INTO system_config (config_key, config_value) VALUES ('company_name','合同流转审批系统')");
    database.run("INSERT INTO system_config (config_key, config_value) VALUES ('company_logo','')");
    database.run("INSERT INTO system_config (config_key, config_value) VALUES ('profit_percentage','10')");
  }
  const pc = database.exec('SELECT COUNT(*) FROM role_permissions');
  if ((pc[0]?.values[0]?.[0] || 0) === 0) {
    const menus = ['dashboard','contracts','partners','users','departments','settings','permissions'];
    const roles = { admin: menus, employee: ['dashboard','contracts','partners'],
      supervisor: ['dashboard','contracts','partners'], finance: ['dashboard','contracts','partners'],
      secretary: ['dashboard','contracts','partners'] };
    for (const [role, vm] of Object.entries(roles)) {
      for (const m of menus) {
        database.run('INSERT INTO role_permissions (role, menu_key, visible) VALUES (?,?,?)',
          [role, m, vm.includes(m) ? 1 : 0]);
      }
    }
  }
  const pac = database.exec('SELECT COUNT(*) FROM partners');
  if ((pac[0]?.values[0]?.[0] || 0) === 0) {
    const defaultPartners = [
      ['健帆生物科技集团股份有限公司', '健帆生物', 'Jafron Biomedical Co., Ltd.', 'http://www.jafron.com', '', '珠海市唐家湾科技创新海岸科技一路9号', '血液净化产品的研发、生产与销售'],
      ['天士力医药集团股份有限公司', '天士力', 'Tasly Pharmaceutical Group Co., Ltd.', 'http://www.tasly.com', '', '天津市北辰科技园区科技东路1号', '现代中药、化学药、生物药的研发、生产与销售'],
      ['雅培贸易（上海）有限公司', '雅培', 'Abbott Laboratories Trading (Shanghai) Co., Ltd.', 'http://www.abbott.com.cn', '', '中国（上海）自由贸易试验区外高桥保税区富特北路399号', '医疗健康、诊断、营养品及成熟药品'],
      ['成都嗖嗖优速网络科技有限公司', '嗖嗖优速', 'Chengdu Sousou Yousu Network Technology Co., Ltd.', 'http://www.sousouyousu.com', '', '四川省成都市高新区吉泰五路88号', '互联网信息服务与网络技术研发'],
      ['成都世纪城会展集团有限公司', '成都世纪城会展', 'Chengdu Century City Exhibition Group Co., Ltd.', 'http://www.centurycityexhibition.com', '', '四川省成都市高新区天府大道中段177号', '会展场馆运营、会议展览策划与执行'],
      ['正大天晴药业集团股份有限公司', '正大天晴', 'Chia Tai-Tianqing Pharmaceutical Group Co., Ltd.', 'http://www.cttq.com', '', '江苏省连云港市新浦区巨龙北路16号', '抗肿瘤、肝病及呼吸系统药物研发与生产'],
      ['国家卫生健康委能力建设和继续教育中心', '卫健委能建中心', 'NCCHD, NHC', 'http://www.ncchd.org.cn', '', '北京市海淀区学院路38号', '卫生健康行业人才队伍能力建设与继续医学教育'],
      ['南京正大天晴制药有限公司', '南京正大天晴', 'Nanjing Chia Tai-Tianqing Pharmaceutical Co., Ltd.', 'http://www.njcttq.com', '', '江苏省南京市经济技术开发区恒广路36号', '心脑血管、外科及消化系统药物制造'],
      ['西安盛博商务会展服务有限公司', '西安盛博会展', 'Xi\'an Shengbo Business Exhibition Service Co., Ltd.', 'http://www.xashengbo.com', '', '陕西省西安市雁塔区朱雀大街南段2号', '会议展览服务与公关策划业务']
    ];
    for (const p of defaultPartners) {
      database.run('INSERT INTO partners (name, short_name, english_name, website, logo, address, description) VALUES (?,?,?,?,?,?,?)', p);
    }
  }
}
