import express from 'express';
import mysql from 'mysql2/promise';
import cors from 'cors';
import dotenv from 'dotenv';

dotenv.config();

const app = express();
app.use(cors());
app.use(express.json({ limit: '100mb' }));

// Request Logger
app.use((req, res, next) => {
  console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
  next();
});

const pool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME,
  port: parseInt(process.env.DB_PORT || '3306'),
  charset: 'utf8mb4'
});

const handleError = (res, err, context, isGet = false) => {
  console.error(`❌ [${context}] Error:`, err.message);
  if (isGet) res.json([]);
  else res.status(500).json({ error: err.message });
};

// --- API Implementation ---

/**
 * Generic Fetcher for Asset Tables
 */
const fetchAssets = async (tableName, res, context) => {
  try {
    const [rows] = await pool.query(`SELECT * FROM ${tableName}`);
    console.log(`📡 [GET ${context}] Returning ${rows.length} rows from ${tableName}`);
    res.json(rows);
  } catch (err) {
    handleError(res, err, context, true);
  }
};

/**
 * Generic Batch Saver for Asset Tables
 */
const saveAssetsBatch = async (tableName, items, res, context) => {
  const connection = await pool.getConnection();
  try {
    await connection.beginTransaction();
    
    // Get valid columns for this table
    const [cols] = await connection.query(`DESCRIBE ${tableName}`);
    const validColumns = cols.map(c => c.Field);
    
    // 1. Clear existing (or we could use UPSERT logic, but existing code used DELETE-INSERT pattern)
    await connection.query(`DELETE FROM ${tableName}`);
    
    // 2. Insert new items
    for (const item of items) {
      const filteredRow = {};
      validColumns.forEach(col => {
        // Exclude auto-managed timestamps from manual insertion
        if (col === 'created_at' || col === 'updated_at') return;
        
        if (item[col] !== undefined) filteredRow[col] = item[col];
      });
      
      // Auto-generate ID if missing
      if (!filteredRow.id) filteredRow.id = Math.random().toString(36).substring(2, 9);
      
      await connection.query(`INSERT INTO ${tableName} SET ?`, [filteredRow]);
    }
    
    await connection.commit();
    res.json({ success: true, count: items.length });
  } catch (err) {
    await connection.rollback();
    handleError(res, err, context);
  } finally {
    connection.release();
  }
};

// --- Routes ---

const routeMap = {
  '/api/users': { table: 'system_users', context: 'USERS' },
  '/api/pc': { table: 'asset_pc', context: 'PC' },
  '/api/server': { table: 'asset_server', context: 'SERVER' },
  '/api/storage': { table: 'asset_storage', context: 'STORAGE' },
  '/api/network': { table: 'asset_network', context: 'NETWORK' },
  '/api/sw/internal': { table: 'asset_sw_internal', context: 'SW INTERNAL' },
  '/api/sw/external': { table: 'asset_sw_external', context: 'SW EXTERNAL' },
  '/api/survey': { table: 'asset_survey', context: 'SURVEY' },
  '/api/pc-parts': { table: 'asset_pc_parts', context: 'PC PARTS' },
  '/api/equipment': { table: 'asset_equipment', context: 'EQUIPMENT' },
  '/api/office-supplies': { table: 'asset_office_supplies', context: 'OFFICE SUPPLIES' },
  '/api/cloud': { table: 'asset_cloud', context: 'CLOUD' },
  '/api/domain': { table: 'asset_domain', context: 'DOMAIN' },
  '/api/cost': { table: 'asset_cost', context: 'COST' },
  '/api/vip': { table: 'asset_vip', context: 'VIP' },
  '/api/asset/software/assignment': { table: 'asset_software_assignment', context: 'SW ASSIGN' }
};

// 동적 라우팅 생성 (Dynamic Routing)
Object.entries(routeMap).forEach(([route, { table, context }]) => {
  app.get(route, (req, res) => fetchAssets(table, res, context));
  app.post(`${route}/batch`, (req, res) => saveAssetsBatch(table, req.body, res, `${context} BATCH`));
});

// 4. Legacy/Auxiliary (History & Assignment)
app.get('/api/asset/history', (req, res) => fetchAssets('asset_history', res, 'HISTORY'));
app.post('/api/asset/history/batch', async (req, res) => {
    // Custom logic for history as it might not follow the random-id pattern
    const connection = await pool.getConnection();
    try {
        await connection.beginTransaction();
        await connection.query('DELETE FROM asset_history');
        for (const item of req.body) {
            const dbRow = {
                asset_id: item.assetId,
                log_date: item.date,
                log_user: item.user,
                details: item.details,
                cost: item.cost || 0
            };
            await connection.query('INSERT INTO asset_history SET ?', [dbRow]);
        }
        await connection.commit();
        res.json({ success: true });
    } catch (err) { await connection.rollback(); handleError(res, err, 'BATCH HISTORY'); } finally { connection.release(); }
});

// 5. Utility
app.get('/api/generate-asset-code', async (req, res) => {
  try {
    const { prefix } = req.query;
    if (!prefix) return res.status(400).json({ error: 'Prefix is required' });
    
    // Search in multiple tables if necessary, but typically prefix-based tables are known
    const tables = ['asset_pc', 'asset_server', 'asset_storage', 'asset_network', 'asset_survey', 'asset_pc_parts', 'asset_equipment', 'asset_office_supplies', 'asset_vip'];
    let lastCode = '';
    
    for (const table of tables) {
        const [rows] = await pool.query(`SELECT asset_code FROM ${table} WHERE asset_code LIKE ? ORDER BY asset_code DESC LIMIT 1`, [`${prefix}%`]);
        if (rows.length > 0 && rows[0].asset_code > lastCode) {
            lastCode = rows[0].asset_code;
        }
    }

    let nextNum = 1;
    if (lastCode) {
      const lastNum = parseInt(lastCode.split('-').pop() || '0');
      nextNum = lastNum + 1;
    }
    res.json({ nextCode: `${prefix}${String(nextNum).padStart(3, '0')}` });
  } catch (err) { handleError(res, err, 'GENERATE CODE'); }
});

app.listen(3000, '0.0.0.0', () => {
  console.log('📡 ITAM BACKEND SERVER RUNNING ON PORT 3000 (Multi-Table Optimized)');
});
