import logging
from telegram.constants import ParseMode
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, MessageHandler, CallbackQueryHandler, filters, ContextTypes, ConversationHandler
from PIL import Image, ImageDraw, ImageFont

# Login configuration
logging.basicConfig(format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO)

# Conversation states
ASK_NAME, ASK_Q1, ASK_Q2, ASK_Q3 = range(4)

FILE_FEEDBACK = "npse-sandri-feedback.txt"

# Certificate template path
TEMPLATE_PATH = "C:/certificates/npse-template.png"
FONT_PATH = "arial.ttf"
OUTPUT_PATH = "C:/certificates/"

# Multiple-choice questions
QUESTIONS = [
("Did you like the presentation?", ["Yes, it was very interesting.", "It was okay, but could be improved.", "No, I didn’t find it engaging."]),
("Were you aware of the use of bots in education and dissemination?", ["Yes, I already knew about it.", "I had heard of it but didn’t know much.", "No, this was new to me."]),
("Do you think you will use them?", ["Yes, definitely!", "Maybe, if I find a good use for them.", "No, I don’t think so."])
]

def save_feedback(nome, q1, q2, q3):
with open(FILE_FEEDBACK, "a") as f:
f.write(f"{nome}; {q1}; {q2}; {q3}\n")

# Start function
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user = update.message.from_user
logging.info(f"User {user.first_name} started the bot with args: {context.args}")

if context.args:
qr_code_id = context.args[0]

if qr_code_id == "npse-sandri":
photo_url = "https://play.inaf.it/wp-content/uploads/2025/03/npse-banner-firenze.png"
await context.bot.send_photo(
chat_id=update.effective_chat.id,
photo=photo_url,
caption=f"Dear *{user.first_name}*, Thank you for attending the conference *New Perspectives in Science Education*.",
parse_mode=ParseMode.MARKDOWN
)

await update.message.reply_text("I kindly ask you to share your feedback on the presentation _Telegram Bots in Science Education: Applications in the Context of Astrophysics_.",parse_mode=ParseMode.MARKDOWN)
await update.message.reply_text("At the end of the survey, I will send you the personalized certificate 😊 Please write your name exactly as you would like it to appear on the certificate.")

return ASK_NAME

return ConversationHandler.END

# Receiving the name
async def get_name(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
context.user_data["cert_name"] = update.message.text

return await ask_question(update, context, question_index=0)

# Function to submit a multiple-choice question
async def ask_question(update: Update, context: ContextTypes.DEFAULT_TYPE, question_index: int) -> int:

question, options = QUESTIONS[question_index]
keyboard = [[InlineKeyboardButton(opt, callback_data=f"{question_index}_{opt}")] for opt in options]
reply_markup = InlineKeyboardMarkup(keyboard)

await update.message.reply_text(question, reply_markup=reply_markup)

return ASK_Q1 + question_index # Pass to next question (ASK_Q1, ASK_Q2, ASK_Q3)

# Function to manage the answer to a question
async def handle_answer(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
query = update.callback_query
await query.answer()

question_index, answer = query.data.split("_")
question_index = int(question_index)

context.user_data[f"q{question_index+1}"] = answer # Save the answer
logging.info(f"User answered question {question_index+1}: {answer}")

if question_index + 1 < len(QUESTIONS): return await ask_question(query, context, question_index + 1) # Save user data save_feedback( context.user_data['cert_name'], context.user_data.get('q1', 'N/A'), context.user_data.get('q2', 'N/A'), context.user_data.get('q3', 'N/A') ) cert_name = context.user_data["cert_name"] # Generates the certificate with the name cert_path = generate_certificate(cert_name) # Send the certificate to the user if cert_path: await query.message.reply_photo(photo=open(cert_path, "rb"), caption="Here is your certificate! 🎉") else: await query.message.reply_text("An error occurred while generating the certificate 😢") return ConversationHandler.END # Function to generate the certificate def generate_certificate(name: str) -> str:
try:
# Upload template
img = Image.open(TEMPLATE_PATH)
draw = ImageDraw.Draw(img)

# Choose an appropriate font and size
font = ImageFont.truetype(FONT_PATH, 60)

# Define the size of the box (change these values according to your template)
box_width = 800
box_height = 200
box_x = 343
box_y = 700

# Calculate text bounding box
bbox = draw.textbbox((0, 0), name, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]

# Calculates the position of the text to center it in the box
text_x = box_x + (box_width - text_width) // 2
text_y = box_y + (box_height - text_height) // 2

# Text color
text_color = (0, 0, 0) # Nero

# Writes the name centered on the image
draw.text((text_x, text_y), name, font=font, fill=text_color)

output_file = f"{OUTPUT_PATH}{name.replace(' ', '_')}.png"
img.save(output_file)

return output_file

except Exception as e:
logging.error(f"An error occurred while generating the certificate: {e}")
return None

# Cancel the conversation
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
await update.message.reply_text("Operation canceled.")
return ConversationHandler.END

# Main function
def main() -> None:
token = "TOKEN"

application = Application.builder().token(token).build()

conv_handler = ConversationHandler(
entry_points=[CommandHandler("start", start)],
states={
ASK_NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, get_name)],
ASK_Q1: [CallbackQueryHandler(handle_answer, pattern="^0_")],
ASK_Q2: [CallbackQueryHandler(handle_answer, pattern="^1_")],
ASK_Q3: [CallbackQueryHandler(handle_answer, pattern="^2_")],
},
fallbacks=[CommandHandler("cancel", cancel)],
)

application.add_handler(conv_handler)

application.run_polling()

if __name__ == "__main__":
main()