<?php
// Strict types for better type safety (PHP 7+)
declare(strict_types=1);

// Database credentials
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'accurate_be');
define('DB_PASSWORD', 'Saiful.1633');
define('DB_NAME', 'accurate_be');

// --- Helper function to send JSON response and exit ---
function send_json_response(array $data, int $statusCode = 200): void {
    http_response_code($statusCode);
    header('Content-Type: application/json; charset=UTF-8');
    echo json_encode($data);
    exit;
}

// --- Database Connection ---
$link = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME);

if ($link === false) {
    error_log("Database Connection Error: " . mysqli_connect_error());
    send_json_response([
        'success' => false,
        'message' => 'ডাটাবেস সংযোগে সমস্যা। অনুগ্রহ করে পরে আবার চেষ্টা করুন।',
        'results' => [],
        'voted' => false,
        'total_votes' => 0
    ], 503); // 503 Service Unavailable
}

if (!mysqli_set_charset($link, "utf8mb4")) {
    error_log("Error loading character set utf8mb4: " . mysqli_error($link));
    // Continue, but log this. Frontend might see garbled text if fallback charset is wrong.
}

// Initialize response array
$response = [
    'success' => false,
    'message' => 'অবৈধ অনুরোধ।', // Default error message
    'results' => [],
    'voted' => false,
    'total_votes' => 0
];

// --- Function to get vote results ---
function get_vote_results(mysqli $dbLink): array {
    $results_data = [];
    $total_votes = 0;
    $sql = "SELECT option_name, vote_count FROM votes";
    $query_result = mysqli_query($dbLink, $sql);

    if ($query_result) {
        while ($row = mysqli_fetch_assoc($query_result)) {
            $results_data[] = $row;
            $total_votes += (int)$row['vote_count'];
        }
        mysqli_free_result($query_result);

        foreach ($results_data as &$item) {
            $item['percentage'] = $total_votes > 0 ? round(((int)$item['vote_count'] / $total_votes) * 100, 2) : 0;
        }
        unset($item);
        return ['data' => $results_data, 'total' => $total_votes, 'error' => null];
    } else {
        error_log("Error fetching results: " . mysqli_error($dbLink));
        return ['data' => [], 'total' => 0, 'error' => 'ফলাফল আনতে সমস্যা হয়েছে: ' . mysqli_error($dbLink)];
    }
}

// --- Function to check if user has voted ---
function has_user_voted(mysqli $dbLink, string $fingerprint): array {
    if (empty($fingerprint)) {
        return ['voted' => false, 'message' => 'ফিঙ্গারপ্রিন্ট পাওয়া যায়নি।', 'error' => true];
    }

    $sql = "SELECT id FROM voted_users WHERE fingerprint = ?";
    if ($stmt = mysqli_prepare($dbLink, $sql)) {
        mysqli_stmt_bind_param($stmt, "s", $fingerprint);
        if (mysqli_stmt_execute($stmt)) {
            mysqli_stmt_store_result($stmt);
            $hasVoted = mysqli_stmt_num_rows($stmt) > 0;
            mysqli_stmt_close($stmt);
            return ['voted' => $hasVoted, 'message' => $hasVoted ? 'আপনি ইতিমধ্যেই ভোট দিয়েছেন।' : 'ভোট দেওয়ার জন্য প্রস্তুত।', 'error' => false];
        } else {
            error_log("Error executing check voted statement: " . mysqli_stmt_error($stmt));
            mysqli_stmt_close($stmt);
            return ['voted' => false, 'message' => 'ভোটের স্ট্যাটাস যাচাই করতে সমস্যা হয়েছে।', 'error' => true];
        }
    } else {
        error_log("Error preparing check voted statement: " . mysqli_error($dbLink));
        return ['voted' => false, 'message' => 'ভোটের স্ট্যাটাস যাচাইয়ের প্রস্তুতিতে সমস্যা হয়েছে।', 'error' => true];
    }
}


// --- Main Request Handling ---
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
    send_json_response($response, 405); // 405 Method Not Allowed
}

