package com.alttd.altitudeweb.services.discord;

import com.alttd.altitudeweb.database.Databases;
import com.alttd.altitudeweb.database.discord.OutputChannel;
import com.alttd.altitudeweb.database.discord.OutputChannelMapper;
import com.alttd.altitudeweb.database.web_db.forms.StaffApplication;
import com.alttd.altitudeweb.setup.Connection;
import com.alttd.webinterface.objects.MessageForEmbed;
import com.alttd.webinterface.send_message.DiscordSender;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Service
public class StaffApplicationDiscord {

    private static final String OUTPUT_TYPE = "STAFF_APPLICATION";

    public void sendApplicationToDiscord(String username, StaffApplication application) {
        // Fetch channels for staff applications
        CompletableFuture<List<OutputChannel>> channelsFuture = new CompletableFuture<>();
        Connection.getConnection(Databases.DISCORD).runQuery(sql -> {
            try {
                List<OutputChannel> channels = sql.getMapper(OutputChannelMapper.class)
                        .getChannelsWithOutputType(OUTPUT_TYPE);
                channelsFuture.complete(channels);
            } catch (Exception e) {
                log.error("Failed to load output channels for {}", OUTPUT_TYPE, e);
                channelsFuture.complete(new ArrayList<>());
            }
        });

        List<OutputChannel> channels = channelsFuture.join();
        if (channels.isEmpty()) {
            log.warn("No Discord output channels found for type {}. Skipping Discord send.", OUTPUT_TYPE);
            return;
        }

        // Build embed content
        List<DiscordSender.EmbedField> fields = new ArrayList<>();
        fields.add(new DiscordSender.EmbedField(
                "Applicant",
                "Username: `" + safe(username) + "`\n" +
                        "Discord: `" + safe(application.discordUsername()) + "`\n" +
                        "Email: " + safe(application.email()) + "\n" +
                        "Age: " + safe(String.valueOf(application.age())) + "\n" +
                        "Meets reqs: " + (application.meetsRequirements() != null && application.meetsRequirements()),
                false
        ));
        fields.add(new DiscordSender.EmbedField(
                "Availability",
                "Days: " + safe(application.availableDays()) + "\n" +
                        "Times: " + safe(application.availableTimes()),
                false
        ));
        fields.add(new DiscordSender.EmbedField(
                "Experience",
                "Previous: " + safe(application.previousExperience()) + "\n" +
                        "Plugins: " + safe(application.pluginExperience()) + "\n" +
                        "Expectations: " + safe(application.moderatorExpectations()),
                false
        ));
        if (application.additionalInfo() != null && !application.additionalInfo().isBlank()) {
            fields.add(new DiscordSender.EmbedField(
                    "Additional Info",
                    application.additionalInfo(),
                    false
            ));
        }

        List<Long> channelIds = channels.stream()
                .map(OutputChannel::channel)
                .toList();

        Instant timestamp = application.createdAt() != null ? application.createdAt() : Instant.now();
        MessageForEmbed messageForEmbed = new MessageForEmbed(
                "New Staff Application Submitted",
                "Join date: " + (application.joinDate() != null ? application.joinDate().toString() : "unknown") +
                "\nSubmitted: " + formatInstant(timestamp),
                fields,
                null,
                timestamp,
                null);
        DiscordSender.getInstance().sendEmbedWithThreadToChannels(channelIds, messageForEmbed, "Staff Application");
    }

    private String safe(String s) {
        return s == null ? "unknown" : s;
    }

    private String formatInstant(Instant instant) {
        if (instant == null) return "unknown";
        return instant.atZone(ZoneId.of("UTC"))
                .format(DateTimeFormatter.ofPattern("yyyy MMMM dd hh:mm a '(UTC)'"));
    }
}
