from collections import defaultdict
from django.shortcuts import render, redirect, get_object_or_404
from django.views import View
from django.contrib import messages
from django.views.decorators.http import require_POST
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from settingspanel.models import AppSettings
from .services import sonarr_calendar, radarr_calendar, ArrServiceError
from .models import SeriesSubscription, MovieSubscription
from django.utils import timezone


def _get_int(request, key, default):
    try:
        v = int(request.GET.get(key, default))
        return max(1, min(365, v))
    except (TypeError, ValueError):
        return default

def _arr_conf_from_db():
    cfg = AppSettings.current()
    return {
        "sonarr_url": cfg.sonarr_url,
        "sonarr_key": cfg.sonarr_api_key,
        "radarr_url": cfg.radarr_url,
        "radarr_key": cfg.radarr_api_key,
    }


#class SonarrAiringView(APIView):
#    def get(self, request):
#        days = _get_int(request, "days", 30)
#        conf = _arr_conf_from_db()
#        try:
#            data = sonarr_calendar(days=days, base_url=conf["sonarr_url"], api_key=conf["sonarr_key"])
#            return Response({"count": len(data), "results": data})
#        except ArrServiceError as e:
#            return Response({"error": str(e)}, status=status.HTTP_502_BAD_GATEWAY)


#class RadarrUpcomingMoviesView(APIView):
#    def get(self, request):
#        days = _get_int(request, "days", 60)
#        conf = _arr_conf_from_db()
#        try:
#            data = radarr_calendar(days=days, base_url=conf["radarr_url"], api_key=conf["radarr_key"])
#            return Response({"count": len(data), "results": data})
#        except ArrServiceError as e:
#            return Response({"error": str(e)}, status=status.HTTP_502_BAD_GATEWAY)


class ArrIndexView(View):
    def get(self, request):
        q = (request.GET.get("q") or "").lower().strip()
        kind = (request.GET.get("kind") or "all").lower()
        days = _get_int(request, "days", 30)

        conf = _arr_conf_from_db()

        eps, movies = [], []
        # Sonarr robust laden
        try:
            eps = sonarr_calendar(days=days, base_url=conf["sonarr_url"], api_key=conf["sonarr_key"])
        except ArrServiceError as e:
            messages.error(request, f"Sonarr is not reachable: {e}")

        # Radarr robust laden
        try:
            movies = radarr_calendar(days=days, base_url=conf["radarr_url"], api_key=conf["radarr_key"])
        except ArrServiceError as e:
            messages.error(request, f"Radarr is not reachable: {e}")

        # Suche
        if q:
            eps = [e for e in eps if q in (e.get("seriesTitle") or "").lower()]
            movies = [m for m in movies if q in (m.get("title") or "").lower()]

        # Abonnierte Serien und Filme laden
        subscribed_series_ids = set(SeriesSubscription.objects.values_list('series_id', flat=True))
        subscribed_movie_ids = set(MovieSubscription.objects.values_list('movie_id', flat=True))

        # Gruppierung nach Serie
        groups = defaultdict(lambda: {
            "seriesId": None, "seriesTitle": None, "seriesPoster": None,
            "seriesOverview": "", "seriesGenres": [], "episodes": [], "is_subscribed": False,
        })
        for e in eps:
            sid = e["seriesId"]
            g = groups[sid]
            g["seriesId"] = sid
            g["seriesTitle"] = e["seriesTitle"]
            g["seriesPoster"] = g["seriesPoster"] or e.get("seriesPoster")
            if not g["seriesOverview"] and e.get("seriesOverview"):
                g["seriesOverview"] = e["seriesOverview"]
            if not g["seriesGenres"] and e.get("seriesGenres"):
                g["seriesGenres"] = e["seriesGenres"]
            g["episodes"].append({
                "episodeId": e["episodeId"],
                "seasonNumber": e["seasonNumber"],
                "episodeNumber": e["episodeNumber"],
                "title": e["title"],
                "airDateUtc": e["airDateUtc"],
            })

        series_grouped = []
        for g in groups.values():
            g["episodes"].sort(key=lambda x: (x["airDateUtc"] or ""))
            g["is_subscribed"] = g["seriesId"] in subscribed_series_ids
            series_grouped.append(g)

        # Markiere abonnierte Filme
        for movie in movies:
            movie["is_subscribed"] = movie.get("movieId") in subscribed_movie_ids

        return render(request, "arr_api/index.html", {
            "query": q,
            "kind": kind,
            "days": days,
            "show_series": kind in ("all", "series"),
            "show_movies": kind in ("all", "movies"),
            "series_grouped": series_grouped,
            "movies": movies,
        })