// Fetch current results and update response
$current_results_info = get_vote_results($link);
if ($current_results_info['error'] === null) {
    $response['results'] = $current_results_info['data'];
    $response['total_votes'] = $current_results_info['total'];
    $response['success'] = true; // Initial success if results are fetched
    $response['message'] = 'ফলাফল সফলভাবে লোড হয়েছে।';
} else {
    $response['message'] = $current_results_info['error'];
    // success remains false if results couldn't be fetched
}

$action = $_POST['action'] ?? '';
$fingerprint = $_POST['fingerprint'] ?? '';

// Check voted status if fingerprint is provided
if (!empty($fingerprint)) {
    $voted_status_info = has_user_voted($link, $fingerprint);
    if ($voted_status_info['error']) {
        $response['success'] = false; // An error occurred checking status
        $response['message'] = $voted_status_info['message'];
        // voted status in $response remains as default (false) or previous state
    } else {
        $response['voted'] = $voted_status_info['voted'];
        if ($voted_status_info['voted']) {
             // If already voted, message should reflect that, and success of a 'vote' action would be false.
            $response['message'] = $voted_status_info['message'];
        } else if (empty($action)){ // Initial load, not voted yet
            $response['message'] = $voted_status_info['message'];
        }
    }
} else {
    // Fingerprint not provided
    if ($action === 'vote') {
        $response['success'] = false;
        $response['message'] = 'ভোট দেওয়ার জন্য ডিভাইস ফিঙ্গারপ্রিন্ট আবশ্যক।';
    }
    // For 'get_results' or initial load, fingerprint might not be sent, which is fine.
    // $response['voted'] will remain false.
}


// --- Handle 'vote' Action ---
if ($action === 'vote') {
    $option = $_POST['option'] ?? '';
    $allowed_options = ['সংস্কার', 'নির্বাচন']; // Define allowed options

    if (empty($fingerprint)) {
        // Message already set if fingerprint is missing for vote action
        $response['success'] = false;
    } else if ($response['voted'] === true) {
        // User has already voted, message is set by has_user_voted
        $response['success'] = false; // A new vote cannot be successful
    } else if (empty($option) || !in_array($option, $allowed_options, true)) {
        $response['success'] = false;
        $response['message'] = 'অবৈধ অপশন অথবা অপশন নির্বাচন করা হয়নি।';
    } else {
        // Proceed with vote
        mysqli_begin_transaction($link);
        $vote_recorded_successfully = false;

        try {
            // 1. Update vote count
            $sql_update_vote = "UPDATE votes SET vote_count = vote_count + 1 WHERE option_name = ?";
            $stmt_update = mysqli_prepare($link, $sql_update_vote);
            if (!$stmt_update) throw new Exception('ভোট আপডেট স্টেটমেন্ট প্রস্তুতিতে সমস্যা: ' . mysqli_error($link));
            
            mysqli_stmt_bind_param($stmt_update, "s", $option);
            if (!mysqli_stmt_execute($stmt_update)) throw new Exception('ভোট আপডেট করতে সমস্যা: ' . mysqli_stmt_error($stmt_update));
            
            if (mysqli_stmt_affected_rows($stmt_update) === 0) {
                 mysqli_stmt_close($stmt_update);
                 throw new Exception('অবৈধ ভোটিং অপশন।');
            }
            mysqli_stmt_close($stmt_update);

            // 2. Insert fingerprint
            $sql_insert_fingerprint = "INSERT INTO voted_users (fingerprint) VALUES (?)";
            $stmt_insert = mysqli_prepare($link, $sql_insert_fingerprint);
            if (!$stmt_insert) throw new Exception('ফিঙ্গারপ্রিন্ট ইনসার্ট স্টেটমেন্ট প্রস্তুতিতে সমস্যা: ' . mysqli_error($link));

            mysqli_stmt_bind_param($stmt_insert, "s", $fingerprint);
            if (!mysqli_stmt_execute($stmt_insert)) {
                if (mysqli_errno($link) === 1062) { // Duplicate entry for fingerprint
                    mysqli_stmt_close($stmt_insert);
                    // This means a race condition occurred or the initial check was somehow bypassed.
                    // Rollback the vote count increase, as the user was already registered.
                    mysqli_rollback($link);
                    $response['voted'] = true;
                    $response['success'] = false; // Vote was not newly successful
                    $response['message'] = 'আপনি ইতিমধ্যেই ভোট দিয়েছেন (সমসাময়িক অনুরোধ সনাক্ত)।';
                    // Re-fetch results to show correct count before this attempt (already fetched at start)
                    // $current_results_info = get_vote_results($link); // Potentially re-fetch if strict consistency is needed after rollback
                    // $response['results'] = $current_results_info['data'];
                    // $response['total_votes'] = $current_results_info['total'];
                    send_json_response($response, 200); // OK, but vote not new
                }
                throw new Exception('ফিঙ্গারপ্রিন্ট সংরক্ষণ করতে সমস্যা: ' . mysqli_stmt_error($stmt_insert));
            }
            mysqli_stmt_close($stmt_insert);

            mysqli_commit($link);
            $vote_recorded_successfully = true;

        } catch (Exception $e) {
            mysqli_rollback($link);
            error_log("Vote processing error: " . $e->getMessage());
            $response['success'] = false;
            $response['message'] = $e->getMessage();
            // $response['voted'] remains as per initial check or default (false)
        }

        if ($vote_recorded_successfully) {
            $response['success'] = true;
            $response['message'] = 'ভোট সফলভাবে রেকর্ড করা হয়েছে!';
            $response['voted'] = true;

            // Re-fetch results to include the vote just recorded
            $updated_results_info = get_vote_results($link);
            if ($updated_results_info['error'] === null) {
                $response['results'] = $updated_results_info['data'];
                $response['total_votes'] = $updated_results_info['total'];
            } else {
                // Vote was successful, but fetching updated results failed.
                // This is unlikely if the DB is still up.
                $response['message'] .= ' তবে, আপডেটেড ফলাফল আনতে সমস্যা হয়েছে।';
            }
        }
    }
} else if ($action === 'get_results') {
    // Results are already fetched at the beginning.
    // The success and message for fetching results are already set.
    // If user was also checked (fingerprint provided), voted status and message are also set.
    // If no fingerprint, voted status is false.
    // If results fetch was fine, $response['success'] is true.
} else if (empty($action)) {
    // Initial load (no specific action)
    // Results are fetched. Voted status is checked if fingerprint is provided.
    // Messages are set accordingly.
    // $response['success'] is true if results were fetched.
} else {
    $response['success'] = false;
    $response['message'] = 'অজানা অ্যাকশন: ' . htmlspecialchars($action);
}


