<?php
/**
 * Service Tickets Controller
 * CRUD for guest service requests + staff management
 */
class ServiceTicketsController {
    private $db;
    private $config;

    public function __construct($db, $config) {
        $this->db = $db;
        $this->config = $config;
    }

    private function generateTicketNumber() {
        $prefix = 'TK';
        $date = date('ymd');
        $stmt = $this->db->query("SELECT COUNT(*) FROM service_tickets WHERE DATE(created_at) = CURDATE()");
        $count = $stmt->fetchColumn() + 1;
        return $prefix . $date . str_pad($count, 3, '0', STR_PAD_LEFT);
    }

    public function create($data) {
        $required = ['property_id', 'category', 'request_type'];
        foreach ($required as $f) {
            if (empty($data[$f])) return ['success' => false, 'message' => "$f is required"];
        }

        try {
            $ticketNumber = $this->generateTicketNumber();
            $priority = $this->autoPriority($data['category'], $data['request_type']);

            $stmt = $this->db->prepare("
                INSERT INTO service_tickets (ticket_number, property_id, booking_id, guest_id, guest_name, room_number,
                    category, request_type, description, priority)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                $ticketNumber, $data['property_id'], $data['booking_id'] ?? null,
                $data['guest_id'] ?? null, $data['guest_name'] ?? 'Guest',
                $data['room_number'] ?? null, $data['category'],
                $data['request_type'], $data['description'] ?? null, $priority
            ]);

            $ticketId = $this->db->lastInsertId();

            // Auto-assign to available staff
            $this->autoAssign($ticketId, $data['property_id'], $data['category']);

            return [
                'success' => true,
                'message' => 'Request submitted',
                'ticket' => [
                    'id' => $ticketId,
                    'ticket_number' => $ticketNumber,
                    'status' => 'pending',
                    'priority' => $priority
                ]
            ];
        } catch (Exception $e) {
            error_log('Ticket create error: ' . $e->getMessage());
            return ['success' => false, 'message' => 'Failed to create request'];
        }
    }

    private function autoPriority($category, $requestType) {
        $urgentKeywords = ['not working', 'broken', 'emergency', 'leak', 'flood', 'fire', 'locked out', 'power issue'];
        $highKeywords = ['ac', 'water', 'door lock', 'no hot water'];
        $type = strtolower($requestType);
        foreach ($urgentKeywords as $k) { if (strpos($type, $k) !== false) return 'urgent'; }
        foreach ($highKeywords as $k) { if (strpos($type, $k) !== false) return 'high'; }
        if ($category === 'maintenance') return 'high';
        return 'medium';
    }

    private function autoAssign($ticketId, $propertyId, $category) {
        try {
            $stmt = $this->db->prepare("
                SELECT sp.id, sp.user_id, u.name, sp.phone, sp.whatsapp_enabled
                FROM staff_profiles sp
                JOIN users u ON u.id = sp.user_id
                WHERE sp.property_id = ? AND sp.department = ? AND sp.is_on_duty = 1
                ORDER BY (SELECT COUNT(*) FROM service_tickets st WHERE st.assigned_to = sp.user_id AND st.status IN ('pending','assigned','in_progress')) ASC
                LIMIT 1
            ");
            $stmt->execute([$propertyId, $category]);
            $staff = $stmt->fetch(PDO::FETCH_ASSOC);

            if ($staff) {
                $update = $this->db->prepare("UPDATE service_tickets SET assigned_to=?, assigned_at=NOW(), status='assigned' WHERE id=?");
                $update->execute([$staff['user_id'], $ticketId]);

                // Notify the assigned staff member on WhatsApp (two-way comms).
                if (!empty($staff['phone']) && !empty($staff['whatsapp_enabled'])) {
                    try {
                        require_once __DIR__ . '/../services/WhatsAppService.php';
                        $t = $this->db->prepare("SELECT id, ticket_number, guest_name, room_number, request_type, description, priority FROM service_tickets WHERE id=?");
                        $t->execute([$ticketId]);
                        $ticket = $t->fetch(PDO::FETCH_ASSOC);
                        if ($ticket) {
                            $wa = new WhatsAppService($this->db, $this->config, $propertyId);
                            $wa->sendTicketCreated($staff['phone'], $staff['name'], $ticket);
                        }
                    } catch (Exception $e) {
                        error_log('WA notify (ticket create) failed: ' . $e->getMessage());
                    }
                }
            }
        } catch (Exception $e) {
            // Silent — manual assignment will be needed
        }
    }

    public function getAll($filters = []) {
        try {
            $where = ['1=1'];
            $params = [];

            if (!empty($filters['property_id'])) { $where[] = 'st.property_id = ?'; $params[] = $filters['property_id']; }
            if (!empty($filters['status'])) { $where[] = 'st.status = ?'; $params[] = $filters['status']; }
            if (!empty($filters['category'])) { $where[] = 'st.category = ?'; $params[] = $filters['category']; }
            if (!empty($filters['assigned_to'])) { $where[] = 'st.assigned_to = ?'; $params[] = $filters['assigned_to']; }

            $sql = "SELECT st.*, u.name AS assigned_name
                    FROM service_tickets st
                    LEFT JOIN users u ON u.id = st.assigned_to
                    WHERE " . implode(' AND ', $where) . "
                    ORDER BY FIELD(st.priority,'urgent','high','medium','low'), st.created_at DESC
                    LIMIT 100";
            $stmt = $this->db->prepare($sql);
            $stmt->execute($params);

            return ['success' => true, 'tickets' => $stmt->fetchAll(PDO::FETCH_ASSOC)];
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Error fetching tickets'];
        }
    }

    public function getById($id) {
        try {
            $stmt = $this->db->prepare("SELECT st.*, u.name AS assigned_name FROM service_tickets st LEFT JOIN users u ON u.id=st.assigned_to WHERE st.id=?");
            $stmt->execute([$id]);
            $ticket = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$ticket) return ['success' => false, 'message' => 'Ticket not found'];
            return ['success' => true, 'ticket' => $ticket];
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Error'];
        }
    }

    public function updateStatus($ticketId, $status, $userId = null, $notes = null) {
        try {
            $timeCol = '';
            if ($status === 'in_progress') $timeCol = ', started_at=NOW()';
            if ($status === 'completed') $timeCol = ', completed_at=NOW()';
            if ($status === 'verified') $timeCol = ', verified_at=NOW()';

            $stmt = $this->db->prepare("UPDATE service_tickets SET status=?{$timeCol}, updated_at=NOW() WHERE id=?");
            $stmt->execute([$status, $ticketId]);
            return ['success' => true, 'message' => 'Status updated'];
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Update failed'];
        }
    }

    public function assign($ticketId, $staffUserId) {
        try {
            $stmt = $this->db->prepare("UPDATE service_tickets SET assigned_to=?, assigned_at=NOW(), status='assigned' WHERE id=?");
            $stmt->execute([$staffUserId, $ticketId]);
            return ['success' => true, 'message' => 'Ticket assigned'];
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Assignment failed'];
        }
    }

    public function rateTicket($ticketId, $rating, $feedback = null) {
        try {
            $stmt = $this->db->prepare("UPDATE service_tickets SET guest_rating=?, guest_feedback=? WHERE id=?");
            $stmt->execute([$rating, $feedback, $ticketId]);
            return ['success' => true, 'message' => 'Thank you for your feedback'];
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Rating failed'];
        }
    }

    public function getDashboardStats($propertyId) {
        try {
            $stats = [];
            $stmt = $this->db->prepare("SELECT status, COUNT(*) as cnt FROM service_tickets WHERE property_id=? GROUP BY status");
            $stmt->execute([$propertyId]);
            foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $r) { $stats[$r['status']] = (int)$r['cnt']; }

            $stmt = $this->db->prepare("SELECT AVG(TIMESTAMPDIFF(MINUTE, created_at, completed_at)) as avg_time FROM service_tickets WHERE property_id=? AND completed_at IS NOT NULL AND created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)");
            $stmt->execute([$propertyId]);
            $stats['avg_resolution_minutes'] = round($stmt->fetchColumn() ?? 0);

            $stmt = $this->db->prepare("SELECT AVG(guest_rating) as avg_rating FROM service_tickets WHERE property_id=? AND guest_rating IS NOT NULL");
            $stmt->execute([$propertyId]);
            $stats['avg_guest_rating'] = round($stmt->fetchColumn() ?? 0, 1);

            $stmt = $this->db->prepare("SELECT COUNT(*) FROM service_tickets WHERE property_id=? AND DATE(created_at)=CURDATE()");
            $stmt->execute([$propertyId]);
            $stats['today_total'] = (int)$stmt->fetchColumn();

            return ['success' => true, 'stats' => $stats];
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Stats error'];
        }
    }
}
