const { getDatabase } = require('../config/database');

class Asset {
    /**
     * Get all assets with related user information
     */
    static getAll({ departments } = {}) {
        const db = getDatabase();
        const where = departments && departments.length
            ? `WHERE a.department IN (${departments.map(() => '?').join(',')})`
            : '';
        const stmt = db.prepare(`
            SELECT
                a.*,
                au.username as assigned_to_username,
                au.email as assigned_to_email,
                cu.username as created_by_username,
                uu.username as updated_by_username
            FROM assets a
            LEFT JOIN users au ON a.assigned_to_user_id = au.id
            LEFT JOIN users cu ON a.created_by_user_id = cu.id
            LEFT JOIN users uu ON a.updated_by_user_id = uu.id
            ${where}
            ORDER BY a.created_at DESC
        `);
        return departments && departments.length ? stmt.all(...departments) : stmt.all();
    }

    /**
     * Get asset by ID
     */
    static getById(id) {
        const db = getDatabase();
        const stmt = db.prepare(`
            SELECT
                a.*,
                au.username as assigned_to_username,
                au.email as assigned_to_email,
                cu.username as created_by_username,
                uu.username as updated_by_username,
                wl.name as location_name
            FROM assets a
            LEFT JOIN users au ON a.assigned_to_user_id = au.id
            LEFT JOIN users cu ON a.created_by_user_id = cu.id
            LEFT JOIN users uu ON a.updated_by_user_id = uu.id
            LEFT JOIN warehouse_locations wl ON a.location_id = wl.id
            WHERE a.id = ?
        `);
        return stmt.get(id);
    }

    /**
     * Get asset by name (hostname match)
     */
    static getByName(name) {
        const db = getDatabase();
        return db.prepare('SELECT * FROM assets WHERE LOWER(name) = LOWER(?)').get(name);
    }

    /**
     * Get asset by serial number
     */
    static getBySerialNumber(serialNumber) {
        const db = getDatabase();
        const stmt = db.prepare(`
            SELECT
                a.*,
                au.username as assigned_to_username,
                cu.username as created_by_username,
                wl.name as location_name
            FROM assets a
            LEFT JOIN users au ON a.assigned_to_user_id = au.id
            LEFT JOIN users cu ON a.created_by_user_id = cu.id
            LEFT JOIN warehouse_locations wl ON a.location_id = wl.id
            WHERE a.serial_number = ?
        `);
        return stmt.get(serialNumber);
    }

    /**
     * Get assets by status
     */
    static getByStatus(status) {
        const db = getDatabase();
        const stmt = db.prepare(`
            SELECT
                a.*,
                au.username as assigned_to_username,
                cu.username as created_by_username
            FROM assets a
            LEFT JOIN users au ON a.assigned_to_user_id = au.id
            LEFT JOIN users cu ON a.created_by_user_id = cu.id
            WHERE a.status = ?
            ORDER BY a.created_at DESC
        `);
        return stmt.all(status);
    }

    /**
     * Get assets by type
     */
    static getByType(type) {
        const db = getDatabase();
        const stmt = db.prepare(`
            SELECT
                a.*,
                au.username as assigned_to_username,
                cu.username as created_by_username
            FROM assets a
            LEFT JOIN users au ON a.assigned_to_user_id = au.id
            LEFT JOIN users cu ON a.created_by_user_id = cu.id
            WHERE a.type = ?
            ORDER BY a.created_at DESC
        `);
        return stmt.all(type);
    }

    /**
     * Get assets assigned to a specific user
     */
    static getByAssignedUser(userId) {
        const db = getDatabase();
        const stmt = db.prepare(`
            SELECT
                a.*,
                cu.username as created_by_username
            FROM assets a
            LEFT JOIN users cu ON a.created_by_user_id = cu.id
            WHERE a.assigned_to_user_id = ?
            ORDER BY a.created_at DESC
        `);
        return stmt.all(userId);
    }

    /**
     * Create a new asset
     */
    static create(assetData) {
        const db = getDatabase();
        const stmt = db.prepare(`
            INSERT INTO assets (
                name,
                type,
                serial_number,
                model,
                status,
                purchase_date,
                description,
                teamviewer_id,
                assigned_to_user_id,
                created_by_user_id,
                last_maintenance_date,
                next_maintenance_date,
                maintenance_interval_months,
                maintenance_notes,
                department,
                inventory_number,
                purchase_price,
                useful_life_years,
                residual_value
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        `);

        const result = stmt.run(
            assetData.name,
            assetData.type,
            assetData.serial_number,
            assetData.model || null,
            assetData.status,
            assetData.purchase_date || null,
            assetData.description || null,
            assetData.teamviewer_id || null,
            assetData.assigned_to_user_id || null,
            assetData.created_by_user_id,
            assetData.last_maintenance_date || null,
            assetData.next_maintenance_date || null,
            assetData.maintenance_interval_months ? parseInt(assetData.maintenance_interval_months) : null,
            assetData.maintenance_notes || null,
            assetData.department || 'IT',
            assetData.inventory_number || null,
            assetData.purchase_price ? parseFloat(assetData.purchase_price) : null,
            assetData.useful_life_years ? parseInt(assetData.useful_life_years) : null,
            assetData.residual_value ? parseFloat(assetData.residual_value) : 0
        );

        return this.getById(result.lastInsertRowid);
    }

