<?php
/**
 * Service de gestion des escalades
 * Gère les tickets et demandes de chat en temps réel
 */

namespace App\Services;

use Core\Database;

require_once APP_PATH . '/Services/EmailService.php';

class EscalationService
{
    private $db;
    private $emailService;

    public function __construct()
    {
        $this->db = Database::getInstance();
        $this->emailService = new EmailService();
    }

    /**
     * Génère un numéro de ticket unique
     */
    public function generateTicketNumber(int $entrepriseId): string
    {
        // Incrémenter le compteur de tickets
        $this->db->query(
            "UPDATE entreprises SET ticket_counter = ticket_counter + 1 WHERE id = :id",
            ['id' => $entrepriseId]
        );
        
        $entreprise = $this->db->fetch(
            "SELECT ticket_counter, slug FROM entreprises WHERE id = :id",
            ['id' => $entrepriseId]
        );
        
        $prefix = strtoupper(substr($entreprise['slug'] ?? 'TKT', 0, 3));
        $number = str_pad($entreprise['ticket_counter'], 6, '0', STR_PAD_LEFT);
        $year = date('y');
        
        return "{$prefix}-{$year}{$number}";
    }

    /**
     * Crée un ticket de support
     */
    public function createTicket(array $data): array
    {
        $ticketNumber = $this->generateTicketNumber($data['entreprise_id']);
        
        $ticketId = $this->db->insert('support_tickets', [
            'entreprise_id' => $data['entreprise_id'],
            'conversation_id' => $data['conversation_id'] ?? null,
            'client_id' => $data['client_id'],
            'ticket_number' => $ticketNumber,
            'sujet' => $data['sujet'] ?? 'Demande d\'assistance',
            'description' => $data['description'] ?? '',
            'categorie' => $data['categorie'] ?? 'general',
            'priorite' => $data['priorite'] ?? 'medium',
            'source' => $data['source'] ?? 'chat_escalation',
            'created_at' => date('Y-m-d H:i:s')
        ]);

        // Mettre à jour la conversation
        if (!empty($data['conversation_id'])) {
            $this->db->query(
                "UPDATE conversations SET 
                    escalation_type = 'ticket', 
                    ticket_id = :tid,
                    is_escalated = TRUE,
                    escalated_at = NOW()
                 WHERE id = :cid",
                ['tid' => $ticketId, 'cid' => $data['conversation_id']]
            );
        }

        // Créer notification pour les agents
        $this->createAgentNotification([
            'entreprise_id' => $data['entreprise_id'],
            'type' => 'new_ticket',
            'titre' => "Nouveau ticket: {$ticketNumber}",
            'message' => $data['sujet'] ?? 'Un client a créé un ticket de support',
            'reference_type' => 'ticket',
            'reference_id' => $ticketId,
            'is_urgent' => ($data['priorite'] ?? 'medium') === 'urgent'
        ]);

        // Envoyer email de confirmation au client
        $this->sendTicketEmails($ticketId, $ticketNumber, $data);

        return [
            'ticket_id' => $ticketId,
            'ticket_number' => $ticketNumber
        ];
    }

    /**
     * Envoie les emails liés à un ticket
     */
    private function sendTicketEmails(int $ticketId, string $ticketNumber, array $data): void
    {
        // Récupérer les infos complètes
        $entreprise = $this->db->fetch(
            "SELECT * FROM entreprises WHERE id = :id",
            ['id' => $data['entreprise_id']]
        );

        $client = $this->db->fetch(
            "SELECT * FROM clients WHERE id = :id",
            ['id' => $data['client_id']]
        );

        if (!$entreprise || !$client) return;

        // Vérifier si les notifications email sont activées
        if (empty($entreprise['email_notifications'])) return;

        $ticket = [
            'id' => $ticketId,
            'ticket_number' => $ticketNumber,
            'sujet' => $data['sujet'] ?? 'Demande d\'assistance'
        ];

        // Email au client
        $this->emailService->sendTicketCreated($ticket, $client, $entreprise);

        // Email aux agents
        $agents = $this->db->fetchAll(
            "SELECT * FROM users WHERE entreprise_id = :eid AND role = 'agent' AND is_active = TRUE",
            ['eid' => $data['entreprise_id']]
        );

        if (!empty($agents)) {
            $escalation = [
                'type' => 'ticket',
                'client_nom' => $client['nom'] ?? 'Client',
                'reason' => $data['sujet'] ?? ''
            ];
            $this->emailService->sendEscalationAlert($escalation, $agents, $entreprise);
        }
    }

