<?php
require_once 'Logger.php';

class Notifications {
    private $db;
    private $logger;

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

    public function register($username, $password, $role, $email, $branch_id) {
        $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
        $sql = "INSERT INTO users (username, password, role, email, branch_id) VALUES (:username, :password, :role, :email, :branch_id)";
        $stmt = $this->db->prepare($sql);
        $stmt->bindParam(':username', $username);
        $stmt->bindParam(':password', $hashedPassword);
        $stmt->bindParam(':role', $role);
        $stmt->bindParam(':email', $email);
        $stmt->bindParam(':branch_id', $branch_id);

        $result = $stmt->execute();

        if ($result && $this->logger) {
            $userId = $this->db->lastInsertId();
            $this->logger->logUser('CREATE', $userId, [
                'username' => $username,
                'role' => $role,
                'email' => $email,
                'branch_id' => $branch_id
            ]);
        }

        return $result;
    }

    public function login($username, $password) {
        $sql = "SELECT * FROM users WHERE username = :username";
        $stmt = $this->db->prepare($sql);
        $stmt->bindParam(':username', $username);
        $stmt->execute();
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($user) {
            if (password_verify($password, $user['password'])) {
                return $user;
            } else {
                error_log("Password verification failed for username: $username");
            }
        } else {
            error_log("User not found: $username");
        }
        return false;
    }

