<?php
/**
 * FinoviaPay Telegram Bot
 * Customer Feedback / Poll Functions
 *
 * Fresh fixed updated working file
 * Includes optional comment system without requiring new SQL tables
 *
 * Required existing tables:
 * - bot_join_logs
 * - bot_feedback_polls
 * - bot_feedback_poll_options
 * - bot_feedback_poll_votes
 * - bot_feedback_poll_notifications
 *
 * Optional comment flow:
 * - Uses bot_feedback_poll_votes.comment_text
 * - Uses a small JSON state file for pending comment capture
 */

if (!function_exists('bfp_db')) {

    /* =========================================================
       CONFIG
    ========================================================= */

    function bfp_comment_state_file() {
        return __DIR__ . '/bot_feedback_poll_comment_state.json';
    }

    /* =========================================================
       DATABASE RESOLVER
    ========================================================= */

    function bfp_db() {
        global $pdo, $conn;

        if (isset($pdo) && $pdo instanceof PDO) {
            return ['type' => 'pdo', 'db' => $pdo];
        }

        if (isset($conn) && $conn instanceof mysqli) {
            return ['type' => 'mysqli', 'db' => $conn];
        }

        die('Database connection not found in config.php');
    }

    /* =========================================================
       BASIC DB HELPERS
    ========================================================= */

    function bfp_fetch($sql, array $params = []) {
        $db = bfp_db();

        if ($db['type'] === 'pdo') {
            $stmt = $db['db']->prepare($sql);
            $stmt->execute($params);
            return $stmt->fetch(PDO::FETCH_ASSOC);
        }

        $stmt = $db['db']->prepare($sql);
        if (!$stmt) {
            return null;
        }

        if (!empty($params)) {
            $types = '';
            $bind = [];

            foreach ($params as $param) {
                if (is_int($param)) {
                    $types .= 'i';
                } elseif (is_float($param)) {
                    $types .= 'd';
                } else {
                    $types .= 's';
                }
                $bind[] = $param;
            }

            $stmt->bind_param($types, ...$bind);
        }

        $stmt->execute();
        $result = $stmt->get_result();
        $row = $result ? $result->fetch_assoc() : null;
        $stmt->close();

        return $row;
    }

    function bfp_fetch_all($sql, array $params = []) {
        $db = bfp_db();

        if ($db['type'] === 'pdo') {
            $stmt = $db['db']->prepare($sql);
            $stmt->execute($params);
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        }

        $stmt = $db['db']->prepare($sql);
        if (!$stmt) {
            return [];
        }

        if (!empty($params)) {
            $types = '';
            $bind = [];

            foreach ($params as $param) {
                if (is_int($param)) {
                    $types .= 'i';
                } elseif (is_float($param)) {
                    $types .= 'd';
                } else {
                    $types .= 's';
                }
                $bind[] = $param;
            }

            $stmt->bind_param($types, ...$bind);
        }

        $stmt->execute();
        $result = $stmt->get_result();
        $rows = [];

        if ($result) {
            while ($row = $result->fetch_assoc()) {
                $rows[] = $row;
            }
        }

        $stmt->close();
        return $rows;
    }

    function bfp_exec($sql, array $params = []) {
        $db = bfp_db();

        if ($db['type'] === 'pdo') {
            $stmt = $db['db']->prepare($sql);
            $ok = $stmt->execute($params);

            return [
                'ok' => $ok,
                'insert_id' => $ok ? $db['db']->lastInsertId() : null,
                'error' => $ok ? '' : (($stmt->errorInfo()[2] ?? 'Database error'))
            ];
        }

        $stmt = $db['db']->prepare($sql);
        if (!$stmt) {
            return [
                'ok' => false,
                'insert_id' => null,
                'error' => 'MySQLi prepare failed: ' . $db['db']->error
            ];
        }

        if (!empty($params)) {
            $types = '';
            $bind = [];

            foreach ($params as $param) {
                if (is_int($param)) {
                    $types .= 'i';
                } elseif (is_float($param)) {
                    $types .= 'd';
                } else {
                    $types .= 's';
                }
                $bind[] = $param;
            }

            $stmt->bind_param($types, ...$bind);
        }

        $ok = $stmt->execute();
        $insertId = $ok ? $stmt->insert_id : null;
        $error = $stmt->error;
        $stmt->close();

        return [
            'ok' => $ok,
            'insert_id' => $insertId,
            'error' => $error
        ];
    }

    /* =========================================================
       USER / POLL HELPERS
    ========================================================= */

    function bfp_get_user_by_chat_id($chatId) {
        return bfp_fetch(
            "SELECT *
             FROM bot_join_logs
             WHERE telegram_chat_id = ?
             LIMIT 1",
            [(string)$chatId]
        );
    }

    function bfp_get_poll($pollId) {
        return bfp_fetch(
            "SELECT *
             FROM bot_feedback_polls
             WHERE id = ?
             LIMIT 1",
            [(int)$pollId]
        );
    }

    function bfp_get_active_poll($pollId) {
        $poll = bfp_get_poll($pollId);

        if (!$poll) {
            return null;
        }

        if (!isset($poll['status']) || $poll['status'] !== 'active') {
            return null;
        }

        $now = time();

        if (!empty($poll['start_at'])) {
            $start = strtotime($poll['start_at']);
            if ($start !== false && $now < $start) {
                return null;
            }
        }

        if (!empty($poll['expires_at'])) {
            $end = strtotime($poll['expires_at']);
            if ($end !== false && $now > $end) {
                return null;
            }
        }

        return $poll;
    }

    function bfp_get_poll_option($pollId, $optionId) {
        return bfp_fetch(
            "SELECT *
             FROM bot_feedback_poll_options
             WHERE poll_id = ?
               AND id = ?
               AND status = 'active'
             LIMIT 1",
            [(int)$pollId, (int)$optionId]
        );
    }

    function bfp_already_voted($pollId, $userId) {
        $row = bfp_fetch(
            "SELECT id
             FROM bot_feedback_poll_votes
             WHERE poll_id = ?
               AND user_id = ?
             LIMIT 1",
            [(int)$pollId, (int)$userId]
        );

        return $row ? true : false;
    }

    function bfp_get_vote_row($pollId, $userId) {
        return bfp_fetch(
            "SELECT *
             FROM bot_feedback_poll_votes
             WHERE poll_id = ?
               AND user_id = ?
             LIMIT 1",
            [(int)$pollId, (int)$userId]
        );
    }

    function bfp_save_vote($pollId, $optionId, $userId, $chatId) {
        return bfp_exec(
            "INSERT INTO bot_feedback_poll_votes
            (poll_id, option_id, user_id, telegram_chat_id, response_source, voted_at, created_at)
            VALUES (?, ?, ?, ?, 'telegram', NOW(), NOW())",
            [(int)$pollId, (int)$optionId, (int)$userId, (string)$chatId]
        );
    }

    function bfp_save_comment($pollId, $userId, $commentText) {
        return bfp_exec(
            "UPDATE bot_feedback_poll_votes
             SET comment_text = ?
             WHERE poll_id = ?
               AND user_id = ?
             LIMIT 1",
            [(string)$commentText, (int)$pollId, (int)$userId]
        );
    }

    function bfp_mark_notification_clicked($pollId, $userId) {
        return bfp_exec(
            "UPDATE bot_feedback_poll_notifications
             SET delivery_status = CASE
                    WHEN delivery_status IN ('pending','sent','read') THEN 'clicked'
                    ELSE delivery_status
                 END,
                 clicked_at = NOW()
             WHERE poll_id = ?
               AND user_id = ?",
            [(int)$pollId, (int)$userId]
        );
    }

    /* =========================================================
       COMMENT STATE FILE HELPERS
    ========================================================= */

    function bfp_read_comment_states() {
        $file = bfp_comment_state_file();

        if (!file_exists($file)) {
            return [];
        }

        $raw = @file_get_contents($file);
        if ($raw === false || $raw === '') {
            return [];
        }

        $data = json_decode($raw, true);
        return is_array($data) ? $data : [];
    }

    function bfp_write_comment_states(array $data) {
        $file = bfp_comment_state_file();
        return @file_put_contents($file, json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), LOCK_EX) !== false;
    }

    function bfp_set_pending_comment_state($chatId, $pollId, $userId) {
        $states = bfp_read_comment_states();
        $states[(string)$chatId] = [
            'poll_id' => (int)$pollId,
            'user_id' => (int)$userId,
            'created_at' => date('Y-m-d H:i:s')
        ];
        return bfp_write_comment_states($states);
    }

    function bfp_get_pending_comment_state($chatId) {
        $states = bfp_read_comment_states();
        return isset($states[(string)$chatId]) ? $states[(string)$chatId] : null;
    }

    function bfp_clear_pending_comment_state($chatId) {
        $states = bfp_read_comment_states();
        if (isset($states[(string)$chatId])) {
            unset($states[(string)$chatId]);
            return bfp_write_comment_states($states);
        }
        return true;
    }

    /* =========================================================
       MAIN VOTE HANDLER
       callback_data format: pollvote_{poll_id}_{option_id}
    ========================================================= */

    function bfp_handle_vote($chatId, $callbackData) {
        $parts = explode('_', (string)$callbackData);

        if (count($parts) !== 3) {
            return [
                'ok' => false,
                'message' => 'Invalid feedback request.'
            ];
        }

        $pollId = (int)$parts[1];
        $optionId = (int)$parts[2];

        if ($pollId <= 0 || $optionId <= 0) {
            return [
                'ok' => false,
                'message' => 'Invalid feedback request.'
            ];
        }

        $user = bfp_get_user_by_chat_id($chatId);
        if (!$user) {
            return [
                'ok' => false,
                'message' => 'Your customer record could not be found.'
            ];
        }

        $poll = bfp_get_active_poll($pollId);
        if (!$poll) {
            return [
                'ok' => false,
                'message' => 'This feedback request is no longer available.'
            ];
        }

        $option = bfp_get_poll_option($pollId, $optionId);
        if (!$option) {
            return [
                'ok' => false,
                'message' => 'The selected voting option is not valid.'
            ];
        }

        if (bfp_already_voted($pollId, (int)$user['id'])) {
            return [
                'ok' => false,
                'message' => 'Your response has already been recorded for this poll.'
            ];
        }

        $save = bfp_save_vote($pollId, $optionId, (int)$user['id'], $chatId);
        if (!$save['ok']) {
            return [
                'ok' => false,
                'message' => 'Unable to record your response at the moment. Please try again.'
            ];
        }

        bfp_mark_notification_clicked($pollId, (int)$user['id']);

        $allowComment = !empty($poll['allow_comment']) ? 1 : 0;

        if ($allowComment === 1) {
            bfp_set_pending_comment_state($chatId, $pollId, (int)$user['id']);

            return [
                'ok' => true,
                'message' => "✅ Thank you. Your vote has been recorded successfully.\n\nIf you would like to share an additional comment, please send it now as a new message.\n\nIf you do not want to add a comment, reply with: skip",
                'awaiting_comment' => true,
                'poll_id' => $pollId,
                'user_id' => (int)$user['id']
            ];
        }

        return [
            'ok' => true,
            'message' => '✅ Thank you. Your feedback has been recorded successfully.',
            'awaiting_comment' => false,
            'poll_id' => $pollId,
            'user_id' => (int)$user['id']
        ];
    }

    /* =========================================================
       COMMENT MESSAGE HANDLER
       Use this when a normal text message arrives after vote
    ========================================================= */

    function bfp_handle_comment_message($chatId, $messageText) {
        $state = bfp_get_pending_comment_state($chatId);

        if (!$state) {
            return [
                'handled' => false,
                'message' => ''
            ];
        }

        $pollId = isset($state['poll_id']) ? (int)$state['poll_id'] : 0;
        $userId = isset($state['user_id']) ? (int)$state['user_id'] : 0;
        $text = trim((string)$messageText);

        if ($pollId <= 0 || $userId <= 0) {
            bfp_clear_pending_comment_state($chatId);
            return [
                'handled' => true,
                'message' => 'Comment session expired. Please vote again if needed.'
            ];
        }

        if ($text === '') {
            return [
                'handled' => true,
                'message' => 'Please send your comment as a text message, or reply with: skip'
            ];
        }

        if (mb_strtolower($text, 'UTF-8') === 'skip') {
            bfp_clear_pending_comment_state($chatId);
            return [
                'handled' => true,
                'message' => 'Thank you. Your vote has been saved without an additional comment.'
            ];
        }

        $vote = bfp_get_vote_row($pollId, $userId);
        if (!$vote) {
            bfp_clear_pending_comment_state($chatId);
            return [
                'handled' => true,
                'message' => 'Your vote record could not be found. Please vote again if needed.'
            ];
        }

        $save = bfp_save_comment($pollId, $userId, $text);
        bfp_clear_pending_comment_state($chatId);

        if (!$save['ok']) {
            return [
                'handled' => true,
                'message' => 'Your vote was saved, but your comment could not be stored at the moment.'
            ];
        }

        return [
            'handled' => true,
            'message' => '✅ Thank you. Your additional comment has been recorded successfully.'
        ];
    }

    /* =========================================================
       OPTIONAL HELPERS
    ========================================================= */

    function bfp_get_poll_results_summary($pollId) {
        return bfp_fetch_all(
            "SELECT
                o.id,
                o.option_text,
                COUNT(v.id) AS total_votes
             FROM bot_feedback_poll_options o
             LEFT JOIN bot_feedback_poll_votes v
                ON v.option_id = o.id
               AND v.poll_id = o.poll_id
             WHERE o.poll_id = ?
             GROUP BY o.id, o.option_text
             ORDER BY o.sort_order ASC, o.id ASC",
            [(int)$pollId]
        );
    }

    function bfp_is_waiting_for_comment($chatId) {
        return bfp_get_pending_comment_state($chatId) ? true : false;
    }
}

/* =========================================================
   BOT.PHP INTEGRATION EXAMPLE

   1) Add:
      require_once 'bot_feedback_poll_functions.php';

   2) In callback_query handler:
      if (strpos($callback_data, 'pollvote_') === 0) {
          $result = bfp_handle_vote($chat_id, $callback_data);
          sendMessage($chat_id, $result['message']);
          exit;
      }

   3) In normal message/text handler:
      $commentFlow = bfp_handle_comment_message($chat_id, $text);
      if (!empty($commentFlow['handled'])) {
          sendMessage($chat_id, $commentFlow['message']);
          exit;
      }
========================================================= */
?>