    /**
     * Crée une demande de chat en temps réel
     */
    public function createLiveRequest(array $data): array
    {
        // Vérifier si une demande existe déjà pour cette conversation
        $existing = $this->db->fetch(
            "SELECT id FROM live_assistance_requests 
             WHERE conversation_id = :cid AND statut IN ('waiting', 'assigned', 'active')",
            ['cid' => $data['conversation_id']]
        );

        if ($existing) {
            return [
                'request_id' => $existing['id'],
                'status' => 'already_waiting',
                'position' => $this->getQueuePosition($data['entreprise_id'], $existing['id'])
            ];
        }

        $requestId = $this->db->insert('live_assistance_requests', [
            'entreprise_id' => $data['entreprise_id'],
            'conversation_id' => $data['conversation_id'],
            'client_id' => $data['client_id'],
            'reason' => $data['reason'] ?? '',
            'priority_score' => $this->calculatePriority($data),
            'wait_started_at' => date('Y-m-d H:i:s'),
            'created_at' => date('Y-m-d H:i:s')
        ]);

        // Mettre à jour la conversation
        $this->db->query(
            "UPDATE conversations SET 
                escalation_type = 'live_chat', 
                live_request_id = :rid,
                is_escalated = TRUE,
                escalated_at = NOW()
             WHERE id = :cid",
            ['rid' => $requestId, 'cid' => $data['conversation_id']]
        );

        // Créer notification urgente pour les agents
        $this->createAgentNotification([
            'entreprise_id' => $data['entreprise_id'],
            'type' => 'live_request',
            'titre' => "Demande de chat en direct",
            'message' => $data['reason'] ?? 'Un client souhaite parler à un agent',
            'reference_type' => 'live_request',
            'reference_id' => $requestId,
            'is_urgent' => true
        ]);

        // Envoyer email aux agents
        $this->sendLiveRequestEmails($requestId, $data);

        return [
            'request_id' => $requestId,
            'status' => 'waiting',
            'position' => $this->getQueuePosition($data['entreprise_id'], $requestId)
        ];
    }

    /**
     * Envoie les emails pour demande de chat live
     */
    private function sendLiveRequestEmails(int $requestId, array $data): void
    {
        $entreprise = $this->db->fetch(
            "SELECT * FROM entreprises WHERE id = :id",
            ['id' => $data['entreprise_id']]
        );

        $client = $this->db->fetch(
            "SELECT * FROM clients WHERE id = :id",
            ['id' => $data['client_id']]
        );

        if (!$entreprise || empty($entreprise['email_notifications'])) return;

        $agents = $this->db->fetchAll(
            "SELECT * FROM users WHERE entreprise_id = :eid AND role = 'agent' AND is_active = TRUE",
            ['eid' => $data['entreprise_id']]
        );

        if (!empty($agents)) {
            $escalation = [
                'type' => 'live_chat',
                'client_nom' => $client['nom'] ?? 'Client',
                'reason' => $data['reason'] ?? 'Demande de chat en direct'
            ];
            $this->emailService->sendEscalationAlert($escalation, $agents, $entreprise);
        }
    }