class CalendarView(View):
    def get(self, request):
        days = _get_int(request, "days", 60)
        return render(request, "arr_api/calendar.html", {"days": days})


@method_decorator(login_required, name='dispatch')
class CalendarEventsApi(APIView):
    def get(self, request):
        days = _get_int(request, "days", 60)
        conf = _arr_conf_from_db()
        try:
            eps = sonarr_calendar(days=days, base_url=conf["sonarr_url"], api_key=conf["sonarr_key"])
        except ArrServiceError:
            eps = []
        try:
            movies = radarr_calendar(days=days, base_url=conf["radarr_url"], api_key=conf["radarr_key"])
        except ArrServiceError:
            movies = []

        series_sub = set(SeriesSubscription.objects.filter(user=request.user).values_list('series_id', flat=True))
        movie_sub_titles = set(MovieSubscription.objects.filter(user=request.user).values_list('title', flat=True))

        events = []
        for e in eps:
            when = e.get("airDateUtc")
            if not when:
                continue
            events.append({
                "id": f"s:{e.get('seriesId')}:{e.get('episodeId')}",
                "title": f"{e.get('seriesTitle','')} — S{e.get('seasonNumber')}E{e.get('episodeNumber')}",
                "start": when,
                "allDay": False,
                "extendedProps": {
                    "kind": "series",
                    "seriesId": e.get('seriesId'),
                    "seriesTitle": e.get('seriesTitle'),
                    "seasonNumber": e.get('seasonNumber'),
                    "episodeNumber": e.get('episodeNumber'),
                    "episodeTitle": e.get('title'),
                    "overview": e.get('seriesOverview') or "",
                    "poster": e.get('seriesPoster') or "",
                    "subscribed": int(e.get('seriesId') or 0) in series_sub,
                }
            })

        for m in movies:
            when = m.get('digitalRelease') or m.get('physicalRelease') or m.get('inCinemas')
            if not when:
                continue
            events.append({
                "id": f"m:{m.get('movieId') or m.get('title')}",
                "title": m.get('title') or "(movie)",
                "start": when,
                "allDay": True,
                "extendedProps": {
                    "kind": "movie",
                    "movieId": m.get('movieId'),
                    "title": m.get('title'),
                    "overview": m.get('overview') or "",
                    "poster": m.get('posterUrl') or "",
                    "subscribed": (m.get('title') or '') in movie_sub_titles,
                }
            })

        return Response({"events": events})


class SubscribeSeriesView(View):
    @method_decorator(require_POST)
    def post(self, request, series_id):
        series_data = {
            'series_id': series_id,
            'series_title': request.POST.get('series_title'),
            'series_poster': request.POST.get('series_poster'),
            'series_overview': request.POST.get('series_overview'),
            'series_genres': request.POST.getlist('series_genres[]', [])
        }
        
        subscription, created = SeriesSubscription.objects.get_or_create(
            series_id=series_id,
            defaults=series_data
        )
        
        if created:
            messages.success(request, f'Subscribed to series "{series_data["series_title"]}"!')
        else:
            messages.info(request, f'Series "{series_data["series_title"]}" was already subscribed.')
            
        return redirect('arr_api:index')