    public function getUserById($id) {
        $sql = "SELECT * FROM users WHERE user_id = :id";
        $stmt = $this->db->prepare($sql);
        $stmt->bindParam(':id', $id);
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    public function markMessage($notification_id) {
        
        $query = "UPDATE notifications SET is_read = 1  WHERE notification_id = :notification_id";
		
		$stmt = $this->db->prepare($query);
		$stmt->bindParam(':notification_id', $notification_id);
		$result = $stmt->execute();
		return $result;
    }

    public function createNotification($branchId, $message, $target = 'Admin', $type = 0, $dedupe = true) {
        $target = strtolower($target) === 'branch' ? 'branch' : 'Admin';

        if ($dedupe) {
            $query = "SELECT notification_id
                      FROM notifications
                      WHERE branch_id = :branch_id
                        AND LOWER(target) = LOWER(:target)
                        AND message = :message
                        AND type = :type
                      LIMIT 1";
            $stmt = $this->db->prepare($query);
            $stmt->bindValue(':branch_id', $branchId, PDO::PARAM_INT);
            $stmt->bindValue(':target', $target);
            $stmt->bindValue(':message', $message);
            $stmt->bindValue(':type', $type, PDO::PARAM_INT);
            $stmt->execute();

            $existingId = $stmt->fetchColumn();
            if ($existingId) {
                return $existingId;
            }
        }

        $query = "INSERT INTO notifications (branch_id, message, target, type, created_at)
                  VALUES (:branch_id, :message, :target, :type, NOW())";
        $stmt = $this->db->prepare($query);
        $stmt->bindValue(':branch_id', $branchId, PDO::PARAM_INT);
        $stmt->bindValue(':message', $message);
        $stmt->bindValue(':target', $target);
        $stmt->bindValue(':type', $type, PDO::PARAM_INT);

        return $stmt->execute() ? $this->db->lastInsertId() : false;
    }

    public function extractTransactionIdFromMessage($message) {
        if (!is_string($message)) {
            return null;
        }

        if (preg_match('/\btransaction(?:\s+(?:id|number|no\.?|#))?\s*[:#-]?\s*([A-Za-z0-9_-]+)/i', $message, $matches)) {
            return rtrim($matches[1], ".:,; \t\n\r\0\x0B");
        }

        if (preg_match('/\bTXN[-_][A-Za-z0-9_-]+/i', $message, $matches)) {
            return rtrim($matches[0], ".:,; \t\n\r\0\x0B");
        }

        if (preg_match('/\bTXN[A-Za-z0-9_-]+/i', $message, $matches)) {
            return rtrim($matches[0], ".:,; \t\n\r\0\x0B");
        }

        return null;
    }

    public function getPreviewLinkForNotification(array $notification) {
        $message = $notification['message'] ?? '';
        if (!is_string($message) || trim($message) === '') {
            return null;
        }

        $branchId = isset($notification['branch_id']) ? (int)$notification['branch_id'] : 0;
        $target = strtolower(trim($notification['target'] ?? ''));

        $transactionId = $this->extractTransactionIdFromMessage($message);
        if ($transactionId) {
            return [
                'url' => '../tracking/txn_tracking.php?transaction_id=' . urlencode($transactionId),
                'label' => 'Preview sale'
            ];
        }

        if (preg_match('/\bshipment\s*#?\s*(\d+)/i', $message, $matches)) {
            return [
                'url' => '../shipments/view_shipment.php?id=' . (int)$matches[1],
                'label' => 'Preview transfer'
            ];
        }

        if (preg_match('/\breport\s*#?\s*(\d+)/i', $message, $matches)) {
            $reportId = (int)$matches[1];
            $isEditRequest = stripos($message, 'edit') !== false || stripos($message, 'error #9001') !== false;
            $url = ($target === 'branch' && $isEditRequest)
                ? '../sales/weekly3.php?report_id=' . $reportId
                : '../reports/view_report.php?report_id=' . $reportId;

            return [
                'url' => $url,
                'label' => $isEditRequest ? 'Preview report edit' : 'Preview report'
            ];
        }

        if (preg_match('/\bdeposit\s*#?\s*(\d+)/i', $message, $matches)) {
            return [
                'url' => '../sales/view_deposit.php?id=' . (int)$matches[1],
                'label' => 'Preview deposit'
            ];
        }

        if (preg_match('/\blaybuy payment\s*#?\s*(\d+)\s+for\s+record\s*#?\s*(\d+)/i', $message, $matches)) {
            return [
                'url' => '../laybuy_&_loans/pay_loan_or_laybuy.php?record_id=' . (int)$matches[2] . ($branchId ? '&branch_id=' . $branchId : ''),
                'label' => 'Preview laybuy'
            ];
        }

        if (preg_match('/\b(loan|laybuy)\s+record\s+([A-Za-z0-9_-]+)/i', $message, $matches)) {
            $record = $this->getLoanLaybuyRecordByNumber($matches[2]);
            if ($record) {
                return [
                    'url' => '../laybuy_&_loans/pay_loan_or_laybuy.php?record_id=' . (int)$record['record_id'] . '&branch_id=' . (int)$record['branch_id'],
                    'label' => 'Preview ' . strtolower($matches[1])
                ];
            }
        }

        return null;
    }

    private function getLoanLaybuyRecordByNumber($recordNumber) {
        $query = "SELECT record_id, branch_id FROM loans_laybuys WHERE record_number = :record_number LIMIT 1";
        $stmt = $this->db->prepare($query);
        $stmt->bindValue(':record_number', $recordNumber);
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }

    public function markMessageForTarget($notification_id, $branchId, $isAdmin = false) {
        if ($isAdmin) {
            $query = "UPDATE notifications
                      SET is_read = 1
                      WHERE notification_id = :notification_id
                        AND LOWER(TRIM(target)) = 'admin'";
            $stmt = $this->db->prepare($query);
            $stmt->bindValue(':notification_id', $notification_id, PDO::PARAM_INT);
            return $stmt->execute() && $stmt->rowCount() > 0;
        }

        $query = "UPDATE notifications
                  SET is_read = 1
                  WHERE notification_id = :notification_id
                    AND branch_id = :branch_id
                    AND LOWER(TRIM(target)) = 'branch'";
        $stmt = $this->db->prepare($query);
        $stmt->bindValue(':notification_id', $notification_id, PDO::PARAM_INT);
        $stmt->bindValue(':branch_id', $branchId, PDO::PARAM_INT);
        return $stmt->execute() && $stmt->rowCount() > 0;
    }

    public function deleteUser($id) {
        // Get user info for logging before deletion
        $userInfo = null;
        if ($this->logger) {
            $userInfo = $this->getUserById($id);
        }

        $query = "DELETE FROM users WHERE user_id = :id";
        $stmt = $this->db->prepare($query);
        $stmt->bindParam(':id', $id);
        $result = $stmt->execute();

        if ($result && $this->logger && $userInfo) {
            $this->logger->logUser('DELETE', $id, null, $userInfo);
        }

        return $result;
    }

    public function getUnreadnotification($userBranchId) {
        $query = "SELECT * FROM notifications
                  WHERE branch_id = :branch_id
                    AND LOWER(target) = 'branch'
                    AND is_read = 0
                  ORDER BY created_at DESC, notification_id DESC";
        $stmt = $this->db->prepare($query);
        $stmt->bindValue(':branch_id', $userBranchId, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
	
	 public function getUnreadnotificationAdmin() {
        $query = "SELECT * FROM notifications
                  WHERE LOWER(TRIM(target)) = 'admin'
                    AND is_read = 0
                  ORDER BY created_at DESC, notification_id DESC";
        $stmt = $this->db->prepare($query);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function getUserBranch($userId) {
        $query = "SELECT branch_id FROM users WHERE user_id = :user_id";
        $stmt = $this->db->prepare($query);
        $stmt->bindParam(':user_id', $userId);
        $stmt->execute();
        return $stmt->fetchColumn();
    }

    public function isUserInBranch($userId, $branchId) {
        $query = "SELECT COUNT(*) FROM users WHERE user_id = :user_id AND branch_id = :branch_id";
        $stmt = $this->db->prepare($query);
        $stmt->bindParam(':user_id', $userId);
        $stmt->bindParam(':branch_id', $branchId);
        $stmt->execute();
        return $stmt->fetchColumn() > 0;
    }
}
?>
