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

class Ticket {
    /**
     * Get all tickets with filters and related data
     */
    static getAll(filters = {}) {
        const db = getDatabase();

        let where = [];
        let params = [];

        if (filters.status) {
            where.push('t.status = ?');
            params.push(filters.status);
        }
        if (filters.priority) {
            where.push('t.priority = ?');
            params.push(filters.priority);
        }
        if (filters.category) {
            where.push('t.category = ?');
            params.push(filters.category);
        }
        if (filters.assigned_to) {
            where.push('t.assigned_to_user_id = ?');
            params.push(filters.assigned_to);
        }
        if (filters.created_by_user_id) {
            where.push('t.created_by_user_id = ?');
            params.push(filters.created_by_user_id);
        }
        // User scope: tickets created by user OR where user is the requester (by email)
        if (filters.user_scope) {
            where.push('(t.created_by_user_id = ? OR LOWER(t.requester_email) = LOWER(?))');
            params.push(filters.user_scope.userId, filters.user_scope.email);
        }
        if (filters.search) {
            where.push('(t.title LIKE ? OR t.description LIKE ? OR t.ticket_number LIKE ? OR t.requester_name LIKE ?)');
            const s = `%${filters.search}%`;
            params.push(s, s, s, s);
        }

        const whereClause = where.length > 0 ? 'WHERE ' + where.join(' AND ') : '';

        const stmt = db.prepare(`
            SELECT
                t.*,
                au.username as assigned_to_username,
                au.first_name as assigned_to_first_name,
                au.last_name as assigned_to_last_name,
                cu.username as created_by_username,
                a.name as asset_name,
                a.serial_number as asset_serial,
                a.teamviewer_id as asset_teamviewer_id
            FROM tickets t
            LEFT JOIN users au ON t.assigned_to_user_id = au.id
            LEFT JOIN users cu ON t.created_by_user_id = cu.id
            LEFT JOIN assets a ON t.asset_id = a.id
            ${whereClause}
            ORDER BY
                CASE t.priority
                    WHEN 'kritisch' THEN 1
                    WHEN 'hoch' THEN 2
                    WHEN 'mittel' THEN 3
                    WHEN 'niedrig' THEN 4
                END,
                t.created_at DESC
        `);

        return stmt.all(...params);
    }

    /**
     * Get a single ticket by ID with all related data
     */
    static getById(id) {
        const db = getDatabase();
        const stmt = db.prepare(`
            SELECT
                t.*,
                au.username as assigned_to_username,
                au.first_name as assigned_to_first_name,
                au.last_name as assigned_to_last_name,
                au.email as assigned_to_email,
                cu.username as created_by_username,
                cu.first_name as created_by_first_name,
                cu.last_name as created_by_last_name,
                a.name as asset_name,
                a.serial_number as asset_serial,
                a.type as asset_type,
                a.teamviewer_id as asset_teamviewer_id
            FROM tickets t
            LEFT JOIN users au ON t.assigned_to_user_id = au.id
            LEFT JOIN users cu ON t.created_by_user_id = cu.id
            LEFT JOIN assets a ON t.asset_id = a.id
            WHERE t.id = ?
        `);
        const ticket = stmt.get(id);
        if (ticket) ticket.assignees = Ticket.getAssignees(id);
        return ticket;
    }

    /**
     * Get ticket by email Message-ID (for deduplication)
     */
    static getByEmailMessageId(messageId) {
        const db = getDatabase();
        return db.prepare('SELECT id FROM tickets WHERE email_message_id = ?').get(messageId);
    }

    static getByTicketNumber(ticketNumber) {
        const db = getDatabase();
        return db.prepare('SELECT id, status FROM tickets WHERE ticket_number = ?').get(ticketNumber);
    }

    static getAssignees(ticketId) {
        const db = getDatabase();
        return db.prepare(`
            SELECT u.id, u.username, u.first_name, u.last_name, u.email, ta.assigned_at
            FROM ticket_assignees ta
            JOIN users u ON ta.user_id = u.id
            WHERE ta.ticket_id = ?
            ORDER BY ta.assigned_at ASC
        `).all(ticketId);
    }

    static addAssignee(ticketId, userId, assignedByUserId) {
        const db = getDatabase();
        try {
            db.prepare(`INSERT OR IGNORE INTO ticket_assignees (ticket_id, user_id, assigned_by_user_id) VALUES (?, ?, ?)`)
              .run(ticketId, userId, assignedByUserId || null);
            return true;
        } catch { return false; }
    }