class UnsubscribeSeriesView(View):
    @method_decorator(require_POST)
    def post(self, request, series_id):
        subscription = get_object_or_404(SeriesSubscription, series_id=series_id)
        series_title = subscription.series_title
        subscription.delete()
        messages.success(request, f'Subscription for "{series_title}" has been removed.')
        return redirect('arr_api:index')

class SubscribeMovieView(View):
    @method_decorator(require_POST)
    def post(self, request, movie_id):
        movie_data = {
            'movie_id': movie_id,
            'title': request.POST.get('title'),
            'poster': request.POST.get('poster'),
            'overview': request.POST.get('overview'),
            'genres': request.POST.getlist('genres[]', []),
            'release_date': request.POST.get('release_date')
        }
        
        subscription, created = MovieSubscription.objects.get_or_create(
            movie_id=movie_id,
            defaults=movie_data
        )
        
        if created:
            messages.success(request, f'Subscribed to movie "{movie_data["title"]}"!')
        else:
            messages.info(request, f'Movie "{movie_data["title"]}" was already subscribed.')
            
        return redirect('arr_api:index')

class UnsubscribeMovieView(View):
    @method_decorator(require_POST)
    def post(self, request, movie_id):
        subscription = get_object_or_404(MovieSubscription, movie_id=movie_id)
        movie_title = subscription.title
        subscription.delete()
        messages.success(request, f'Subscription for "{movie_title}" has been removed.')
        return redirect('arr_api:index')


@require_POST
@login_required
def subscribe_series(request, series_id):
    """Subscribe to a series"""
    try:
        # Existiert bereits?
        if SeriesSubscription.objects.filter(user=request.user, series_id=series_id).exists():
            return JsonResponse({'success': True, 'already_subscribed': True})

        # Hole Serien-Details vom Sonarr
        conf = _arr_conf_from_db()
        # TODO: Sonarr API Call für Series Details

        # Erstelle Subscription
        sub = SeriesSubscription.objects.create(
            user=request.user,
            series_id=series_id,
            series_title=request.POST.get('title', ''),
            series_poster=request.POST.get('poster', ''),
            series_overview=request.POST.get('overview', ''),
            series_genres=request.POST.getlist('genres[]', [])
        )
        return JsonResponse({'success': True})

    except Exception as e:
        return JsonResponse({'error': str(e)}, status=400)

@require_POST
@login_required
def unsubscribe_series(request, series_id):
    """Unsubscribe from a series"""
    try:
        SeriesSubscription.objects.filter(user=request.user, series_id=series_id).delete()
        return JsonResponse({'success': True})
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=400)

@login_required
def is_subscribed_series(request, series_id):
    """Check if a series is subscribed"""
    is_subbed = SeriesSubscription.objects.filter(user=request.user, series_id=series_id).exists()
    return JsonResponse({'subscribed': is_subbed})

@require_POST
@login_required
def subscribe_movie(request, movie_id):
    """Subscribe to a movie"""
    try:
        # Existiert bereits?
        if MovieSubscription.objects.filter(user=request.user, movie_id=movie_id).exists():
            return JsonResponse({'success': True, 'already_subscribed': True})

        # Hole Film-Details vom Radarr
        conf = _arr_conf_from_db()
        # TODO: Radarr API Call für Movie Details

        # Erstelle Subscription
        sub = MovieSubscription.objects.create(
            user=request.user,
            movie_id=movie_id,
            title=request.POST.get('title', ''),
            poster=request.POST.get('poster', ''),
            overview=request.POST.get('overview', ''),
            genres=request.POST.getlist('genres[]', []),
            release_date=request.POST.get('release_date')
        )
        return JsonResponse({'success': True})

    except Exception as e:
        return JsonResponse({'error': str(e)}, status=400)

@require_POST
@login_required
def unsubscribe_movie(request, movie_id):
    """Unsubscribe from a movie"""
    try:
        MovieSubscription.objects.filter(user=request.user, movie_id=movie_id).delete()
        return JsonResponse({'success': True})
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=400)

