from flask import Blueprint, render_template, request, send_file, jsonify
import math, time
from helpers.db import db_get_videos, db_get_video, db_get_recent
from helpers.favorites import mark_favorites, db_get_favorites, db_get_fav_set
from helpers.cache import build_cache
from config import VIDEOS_PER_PAGE, DASHBOARD_PER_PAGE

web = Blueprint("web", __name__)

import requests
def _get_recording_streamers() -> set[str]:
    try:
        resp = requests.get("http://localhost:5000/api/get_recording/", timeout=3)
        resp.raise_for_status()
        return resp.json()
    except Exception:
        return set()

from datetime import date, datetime, timedelta
def _parse_dates(timeframe: str, start_str: str | None, end_str: str | None):
    """Return (start, end) as date objects or (None, None). End inclusive by day."""
    today = date.today()
    if timeframe == "week":
        # This week = last 7 days ending today
        return (today - timedelta(days=6)), today
    if timeframe == "month":
        # Last 30 days
        return (today - timedelta(days=29)), today
    if timeframe == "year":
        # Last 365 days
        return (today - timedelta(days=364)), today
    if timeframe == "custom":
        try:
            s = datetime.strptime(start_str, "%Y-%m-%d").date() if start_str else None
            e = datetime.strptime(end_str, "%Y-%m-%d").date() if end_str else None
            if s and e and s > e: s, e = e, s
            return s, e
        except ValueError:
            return None, None
    # "all" or unknown → no filter
    return None, None

@web.route("/")
def dashboard():
    # ---- read filters ----
    query = request.args.get("q", "").lower().strip()
    sort = request.args.get("sort", "total_size")
    dir_ = request.args.get("dir", "desc")
    reverse = (dir_ == "desc")

    timeframe = request.args.get("timeframe", "all")
    start_str = request.args.get("start")
    end_str = request.args.get("end")
    show_online_first = request.args.get("online") == "1"

    start, end = _parse_dates(timeframe, start_str, end_str)

    # ---- build cache over timeframe ----
    cache = build_cache(start=start, end=end)
    items = list(cache["storage_usage"].items())  # [("user::platform", {...}), ...]

    # ---- search ----
    if query:
        items = [e for e in items if query in e[0].split("::")[0].lower()]

    # ---- sort keys ----
    def k_user(x): return x[0].split("::")[0].lower()
    def k_platform(x): return x[0].split("::")[1].lower()
    def k_total(x): return x[1]["total_size"]
    def k_count(x): return x[1]["video_count"]
    def k_avg(x): return cache["avg_sizes"][x[0]]

    key_map = {
        "user": k_user,
        "platform": k_platform,
        "total_size": k_total,
        "video_count": k_count,
        "avg_size": k_avg,
    }
    base_key = key_map.get(sort, k_total)

    # ---- get recording list → two sets: online + recording_offline ----
    # _get_recording_streamers() returns: [{"username": "...", "is_online": true/false}, ...]
    online_usernames: set[str] = set()
    recording_offline_usernames: set[str] = set()

    if show_online_first:
        try:
            rec_list = _get_recording_streamers()
            for s in rec_list or []:
                u = (s.get("username") or "").lower()
                if not u:
                    continue
                if s.get("is_online"):
                    online_usernames.add(u)
                else:
                    recording_offline_usernames.add(u)
        except Exception:
            pass

    def user_of(item) -> str:
        return item[0].split("::")[0]
    def is_online(item) -> bool:
        return user_of(item).lower() in online_usernames
    def is_recording_offline(item) -> bool:
        u = user_of(item).lower()
        return (u in recording_offline_usernames) and (u not in online_usernames)

    # ---- sort with optional grouping ----
    if show_online_first:
        online_items           = [x for x in items if is_online(x)]
        recording_offline_items= [x for x in items if is_recording_offline(x)]
        the_rest               = [x for x in items if (x not in online_items) and (x not in recording_offline_items)]

        online_items.sort(key=base_key, reverse=reverse)
        recording_offline_items.sort(key=base_key, reverse=reverse)
        the_rest.sort(key=base_key, reverse=reverse)

        items = online_items + recording_offline_items + the_rest
    else:
        items.sort(key=base_key, reverse=reverse)

    # ---- paginate ----
    page = max(1, int(request.args.get("page", 1)))
    total_pages = max(1, math.ceil(len(items) / DASHBOARD_PER_PAGE))
    start_idx = (page - 1) * DASHBOARD_PER_PAGE
    paginated = items[start_idx:start_idx + DASHBOARD_PER_PAGE]

    return render_template(
        "main.html",
        storage_usage=paginated,
        avg_sizes=cache["avg_sizes"],
        page=page,
        total_pages=total_pages,
        query=query,
        sort=sort,
        dir=dir_,
        timeframe=timeframe,
        start_date=start_str,
        end_date=end_str,
        online="1" if show_online_first else "0",
        # send both sets so we can color dots
        online_set=online_usernames,
        recording_offline_set=recording_offline_usernames,
    )

@web.route("/refresh")
def refresh():
    cache = build_cache()
    return jsonify({
        "status": "ok",
        "videos": sum(x["video_count"] for x in cache["storage_usage"].values()),
        "updated": time.ctime(cache["timestamp"])
    })

@web.route("/user/<username>")
def user_page(username):
    videos = db_get_videos(username=username)
    page = max(1, int(request.args.get("page", 1)))
    total_pages = max(1, math.ceil(len(videos) / VIDEOS_PER_PAGE))
    start = (page - 1) * VIDEOS_PER_PAGE
    paginated = videos[start:start + VIDEOS_PER_PAGE]
    mark_favorites(paginated)

    return render_template(
        "user_page.html",
        username=username,
        videos=paginated,
        page=page,
        total_pages=total_pages
    )

@web.route("/video/stream/<video_id>")
def stream_video(video_id):
    video = db_get_video(video_id)
    if video:
        return send_file(video["filepath"], mimetype="video/mp4")
    return "Video not found", 404

@web.route("/video/<video_id>")
def view_video(video_id):
    video = db_get_video(video_id)
    if video:
        video["is_favorite"] = (video["video_id"] in db_get_fav_set())
        return render_template("video_view.html", video=video)
    return "Video not found", 404

@web.route("/recent")
def recent():
    page = max(1, int(request.args.get("page", 1)))
    per_page = VIDEOS_PER_PAGE
    videos, total = db_get_recent(page, per_page)
    total_pages = max(1, math.ceil(total / per_page))
    mark_favorites(videos)

    return render_template(
        "recent.html",
        videos=videos,
        page=page,
        total_pages=total_pages
    )

@web.route("/favorites")
def favorites_page():
    page = max(1, int(request.args.get("page", 1)))
    per_page = VIDEOS_PER_PAGE
    videos, total = db_get_favorites(page, per_page)
    total_pages = max(1, math.ceil(total / per_page))
    mark_favorites(videos)

    return render_template(
        "favorites.html",
        videos=videos,
        page=page,
        total_pages=total_pages
    )