    static removeAssignee(ticketId, userId) {
        const db = getDatabase();
        return db.prepare('DELETE FROM ticket_assignees WHERE ticket_id = ? AND user_id = ?').run(ticketId, userId);
    }

    /**
     * Generate next ticket number: TK-YYYY-NNNN
     */
    static _generateTicketNumber(db) {
        const year = new Date().getFullYear();
        const prefix = `TK-${year}-`;
        const last = db.prepare(`
            SELECT ticket_number FROM tickets
            WHERE ticket_number LIKE ?
            ORDER BY id DESC LIMIT 1
        `).get(`${prefix}%`);

        let seq = 1;
        if (last) {
            const parts = last.ticket_number.split('-');
            seq = parseInt(parts[parts.length - 1]) + 1;
        }
        return `${prefix}${String(seq).padStart(4, '0')}`;
    }

    /**
     * Create a new ticket
     */
    static create(data) {
        const db = getDatabase();
        const ticketNumber = this._generateTicketNumber(db);

        const stmt = db.prepare(`
            INSERT INTO tickets (
                ticket_number, title, description, status, priority, category,
                source, requester_name, requester_email,
                assigned_to_user_id, created_by_user_id, asset_id, email_message_id
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        `);

        const result = stmt.run(
            ticketNumber,
            data.title,
            data.description || null,
            data.status || 'offen',
            data.priority || 'mittel',
            data.category || 'Allgemein',
            data.source || 'web',
            data.requester_name || null,
            data.requester_email || null,
            data.assigned_to_user_id || null,
            data.created_by_user_id || null,
            data.asset_id || null,
            data.email_message_id || null
        );

        return this.getById(result.lastInsertRowid);
    }

    /**
     * Update a ticket
     */
    static update(id, data) {
        const db = getDatabase();
        const fields = [];
        const values = [];

        const allowed = [
            'title', 'description', 'status', 'priority', 'category',
            'assigned_to_user_id', 'asset_id', 'requester_name', 'requester_email',
            'snoozed_until', 'ai_suggestion', 'ai_active',
            'satisfaction_rating', 'satisfaction_comment'
        ];

        for (const key of allowed) {
            if (data[key] !== undefined) {
                fields.push(`${key} = ?`);
                values.push(data[key] === '' ? null : data[key]);
            }
        }

        if (fields.length === 0) return this.getById(id);

        // Set resolved_at / closed_at timestamps
        if (data.status === 'geschlossen' && !fields.includes('resolved_at')) {
            fields.push('resolved_at = CURRENT_TIMESTAMP');
        }
        if (data.status === 'geschlossen') {
            fields.push('closed_at = CURRENT_TIMESTAMP');
        }

        fields.push('updated_at = CURRENT_TIMESTAMP');
        values.push(id);

        db.prepare(`UPDATE tickets SET ${fields.join(', ')} WHERE id = ?`).run(...values);
        return this.getById(id);
    }

    /**
     * Delete a ticket
     */
    static delete(id) {
        const db = getDatabase();
        return db.prepare('DELETE FROM tickets WHERE id = ?').run(id).changes > 0;
    }

    /**
     * Get ticket links
     */
    static getLinks(ticketId) {
        const db = getDatabase();
        return db.prepare(`
            SELECT tl.*, t.ticket_number, t.title, t.status, t.priority
            FROM ticket_links tl
            JOIN tickets t ON tl.linked_ticket_id = t.id
            WHERE tl.ticket_id = ?
            ORDER BY tl.created_at DESC
        `).all(ticketId);
    }

    static addLink(ticketId, linkedTicketId, linkType, userId) {
        const db = getDatabase();
        const result = db.prepare(`
            INSERT OR IGNORE INTO ticket_links (ticket_id, linked_ticket_id, link_type, created_by_user_id)
            VALUES (?, ?, ?, ?)
        `).run(ticketId, linkedTicketId, linkType || 'related', userId || null);
        return result.lastInsertRowid;
    }

    static removeLink(linkId) {
        const db = getDatabase();
        return db.prepare('DELETE FROM ticket_links WHERE id = ?').run(linkId).changes > 0;
    }

