package ru.kayashov.bar.bot.config;

import org.springframework.stereotype.Component;
import org.telegram.telegrambots.meta.api.objects.CallbackQuery;
import org.telegram.telegrambots.meta.api.objects.Chat;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardRow;
import ru.kayashov.bar.bot.domain.model.AbstractCallbackQuery;
import ru.kayashov.bar.bot.domain.model.AbstractChat;
import ru.kayashov.bar.bot.domain.model.AbstractKeyboard;
import ru.kayashov.bar.bot.domain.model.AbstractKeyboardButton;
import ru.kayashov.bar.bot.domain.model.AbstractMessage;
import ru.kayashov.bar.bot.domain.model.AbstractUpdate;

import java.util.List;

@Component
public class TelegramBotMapperImpl implements TelegramBotMapper {

    @Override
    public AbstractUpdate toAbstractUpdate(Update update) {
        if (update == null) return null;

        AbstractUpdate abstractUpdate = new AbstractUpdate();

        abstractUpdate.setMessage(toAbstractMessage(update.getMessage()));
        abstractUpdate.setCallbackQuery(toAbstractCallbackQuery(update.getCallbackQuery()));

        return abstractUpdate;
    }

    @Override
    public AbstractMessage toAbstractMessage(Message message) {
        if (message == null) {
            return null;
        }
        AbstractMessage abstractMessage = new AbstractMessage();

        abstractMessage.setMessage(message.getText());
        abstractMessage.setMessageId(message.getMessageId());
        abstractMessage.setChat(toAbstractChat(message.getChat()));
        abstractMessage.setChatId(message.getChatId());

        return abstractMessage;
    }

    @Override
    public AbstractCallbackQuery toAbstractCallbackQuery(CallbackQuery query) {
        if (query == null) {
            return null;
        }
        AbstractCallbackQuery callbackQuery = new AbstractCallbackQuery();
        callbackQuery.setData(query.getData());
        callbackQuery.setMessage(toAbstractMessage(query.getMessage()));
        return callbackQuery;
    }

    @Override
    public AbstractChat toAbstractChat(Chat chat) {
        if (chat == null) {
            return null;
        }
        AbstractChat abstractChat = new AbstractChat();
        abstractChat.setId(chat.getId());
        abstractChat.setFirstName(chat.getFirstName());
        abstractChat.setLastName(chat.getLastName());
        return abstractChat;
    }

    @Override
    public InlineKeyboardMarkup toInlineKeyboard(AbstractKeyboard replyKeyboard) {
        InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup();

        inlineKeyboardMarkup.setKeyboard(toInlineKeyboard(replyKeyboard.getKeyboard()));

        return inlineKeyboardMarkup;
    }

    @Override
    public ReplyKeyboardMarkup toReplyKeyboard(AbstractKeyboard replyKeyboard) {
        return ReplyKeyboardMarkup.builder()
                .keyboard(toKeyboardRows(replyKeyboard.getKeyboard()))
                .resizeKeyboard(replyKeyboard.getResizeKeyboard())
                .inputFieldPlaceholder(replyKeyboard.getInputFieldPlaceholder())
                .oneTimeKeyboard(replyKeyboard.getOneTimeKeyboard())
                .selective(replyKeyboard.getSelective())
                .build();
    }

    @Override
    public List<List<InlineKeyboardButton>> toInlineKeyboard(List<List<AbstractKeyboardButton>> buttons) {
        return buttons.stream()
                .map(this::toListButtons)
                .toList();
    }

    @Override
    public List<InlineKeyboardButton> toListButtons(List<AbstractKeyboardButton> buttons) {
        return buttons.stream().map(this::toInlineKeyboardButton).toList();
    }

    private InlineKeyboardButton toInlineKeyboardButton(AbstractKeyboardButton button) {
        InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton();

        inlineKeyboardButton.setCallbackData(button.getCallbackData());
        inlineKeyboardButton.setText(button.getText());

        return inlineKeyboardButton;
    }

    @Override
    public List<KeyboardRow> toKeyboardRows(List<List<AbstractKeyboardButton>> rows) {
        return rows.stream()
                .map(this::toKeyboardRow)
                .toList();
    }

    @Override
    public KeyboardRow toKeyboardRow(List<AbstractKeyboardButton> row) {
        KeyboardRow keyboardRow = new KeyboardRow();
        row.forEach(b -> keyboardRow.add(b.getText()));
        return keyboardRow;
    }
}
