"""Profesyonel medya oynatıcı bileşeni (ses + video).

Tek bir `MedyaOynatici` tüm oynatıcıların koordinasyonunu yapar
(bir kart oynatılırken diğerleri duraklar).
"""
from __future__ import annotations
from pathlib import Path
from typing import Optional

from PySide6.QtCore import Qt, QUrl, Signal, QObject
from PySide6.QtGui import QIcon
from PySide6.QtWidgets import (
    QWidget, QHBoxLayout, QVBoxLayout, QPushButton, QSlider, QLabel, QStyle,
    QSizePolicy,
)
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
from PySide6.QtMultimediaWidgets import QVideoWidget


def _fmt_sure(ms: int) -> str:
    s = max(0, ms) // 1000
    return f"{s // 60:02d}:{s % 60:02d}"


class OynaticiKoordinator(QObject):
    """Aynı anda tek bir oynatıcının çalmasını sağlar."""
    _aktif: Optional["MedyaOynatici"] = None

    @classmethod
    def aktif_olarak_isaretle(cls, o: "MedyaOynatici") -> None:
        if cls._aktif is o:
            return
        if cls._aktif is not None:
            cls._aktif.durakla()
        cls._aktif = o


class MedyaOynatici(QWidget):
    """Play/pause/stop/seek + ses seviyesi olan kompakt oynatıcı.

    Video gösterimi için `video=True` ile oluşturulur.
    """

    oynatildi = Signal()
    duraklatildi = Signal()

    def __init__(self, video: bool = False, kompakt: bool = False, parent=None):
        super().__init__(parent)
        self._video = video
        self._dosya = ""

        self._player = QMediaPlayer(self)
        self._audio = QAudioOutput(self)
        self._audio.setVolume(0.7)
        self._player.setAudioOutput(self._audio)

        ana = QVBoxLayout(self)
        ana.setContentsMargins(0, 0, 0, 0)
        ana.setSpacing(6)

        if video:
            self._video_w = QVideoWidget(self)
            self._video_w.setMinimumHeight(160 if kompakt else 260)
            self._video_w.setStyleSheet("background: #000; border-radius: 8px;")
            self._video_w.setSizePolicy(QSizePolicy.Policy.Expanding,
                                        QSizePolicy.Policy.Expanding)
            self._player.setVideoOutput(self._video_w)
            ana.addWidget(self._video_w, 1)

        kontrol = QHBoxLayout()
        kontrol.setSpacing(6)

        st = self.style()
        self.btn_oynat = QPushButton()
        self.btn_oynat.setIcon(st.standardIcon(QStyle.StandardPixmap.SP_MediaPlay))
        self.btn_oynat.setFixedSize(34, 28)
        self.btn_oynat.setToolTip("Oynat / Duraklat (Space)")
        self.btn_oynat.clicked.connect(self.oynat_duraklat)
        kontrol.addWidget(self.btn_oynat)

        self.btn_dur = QPushButton()
        self.btn_dur.setIcon(st.standardIcon(QStyle.StandardPixmap.SP_MediaStop))
        self.btn_dur.setFixedSize(34, 28)
        self.btn_dur.setToolTip("Durdur")
        self.btn_dur.clicked.connect(self.durdur)
        kontrol.addWidget(self.btn_dur)

        self.konum = QSlider(Qt.Orientation.Horizontal)
        self.konum.setRange(0, 0)
        self.konum.sliderMoved.connect(self._ara)
        kontrol.addWidget(self.konum, 1)

        self.etiket = QLabel("00:00 / 00:00")
        self.etiket.setStyleSheet("color: #9ca3af; padding: 0 6px;")
        kontrol.addWidget(self.etiket)

        self.ses_ikon = QLabel("🔊")
        kontrol.addWidget(self.ses_ikon)
        self.ses = QSlider(Qt.Orientation.Horizontal)
        self.ses.setRange(0, 100)
        self.ses.setValue(70)
        self.ses.setFixedWidth(70)
        self.ses.valueChanged.connect(lambda v: self._audio.setVolume(v / 100.0))
        kontrol.addWidget(self.ses)

        ana.addLayout(kontrol)

        self._player.positionChanged.connect(self._konum_degisti)
        self._player.durationChanged.connect(self._sure_degisti)
        self._player.playbackStateChanged.connect(self._durum_degisti)

    # --------------------------------------------------------------- API
    def dosya_yukle(self, yol: str) -> bool:
        if not yol or not Path(yol).exists():
            self._dosya = ""
            self._player.setSource(QUrl())
            self.konum.setValue(0)
            self.etiket.setText("00:00 / 00:00")
            return False
        self._dosya = yol
        self._player.setSource(QUrl.fromLocalFile(str(Path(yol).resolve())))
        return True

    def dosya(self) -> str:
        return self._dosya

    def oynat(self) -> None:
        if not self._dosya:
            return
        OynaticiKoordinator.aktif_olarak_isaretle(self)
        self._player.play()

    def durakla(self) -> None:
        self._player.pause()

    def durdur(self) -> None:
        self._player.stop()

    def oynat_duraklat(self) -> None:
        if self._player.playbackState() == QMediaPlayer.PlaybackState.PlayingState:
            self.durakla()
        else:
            self.oynat()

    # --------------------------------------------------------- slot'lar
    def _ara(self, v: int) -> None:
        self._player.setPosition(v)

    def _konum_degisti(self, v: int) -> None:
        if not self.konum.isSliderDown():
            self.konum.setValue(v)
        self.etiket.setText(f"{_fmt_sure(v)} / {_fmt_sure(self._player.duration())}")

    def _sure_degisti(self, v: int) -> None:
        self.konum.setRange(0, v)
        self.etiket.setText(f"{_fmt_sure(self._player.position())} / {_fmt_sure(v)}")

    def _durum_degisti(self, st: QMediaPlayer.PlaybackState) -> None:
        st_cls = self.style()
        if st == QMediaPlayer.PlaybackState.PlayingState:
            self.btn_oynat.setIcon(st_cls.standardIcon(QStyle.StandardPixmap.SP_MediaPause))
            self.oynatildi.emit()
        else:
            self.btn_oynat.setIcon(st_cls.standardIcon(QStyle.StandardPixmap.SP_MediaPlay))
            if st == QMediaPlayer.PlaybackState.PausedState:
                self.duraklatildi.emit()