    /**
     * Get detailed metrics for the metrics page
     */
    static getMetrics(days = 30) {
        const db = getDatabase();

        // Tickets pro Tag
        const perDay = db.prepare(`
            SELECT DATE(created_at) as date, COUNT(*) as created,
                COUNT(CASE WHEN status IN ('geschlossen') THEN 1 END) as resolved
            FROM tickets
            WHERE created_at >= datetime('now', '-${parseInt(days)} days')
            GROUP BY DATE(created_at)
            ORDER BY date
        `).all();

        // Avg Lösungszeit in Stunden (nur gelöste/geschlossene)
        const avgResolution = db.prepare(`
            SELECT
                priority,
                ROUND(AVG(
                    (JULIANDAY(COALESCE(resolved_at, closed_at)) - JULIANDAY(created_at)) * 24
                ), 1) as avg_hours,
                COUNT(*) as count
            FROM tickets
            WHERE status IN ('geschlossen')
                AND COALESCE(resolved_at, closed_at) IS NOT NULL
            GROUP BY priority
        `).all();

        // Top-Bearbeiter
        const topAssignees = db.prepare(`
            SELECT
                u.username,
                u.first_name,
                u.last_name,
                COUNT(*) as total,
                COUNT(CASE WHEN t.status IN ('geschlossen') THEN 1 END) as resolved
            FROM tickets t
            JOIN users u ON t.assigned_to_user_id = u.id
            GROUP BY t.assigned_to_user_id
            ORDER BY resolved DESC
            LIMIT 5
        `).all();

        // Nach Kategorie
        const byCategory = db.prepare(`
            SELECT category, COUNT(*) as count,
                COUNT(CASE WHEN status NOT IN ('geschlossen') THEN 1 END) as open
            FROM tickets
            GROUP BY category
            ORDER BY count DESC
        `).all();

        // SLA-Verletzungen (offen und über SLA-Grenze)
        const slaBreaches = db.prepare(`
            SELECT priority, COUNT(*) as count
            FROM tickets
            WHERE status NOT IN ('geschlossen')
                AND (
                    (priority = 'kritisch' AND created_at <= datetime('now', '-24 hours')) OR
                    (priority = 'hoch' AND created_at <= datetime('now', '-48 hours')) OR
                    (priority = 'mittel' AND created_at <= datetime('now', '-168 hours')) OR
                    (priority = 'niedrig' AND created_at <= datetime('now', '-336 hours'))
                )
            GROUP BY priority
        `).all();

        // Kundenfeedback
        const satisfactionTotal = db.prepare(`
            SELECT
                COUNT(CASE WHEN satisfaction_rating = 'gut' THEN 1 END) as gut,
                COUNT(CASE WHEN satisfaction_rating = 'schlecht' THEN 1 END) as schlecht,
                COUNT(satisfaction_rating) as total
            FROM tickets
        `).get();

        const recentFeedback = db.prepare(`
            SELECT ticket_number, title, satisfaction_rating, satisfaction_comment,
                   requester_name, requester_email, updated_at
            FROM tickets
            WHERE satisfaction_rating IS NOT NULL
            ORDER BY updated_at DESC
            LIMIT 10
        `).all();

        return { perDay, avgResolution, topAssignees, byCategory, slaBreaches, satisfactionTotal, recentFeedback };
    }

    /**
     * Get ticket statistics for dashboard
     */
    static getStats() {
        const db = getDatabase();
        const byStatus = db.prepare(`
            SELECT status, COUNT(*) as count FROM tickets GROUP BY status
        `).all();

        const byPriority = db.prepare(`
            SELECT priority, COUNT(*) as count FROM tickets
            WHERE status NOT IN ('geschlossen')
            GROUP BY priority
        `).all();

        const total = db.prepare('SELECT COUNT(*) as count FROM tickets').get().count;
        const open = db.prepare("SELECT COUNT(*) as count FROM tickets WHERE status = 'offen'").get().count;
        const inProgress = db.prepare("SELECT COUNT(*) as count FROM tickets WHERE status = 'in_bearbeitung'").get().count;
        const critical = db.prepare("SELECT COUNT(*) as count FROM tickets WHERE priority = 'kritisch' AND status NOT IN ('geschlossen')").get().count;

        return { total, open, inProgress, critical, byStatus, byPriority };
    }
}

module.exports = Ticket;
