package com.puntoz.pro;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.media3.common.MediaItem;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.DefaultHttpDataSource;
import androidx.media3.exoplayer.DefaultLoadControl;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.hls.HlsMediaSource;
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
import androidx.media3.ui.AspectRatioFrameLayout;
import androidx.media3.ui.PlayerView;

import java.io.InputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONObject;
import java.net.HttpURLConnection;
import java.net.URLEncoder;

@UnstableApi
public class PlayerActivity extends Activity {

    PlayerView playerView;
    ExoPlayer player;
    Handler handler = new Handler();

    FrameLayout root;
    LinearLayout osdBox;
    ImageView logoView;
    TextView nowView;
    TextView nowTimeView;
    TextView nextView;
    TextView nextTimeView;
    TextView remainView;
    View progressDone;
    View progressLeft;

    String url = "";
    String channelName = "Puntoz TV";
    String channelLogo = "";
    String nowTitle = "No information";
    String nextTitle = "No information";
    String startTime = "";
    String endTime = "";
    String nextStartTime = "";
    String nextEndTime = "";

    ArrayList<EpgItem> epgItems = new ArrayList<>();
    Runnable epgTicker;

    int amarillo = Color.rgb(255, 220, 0);
    int azul = Color.rgb(0, 210, 255);

    @Override
    protected void onCreate(Bundle b) {
        super.onCreate(b);

        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        url = getIntent().getStringExtra("url");
        channelName = getIntent().getStringExtra("channel_name");
        channelLogo = getIntent().getStringExtra("channel_logo");
        nowTitle = getIntent().getStringExtra("now_title");
        nextTitle = getIntent().getStringExtra("next_title");
        startTime = getIntent().getStringExtra("start_time");
        endTime = getIntent().getStringExtra("end_time");
        nextStartTime = getIntent().getStringExtra("next_start_time");
        nextEndTime = getIntent().getStringExtra("next_end_time");

        if (url == null) url = "";
        if (channelName == null || channelName.trim().isEmpty()) channelName = "Puntoz TV";
        if (channelLogo == null) channelLogo = "";
        if (nowTitle == null || nowTitle.trim().isEmpty()) nowTitle = "No information";
        if (nextTitle == null || nextTitle.trim().isEmpty()) nextTitle = "No information";
        if (startTime == null) startTime = "";
        if (endTime == null) endTime = "";
        if (nextStartTime == null) nextStartTime = "";
        if (nextEndTime == null) nextEndTime = "";

        root = new FrameLayout(this);

        playerView = new PlayerView(this);
        playerView.setUseController(false);
        playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT);