@login_required
def is_subscribed_movie(request, movie_id):
    """Check if a movie is subscribed"""
    is_subbed = MovieSubscription.objects.filter(user=request.user, movie_id=movie_id).exists()
    return JsonResponse({'subscribed': is_subbed})

@login_required
def get_subscriptions(request):
    """Get all subscriptions for the user"""
    series = SeriesSubscription.objects.filter(user=request.user).values_list('series_id', flat=True)
    movies = MovieSubscription.objects.filter(user=request.user).values_list('movie_id', flat=True)
    return JsonResponse({
        'series': list(series),
        'movies': list(movies)
    })


@method_decorator(login_required, name='dispatch')
class SeriesSubscribeView(APIView):
    def post(self, request, series_id):
        from .services import sonarr_get_series
        cfg = AppSettings.current()
        details = None
        try:
            details = sonarr_get_series(series_id, base_url=cfg.sonarr_url, api_key=cfg.sonarr_api_key)
        except Exception:
            details = None
        defaults = {
            'series_title': request.data.get('title', '') if request.data else '',
            'series_poster': request.data.get('poster', '') if request.data else '',
            'series_overview': request.data.get('overview', '') if request.data else '',
            'series_genres': request.data.get('genres', []) if request.data else [],
        }
        if details:
            defaults.update({
                'series_title': details.get('series_title') or defaults['series_title'],
                'series_poster': details.get('series_poster') or defaults['series_poster'],
                'series_overview': details.get('series_overview') or defaults['series_overview'],
                'series_genres': details.get('series_genres') or defaults['series_genres'],
            })
        sub, created = SeriesSubscription.objects.get_or_create(
            user=request.user,
            series_id=series_id,
            defaults=defaults
        )
        return Response({'status': 'subscribed'}, status=status.HTTP_201_CREATED if created else status.HTTP_200_OK)

@method_decorator(login_required, name='dispatch')
class SeriesUnsubscribeView(APIView):
    def post(self, request, series_id):
        SeriesSubscription.objects.filter(user=request.user, series_id=series_id).delete()
        return Response({'status': 'unsubscribed'}, status=status.HTTP_200_OK)

@method_decorator(login_required, name='dispatch')
class MovieSubscribeView(APIView):
    def post(self, request, title):
        from .services import radarr_lookup_movie_by_title
        cfg = AppSettings.current()
        details = None
        try:
            details = radarr_lookup_movie_by_title(title, base_url=cfg.radarr_url, api_key=cfg.radarr_api_key)
        except Exception:
            details = None
        defaults = {
            'movie_id': (request.data.get('movie_id', 0) if request.data else 0) or 0,
            'poster': request.data.get('poster', '') if request.data else '',
            'overview': request.data.get('overview', '') if request.data else '',
            'genres': request.data.get('genres', []) if request.data else [],
        }
        if details:
            defaults.update({
                'movie_id': details.get('movie_id') or defaults['movie_id'],
                'poster': details.get('poster') or defaults['poster'],
                'overview': details.get('overview') or defaults['overview'],
                'genres': details.get('genres') or defaults['genres'],
            })
        sub, created = MovieSubscription.objects.get_or_create(
            user=request.user,
            title=title,
            defaults=defaults
        )
        return Response({'status': 'subscribed'}, status=status.HTTP_201_CREATED if created else status.HTTP_200_OK)

@method_decorator(login_required, name='dispatch')
class MovieUnsubscribeView(APIView):
    def post(self, request, title):
        MovieSubscription.objects.filter(user=request.user, title=title).delete()
        return Response({'status': 'unsubscribed'}, status=status.HTTP_200_OK)

@method_decorator(login_required, name='dispatch')
class ListSeriesSubscriptionsView(APIView):
    def get(self, request):
        subs = SeriesSubscription.objects.filter(user=request.user).values_list('series_id', flat=True)
        return Response(list(subs))

@method_decorator(login_required, name='dispatch')
class ListMovieSubscriptionsView(APIView):
    def get(self, request):
        subs = MovieSubscription.objects.filter(user=request.user).values_list('title', flat=True)
        return Response(list(subs))