mysqli_close($link);
send_json_response($response, $response['success'] ? 200 : ($action === 'vote' && !$response['voted'] ? 400 : 200) );
// If action was 'vote' and it failed due to invalid input (not 'already voted'), send 400 Bad Request.
// Otherwise, send 200 OK even if a 'vote' action determined user already voted (it's not a client error).
// If results fetch failed initially, success will be false, and it will be 200 (with error message) or you might choose 500.
// For simplicity, if overall $response['success'] is false due to server-side issues (like DB error on results), a 500 might be more appropriate earlier.
// The current logic sends 200 if overall success is true. If success is false, it might be due to user input (400) or already voted (200).

// A more nuanced final status code:
$final_status_code = 200;
if (!$response['success']) {
    if ($action === 'vote' && (strpos($response['message'], 'অবৈধ অপশন') !== false || strpos($response['message'], 'ডিভাইস ফিঙ্গারপ্রিন্ট আবশ্যক') !== false)) {
        $final_status_code = 400; // Bad Request
    } else if (strpos($response['message'], 'ডাটাবেস') !== false || strpos($response['message'], 'সমস্যা হয়েছে') !== false && $action !== 'vote') {
         // Heuristic: if "database" or "problem occurred" and not a vote specific error
        // $final_status_code = 500; // Internal Server Error - but `get_vote_results` might have set this.
        // The 503 for DB connection is already handled.
        // For other DB errors during results fetch or status check, 200 with error message is common.
    }
}
// The send_json_response was already called if DB connection failed.
// To avoid re-sending headers, we'll use the one outside the if/else.
// The last send_json_response needs to be removed if it's inside the if/else now.
// The last line before mysqli_close:
// send_json_response($response, $final_status_code);
// The `send_json_response` already has `exit`.

?>