        root.addView(playerView, new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT
        ));

        crearOSD();

        setContentView(root);

        DefaultTrackSelector selector = new DefaultTrackSelector(this);
        selector.setParameters(selector.buildUponParameters()
                .setPreferredAudioLanguage("es")
                .setPreferredTextLanguage("es")
        );

        DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
                .setBufferDurationsMs(8000, 50000, 1500, 3000)
                .build();

        player = new ExoPlayer.Builder(this)
                .setTrackSelector(selector)
                .setLoadControl(loadControl)
                .build();

        playerView.setPlayer(player);
        playUrl(url);
    }

    private TextView tv(String text, int size, int color) {
        TextView t = new TextView(this);
        t.setText(text);
        t.setTextColor(color);
        t.setTextSize(size);
        t.setIncludeFontPadding(false);
        return t;
    }

    private SpannableString labelColor(String label, String text, int color) {
        SpannableString sp = new SpannableString(label + text);
        sp.setSpan(new ForegroundColorSpan(color), 0, label.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return sp;
    }

    private TextView chip(String txt) {
        TextView t = tv(txt, 13, Color.LTGRAY);
        t.setGravity(Gravity.CENTER);
        GradientDrawable bg = new GradientDrawable();
        bg.setColor(Color.argb(35, 0, 0, 0));
        bg.setStroke(2, Color.argb(160, 180, 180, 180));
        bg.setCornerRadius(8);
        t.setBackground(bg);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(68, 30);
        lp.setMargins(8, 0, 8, 0);
        t.setLayoutParams(lp);
        return t;
    }

    private void crearOSD() {
        osdBox = new LinearLayout(this);
        osdBox.setOrientation(LinearLayout.HORIZONTAL);
        osdBox.setGravity(Gravity.CENTER_VERTICAL);
        osdBox.setPadding(28, 16, 28, 16);
        osdBox.setVisibility(View.GONE);

        GradientDrawable bg = new GradientDrawable();
        bg.setColor(Color.argb(82, 0, 0, 0));
        bg.setStroke(2, Color.argb(80, 255, 255, 255));
        bg.setCornerRadius(16);
        osdBox.setBackground(bg);

        logoView = new ImageView(this);
        logoView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        LinearLayout.LayoutParams logoLp = new LinearLayout.LayoutParams(220, 150);
        logoLp.setMargins(0, 0, 28, 0);
        osdBox.addView(logoView, logoLp);

        LinearLayout info = new LinearLayout(this);
        info.setOrientation(LinearLayout.VERTICAL);
        info.setPadding(0, 18, 0, 0);

        nowView = tv("", 13, Color.WHITE);
        nowView.setText(labelColor("Ahora: ", nowTitle, amarillo));

        nowTimeView = tv(formatoHorario(startTime, endTime), 11, Color.WHITE);

        LinearLayout progressRow = new LinearLayout(this);
        progressRow.setOrientation(LinearLayout.HORIZONTAL);
        progressRow.setGravity(Gravity.CENTER_VERTICAL);

        LinearLayout bar = new LinearLayout(this);
        bar.setOrientation(LinearLayout.HORIZONTAL);
        GradientDrawable barBg = new GradientDrawable();
        barBg.setColor(Color.argb(120, 160, 170, 180));
        barBg.setCornerRadius(6);
        bar.setBackground(barBg);

        int progress = calcularProgreso(startTime, endTime);

        progressDone = new View(this);
        progressDone.setBackgroundColor(amarillo);
        bar.addView(progressDone, new LinearLayout.LayoutParams(0, 7, progress));

        progressLeft = new View(this);
        progressLeft.setBackgroundColor(Color.TRANSPARENT);
        bar.addView(progressLeft, new LinearLayout.LayoutParams(0, 7, Math.max(1, 100 - progress)));

        LinearLayout.LayoutParams barLp = new LinearLayout.LayoutParams(560, 7);
        barLp.setMargins(0, 1, 14, 1);
        progressRow.addView(bar, barLp);

        remainView = tv(minutosRestantes(endTime), 11, Color.WHITE);
        progressRow.addView(remainView);

        nextView = tv("", 13, Color.WHITE);
        nextView.setText(labelColor("Sigue: ", nextTitle, azul));

        nextTimeView = tv(formatoHorario(nextStartTime, nextEndTime), 12, Color.WHITE);

        info.addView(nowView);
        info.addView(nowTimeView);
        info.addView(progressRow);
        info.addView(nextView);
        info.addView(nextTimeView);

        osdBox.addView(info, new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1));

        View divider = new View(this);
        divider.setBackgroundColor(Color.argb(130, 180, 180, 180));
        LinearLayout.LayoutParams divLp = new LinearLayout.LayoutParams(2, 128);
        divLp.setMargins(35, 0, 35, 0);
        osdBox.addView(divider, divLp);

        LinearLayout right = new LinearLayout(this);
        right.setOrientation(LinearLayout.HORIZONTAL);
        right.setGravity(Gravity.CENTER);
        right.addView(chip("FHD"));
        right.addView(chip("16:9"));
        right.addView(chip("STEREO"));

        osdBox.addView(right, new LinearLayout.LayoutParams(280, LinearLayout.LayoutParams.WRAP_CONTENT));

        FrameLayout.LayoutParams osdParams = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.WRAP_CONTENT
        );
        osdParams.gravity = Gravity.BOTTOM;
        osdParams.setMargins(70, 0, 70, 42);

        root.addView(osdBox, osdParams);

        actualizarEpgViews();
        cargarLogo(channelLogo);

        cargarEpgUnaVez();
        iniciarEpgLocal();
    }


    private static class EpgItem {
        String title = "";
        String desc = "";
        long start = 0;
        long stop = 0;
    }

    private void cargarEpgUnaVez() {
        new Thread(() -> {
            try {
                String api = "http://216.152.155.250/PUNTOZ_PANEL/pz_epg_api.php?channel=" + URLEncoder.encode(channelName, "UTF-8");
                URL u = new URL(api);
                HttpURLConnection c = (HttpURLConnection) u.openConnection();
                c.setConnectTimeout(6000);
                c.setReadTimeout(10000);
                c.setRequestProperty("User-Agent", "Puntoz-TV-Android");
                InputStream is = c.getInputStream();

                byte[] buf = new byte[16384];
                StringBuilder sb = new StringBuilder();
                int n;
                while ((n = is.read(buf)) > 0) sb.append(new String(buf, 0, n, "UTF-8"));
                is.close();

                JSONObject json = new JSONObject(sb.toString());
                JSONArray arr = json.optJSONArray("programs");
                if (arr == null) return;

                ArrayList<EpgItem> tmp = new ArrayList<>();
                for (int i = 0; i < arr.length(); i++) {
                    JSONObject o = arr.getJSONObject(i);
                    EpgItem it = new EpgItem();
                    it.title = o.optString("title", "Programación");
                    it.desc = o.optString("desc", "");
                    it.start = o.optLong("start", 0);
                    it.stop = o.optLong("stop", 0);
                    if (it.start > 0 && it.stop > it.start) tmp.add(it);
                }

                epgItems = tmp;

                runOnUiThread(() -> actualizarEpgDesdeCacheLocal());

            } catch (Exception e) {
                runOnUiThread(() -> actualizarEpgViews());
            }
        }).start();
    }

    private void iniciarEpgLocal() {
        epgTicker = new Runnable() {
            @Override
            public void run() {
                actualizarEpgDesdeCacheLocal();
                handler.postDelayed(this, 30000);
            }
        };
        handler.postDelayed(epgTicker, 30000);
    }

    private void actualizarEpgDesdeCacheLocal() {
        if (epgItems == null || epgItems.size() == 0) {
            actualizarEpgViews();
            return;
        }

        long now = System.currentTimeMillis() / 1000L;
        EpgItem current = null;
        EpgItem next = null;

        for (int i = 0; i < epgItems.size(); i++) {
            EpgItem it = epgItems.get(i);
            if (now >= it.start && now < it.stop) {
                current = it;
                if (i + 1 < epgItems.size()) next = epgItems.get(i + 1);
                break;
            }
            if (it.start > now) {
                next = it;
                break;
            }
        }

        if (current != null) {
            nowTitle = current.title;
            startTime = String.valueOf(current.start);
            endTime = String.valueOf(current.stop);
        }

        if (next != null) {
            nextTitle = next.title;
            nextStartTime = String.valueOf(next.start);
            nextEndTime = String.valueOf(next.stop);
        }

        actualizarEpgViews();
    }

    private void actualizarEpgViews() {
        try {
            if (nowView != null) nowView.setText(labelColor("Ahora: ", nowTitle, amarillo));
            if (nextView != null) nextView.setText(labelColor("Sigue: ", nextTitle, azul));
            if (nowTimeView != null) nowTimeView.setText(formatoHorario(startTime, endTime));
            if (nextTimeView != null) nextTimeView.setText(formatoHorario(nextStartTime, nextEndTime));
            if (remainView != null) remainView.setText(minutosRestantes(endTime));

            if (progressDone != null && progressLeft != null) {
                int progress = calcularProgreso(startTime, endTime);
                LinearLayout.LayoutParams lpDone = new LinearLayout.LayoutParams(0, 7, progress);
                LinearLayout.LayoutParams lpLeft = new LinearLayout.LayoutParams(0, 7, Math.max(1, 100 - progress));
                progressDone.setLayoutParams(lpDone);
                progressLeft.setLayoutParams(lpLeft);
            }
        } catch (Exception ignored) {}
    }

    private String formatoHorario(String ini, String fin) {
        String a = horaBonita(ini);
        String b = horaBonita(fin);
        if (a.isEmpty() || b.isEmpty()) return "";
        return a + " – " + b;
    }

    private String horaBonita(String raw) {
        try {
            long v = Long.parseLong(raw.trim());
            if (v > 9999999999L) v = v / 1000;
            return new SimpleDateFormat("hh:mm a", new Locale("es", "CL"))
                    .format(new Date(v * 1000))
                    .replace("a. m.", "a. m.")
                    .replace("p. m.", "p. m.");
        } catch (Exception e) {