    /**
     * Calcule la priorité d'une demande
     */
    private function calculatePriority(array $data): int
    {
        $score = 50;
        
        // Augmenter si mots-clés urgents
        $urgentKeywords = ['urgent', 'grave', 'important', 'problème', 'erreur', 'bug'];
        $reason = strtolower($data['reason'] ?? '');
        
        foreach ($urgentKeywords as $keyword) {
            if (strpos($reason, $keyword) !== false) {
                $score += 10;
            }
        }
        
        return min(100, $score);
    }

    /**
     * Position dans la file d'attente
     */
    public function getQueuePosition(int $entrepriseId, int $requestId): int
    {
        $result = $this->db->fetch(
            "SELECT COUNT(*) as position FROM live_assistance_requests 
             WHERE entreprise_id = :eid 
             AND statut = 'waiting' 
             AND id <= :rid",
            ['eid' => $entrepriseId, 'rid' => $requestId]
        );
        
        return $result['position'] ?? 1;
    }

    /**
     * Crée une notification pour les agents
     */
    public function createAgentNotification(array $data): void
    {
        $this->db->insert('agent_notifications', [
            'entreprise_id' => $data['entreprise_id'],
            'agent_id' => $data['agent_id'] ?? null,
            'type' => $data['type'],
            'titre' => $data['titre'],
            'message' => $data['message'] ?? '',
            'reference_type' => $data['reference_type'] ?? null,
            'reference_id' => $data['reference_id'] ?? null,
            'is_urgent' => $data['is_urgent'] ?? false,
            'created_at' => date('Y-m-d H:i:s')
        ]);
    }

    /**
     * Récupère les demandes en attente pour une entreprise
     */
    public function getPendingRequests(int $entrepriseId): array
    {
        return $this->db->fetchAll(
            "SELECT lr.*, c.nom as client_nom, c.telephone, c.email,
                    conv.canal, conv.sujet as conversation_sujet
             FROM live_assistance_requests lr
             JOIN clients c ON lr.client_id = c.id
             JOIN conversations conv ON lr.conversation_id = conv.id
             WHERE lr.entreprise_id = :eid 
             AND lr.statut = 'waiting'
             ORDER BY lr.priority_score DESC, lr.wait_started_at ASC",
            ['eid' => $entrepriseId]
        );
    }

    /**
     * Récupère les tickets ouverts
     */
    public function getOpenTickets(int $entrepriseId): array
    {
        return $this->db->fetchAll(
            "SELECT t.*, c.nom as client_nom, c.telephone, c.email,
                    u.nom as agent_nom, u.prenom as agent_prenom
             FROM support_tickets t
             JOIN clients c ON t.client_id = c.id
             LEFT JOIN users u ON t.assigned_agent_id = u.id
             WHERE t.entreprise_id = :eid 
             AND t.statut NOT IN ('resolved', 'closed')
             ORDER BY 
                CASE t.priorite 
                    WHEN 'urgent' THEN 1 
                    WHEN 'high' THEN 2 
                    WHEN 'medium' THEN 3 
                    ELSE 4 
                END,
                t.created_at ASC",
            ['eid' => $entrepriseId]
        );
    }

    /**
     * Assigner un agent à une demande live
     */
    public function assignLiveRequest(int $requestId, int $agentId): bool
    {
        $this->db->query(
            "UPDATE live_assistance_requests SET 
                statut = 'assigned',
                assigned_agent_id = :aid,
                assigned_at = NOW()
             WHERE id = :rid",
            ['aid' => $agentId, 'rid' => $requestId]
        );

        // Mettre à jour la conversation
        $request = $this->db->fetch(
            "SELECT conversation_id FROM live_assistance_requests WHERE id = :id",
            ['id' => $requestId]
        );

        if ($request) {
            $this->db->query(
                "UPDATE conversations SET 
                    agent_id = :aid,
                    statut = 'in_progress'
                 WHERE id = :cid",
                ['aid' => $agentId, 'cid' => $request['conversation_id']]
            );
        }

        return true;
    }