    /**
     * Update asset
     */
    static update(id, assetData, updatedByUserId) {
        const db = getDatabase();

        const fields = [];
        const values = [];

        if (assetData.name !== undefined) {
            fields.push('name = ?');
            values.push(assetData.name);
        }
        if (assetData.type !== undefined) {
            fields.push('type = ?');
            values.push(assetData.type);
        }
        if (assetData.serial_number !== undefined) {
            fields.push('serial_number = ?');
            values.push(assetData.serial_number);
        }
        if (assetData.model !== undefined) {
            fields.push('model = ?');
            values.push(assetData.model);
        }
        if (assetData.status !== undefined) {
            fields.push('status = ?');
            values.push(assetData.status);
        }
        if (assetData.purchase_date !== undefined) {
            fields.push('purchase_date = ?');
            values.push(assetData.purchase_date);
        }
        if (assetData.description !== undefined) {
            fields.push('description = ?');
            values.push(assetData.description);
        }
        if (assetData.teamviewer_id !== undefined) {
            fields.push('teamviewer_id = ?');
            values.push(assetData.teamviewer_id || null);
        }
        if (assetData.assigned_to_user_id !== undefined) {
            fields.push('assigned_to_user_id = ?');
            values.push(assetData.assigned_to_user_id);
        }
        if (assetData.last_maintenance_date !== undefined) {
            fields.push('last_maintenance_date = ?');
            values.push(assetData.last_maintenance_date || null);
        }
        if (assetData.next_maintenance_date !== undefined) {
            fields.push('next_maintenance_date = ?');
            values.push(assetData.next_maintenance_date || null);
        }
        if (assetData.maintenance_interval_months !== undefined) {
            fields.push('maintenance_interval_months = ?');
            values.push(assetData.maintenance_interval_months ? parseInt(assetData.maintenance_interval_months) : null);
        }
        if (assetData.maintenance_notes !== undefined) {
            fields.push('maintenance_notes = ?');
            values.push(assetData.maintenance_notes || null);
        }
        if (assetData.department !== undefined) {
            fields.push('department = ?');
            values.push(assetData.department || 'IT');
        }
        if (assetData.inventory_number !== undefined) {
            fields.push('inventory_number = ?');
            values.push(assetData.inventory_number || null);
        }
        if (assetData.purchase_price !== undefined) {
            fields.push('purchase_price = ?');
            values.push(assetData.purchase_price ? parseFloat(assetData.purchase_price) : null);
        }
        if (assetData.useful_life_years !== undefined) {
            fields.push('useful_life_years = ?');
            values.push(assetData.useful_life_years ? parseInt(assetData.useful_life_years) : null);
        }
        if (assetData.residual_value !== undefined) {
            fields.push('residual_value = ?');
            values.push(assetData.residual_value ? parseFloat(assetData.residual_value) : 0);
        }
        if (assetData.os !== undefined) {
            fields.push('os = ?');
            values.push(assetData.os || null);
        }
        if (assetData.ip_address !== undefined) {
            fields.push('ip_address = ?');
            values.push(assetData.ip_address || null);
        }
        if (assetData.manufacturer !== undefined) {
            fields.push('manufacturer = ?');
            values.push(assetData.manufacturer || null);
        }
        if (assetData.last_agent_sync !== undefined) {
            fields.push('last_agent_sync = ?');
            values.push(assetData.last_agent_sync || null);
        }

        fields.push('updated_by_user_id = ?');
        fields.push('updated_at = CURRENT_TIMESTAMP');
        values.push(updatedByUserId, id);

        const stmt = db.prepare(`
            UPDATE assets
            SET ${fields.join(', ')}
            WHERE id = ?
        `);

        stmt.run(...values);
        return this.getById(id);
    }

    /**
     * Update only the status
     */
    static updateStatus(id, status, updatedByUserId) {
        const db = getDatabase();
        const stmt = db.prepare(`
            UPDATE assets
            SET status = ?,
                updated_by_user_id = ?,
                updated_at = CURRENT_TIMESTAMP
            WHERE id = ?
        `);

        stmt.run(status, updatedByUserId, id);
        return this.getById(id);
    }

    /**
     * Delete asset
     */
    static delete(id) {
        const db = getDatabase();
        const stmt = db.prepare('DELETE FROM assets WHERE id = ?');
        const result = stmt.run(id);
        return result.changes > 0;
    }

    /**
     * Get statistics
     */
    static getStatistics({ departments } = {}) {
        const db = getDatabase();
        const dw = departments && departments.length
            ? `AND department IN (${departments.map(() => '?').join(',')})`
            : '';
        const dp = departments && departments.length ? departments : [];

        const q = (sql) => db.prepare(sql).get(...dp);

        return {
            total:      q(`SELECT COUNT(*) as v FROM assets WHERE 1=1 ${dw}`).v,
            verfuegbar: q(`SELECT COUNT(*) as v FROM assets WHERE status = 'verfuegbar' ${dw}`).v,
            zugewiesen: q(`SELECT COUNT(*) as v FROM assets WHERE status = 'zugewiesen' ${dw}`).v,
            inaktiv:    q(`SELECT COUNT(*) as v FROM assets WHERE status = 'inaktiv' ${dw}`).v,
            beschaedigt:q(`SELECT COUNT(*) as v FROM assets WHERE status = 'beschaedigt' ${dw}`).v,
            byType: {
                notebook: q(`SELECT COUNT(*) as v FROM assets WHERE type = 'Notebook' ${dw}`).v,
                monitor:  q(`SELECT COUNT(*) as v FROM assets WHERE type = 'Monitor' ${dw}`).v,
                headset:  q(`SELECT COUNT(*) as v FROM assets WHERE type = 'Headset' ${dw}`).v,
                other:    q(`SELECT COUNT(*) as v FROM assets WHERE type = 'Other' ${dw}`).v,
            }
        };
    }
}

module.exports = Asset;
