package com.fongmi.android.tv.browse;

import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.media3.common.MediaItem;

import com.fongmi.android.tv.api.LiveApi;
import com.fongmi.android.tv.api.config.LiveConfig;
import com.fongmi.android.tv.bean.Channel;
import com.fongmi.android.tv.bean.Group;
import com.fongmi.android.tv.bean.Live;
import com.fongmi.android.tv.bean.Result;
import com.fongmi.android.tv.db.AppDatabase;
import com.google.common.collect.ImmutableList;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.IntStream;

class LiveBrowse {

    static final String LIVE_GROUP = "LG:";
    static final String LIVE_CH = "LC:";

    private static final Map<String, String> liveNavMap = new ConcurrentHashMap<>();
    private static final Map<String, Integer> liveCountMap = new ConcurrentHashMap<>();
    private static final Map<String, LiveEntry> livePosMap = new ConcurrentHashMap<>();

    static void clear() {
        livePosMap.clear();
        liveNavMap.clear();
        liveCountMap.clear();
    }

    @NonNull
    static ImmutableList<MediaItem> getGroups() {
        return liveHome().getGroups().stream().map(group -> BrowseTree.folder(LIVE_GROUP + group.getName(), group.getName())).collect(ImmutableList.toImmutableList());
    }

    @NonNull
    static ImmutableList<MediaItem> getChannels(@NonNull String parentId) {
        String groupName = parentId.substring(LIVE_GROUP.length());
        Group group = liveHome().getGroups().stream().filter(item -> item.getName().equals(groupName)).findFirst().orElse(null);
        if (group == null) {
            liveCountMap.put(groupName, 0);
            return ImmutableList.of();
        }
        liveNavMap.keySet().removeIf(key -> key.startsWith(groupName + '|'));
        livePosMap.values().removeIf(entry -> entry.groupName.equals(groupName));
        List<Channel> channels = group.getChannel();
        liveCountMap.put(groupName, channels.size());
        return IntStream.range(0, channels.size()).mapToObj(i -> indexChannel(groupName, channels.get(i), i)).collect(ImmutableList.toImmutableList());
    }

    private static MediaItem indexChannel(@NonNull String groupName, @NonNull Channel channel, int index) {
        String key = liveNavKey(groupName, index);
        String id = LIVE_CH + key;
        liveNavMap.put(key, id);
        livePosMap.put(id, new LiveEntry(channel, groupName, index));
        return BrowseTree.playable(id, channel.getNumber() + " " + channel.getShow(), null, channel.getLogo());
    }

    @Nullable
    static MediaItem getItem(@NonNull String mediaId) {
        if (mediaId.startsWith(LIVE_GROUP)) return BrowseTree.folder(mediaId, mediaId.substring(LIVE_GROUP.length()));
        LiveEntry entry = livePosMap.get(mediaId);
        if (entry == null) return null;
        Channel channel = entry.channel();
        return BrowseTree.playable(mediaId, channel.getNumber() + " " + channel.getShow(), null, channel.getLogo());
    }

    @Nullable
    static MediaItem resolve(@NonNull String mediaId) throws Exception {
        LiveEntry entry = livePosMap.get(mediaId);
        return resolveChannel(entry != null ? entry.channel() : null, mediaId);
    }

    @Nullable
    static MediaItem navigate(@NonNull String mediaId, int delta) throws Exception {
        if (mediaId.startsWith(LIVE_CH)) return navigateChannel(mediaId, delta);
        String liveId = ensureLoaded();
        if (liveId != null) return navigateChannel(liveId, delta);
        return null;
    }

    @Nullable
    private static MediaItem navigateChannel(@NonNull String mediaId, int delta) throws Exception {
        LiveEntry current = livePosMap.get(mediaId);
        if (current == null) return null;
        Integer count = liveCountMap.get(current.groupName);
        if (count == null || count == 0) return null;
        int target = BrowseTree.wrapIndex(current.index, delta, count);
        String nextId = liveNavMap.get(liveNavKey(current.groupName, target));
        if (nextId == null) return null;
        LiveEntry next = livePosMap.get(nextId);
        return resolveChannel(next != null ? next.channel() : null, nextId);
    }

    @Nullable
    private static String ensureLoaded() {
        String keep = liveHome().getKeep();
        if (TextUtils.isEmpty(keep)) return null;
        String[] splits = keep.split(AppDatabase.SYMBOL);
        if (splits.length < 2) return null;
        String groupName = splits[0];
        String channelName = splits[1];
        getChannels(LIVE_GROUP + groupName);
        Integer count = liveCountMap.get(groupName);
        if (count == null || count == 0) return null;
        return livePosMap.entrySet().stream().filter(e -> e.getValue().groupName().equals(groupName) && e.getValue().channel().getName().equals(channelName)).map(Map.Entry::getKey).findFirst().orElse(null);
    }

    @Nullable
    private static MediaItem resolveChannel(@Nullable Channel channel, @NonNull String mediaId) throws Exception {
        if (channel == null || TextUtils.isEmpty(channel.getCurrent())) return null;
        Result result = LiveApi.getUrl(channel);
        if (TextUtils.isEmpty(result.getRealUrl())) return null;
        BrowseTree.putBrowseResult(mediaId, result);
        return BrowseTree.stream(mediaId, result.getRealUrl(), channel.getShow(), null, channel.getLogo());
    }

    private static Live liveHome() {
        LiveConfig.get().ensureLoaded();
        return LiveConfig.get().getHome();
    }

    @NonNull
    private static String liveNavKey(@NonNull String groupName, int index) {
        return groupName + '|' + index;
    }

    private record LiveEntry(Channel channel, String groupName, int index) {
    }
}