    /**
     * Assigner un agent à un ticket
     */
    public function assignTicket(int $ticketId, int $agentId): bool
    {
        $this->db->query(
            "UPDATE support_tickets SET 
                statut = 'assigned',
                assigned_agent_id = :aid,
                updated_at = NOW()
             WHERE id = :tid",
            ['aid' => $agentId, 'tid' => $ticketId]
        );

        return true;
    }

    /**
     * Récupère les notifications non lues pour un agent
     */
    public function getUnreadNotifications(int $entrepriseId, ?int $agentId = null): array
    {
        $sql = "SELECT * FROM agent_notifications 
                WHERE entreprise_id = :eid 
                AND is_read = FALSE";
        $params = ['eid' => $entrepriseId];

        if ($agentId) {
            $sql .= " AND (agent_id IS NULL OR agent_id = :aid)";
            $params['aid'] = $agentId;
        }

        $sql .= " ORDER BY is_urgent DESC, created_at DESC LIMIT 50";

        return $this->db->fetchAll($sql, $params);
    }

    /**
     * Marquer notifications comme lues
     */
    public function markNotificationsRead(array $ids): void
    {
        if (empty($ids)) return;
        
        $placeholders = implode(',', array_fill(0, count($ids), '?'));
        $this->db->query(
            "UPDATE agent_notifications SET is_read = TRUE WHERE id IN ($placeholders)",
            $ids
        );
    }

    /**
     * Compte les éléments en attente pour le dashboard
     */
    public function getDashboardCounts(int $entrepriseId): array
    {
        $liveRequests = $this->db->fetch(
            "SELECT COUNT(*) as count FROM live_assistance_requests 
             WHERE entreprise_id = :eid AND statut = 'waiting'",
            ['eid' => $entrepriseId]
        );

        $openTickets = $this->db->fetch(
            "SELECT COUNT(*) as count FROM support_tickets 
             WHERE entreprise_id = :eid AND statut NOT IN ('resolved', 'closed')",
            ['eid' => $entrepriseId]
        );

        $unreadNotifications = $this->db->fetch(
            "SELECT COUNT(*) as count FROM agent_notifications 
             WHERE entreprise_id = :eid AND is_read = FALSE",
            ['eid' => $entrepriseId]
        );

        $urgentItems = $this->db->fetch(
            "SELECT COUNT(*) as count FROM agent_notifications 
             WHERE entreprise_id = :eid AND is_read = FALSE AND is_urgent = TRUE",
            ['eid' => $entrepriseId]
        );

        return [
            'live_requests' => $liveRequests['count'] ?? 0,
            'open_tickets' => $openTickets['count'] ?? 0,
            'notifications' => $unreadNotifications['count'] ?? 0,
            'urgent' => $urgentItems['count'] ?? 0
        ];
    }

    /**
     * Vérifier le statut d'une demande live
     */
    public function checkLiveRequestStatus(int $conversationId): ?array
    {
        return $this->db->fetch(
            "SELECT lr.*, u.nom as agent_nom, u.prenom as agent_prenom
             FROM live_assistance_requests lr
             LEFT JOIN users u ON lr.assigned_agent_id = u.id
             WHERE lr.conversation_id = :cid
             ORDER BY lr.created_at DESC LIMIT 1",
            ['cid' => $conversationId]
        );
    }

    /**
     * Vérifier le statut d'un ticket
     */
    public function getTicketByConversation(int $conversationId): ?array
    {
        return $this->db->fetch(
            "SELECT t.*, u.nom as agent_nom, u.prenom as agent_prenom
             FROM support_tickets t
             LEFT JOIN users u ON t.assigned_agent_id = u.id
             WHERE t.conversation_id = :cid
             ORDER BY t.created_at DESC LIMIT 1",
            ['cid' => $conversationId]
        );
    }
}
