import logging
from dataclasses import dataclass

import pendulum
import requests
from bs4 import BeautifulSoup
from videos.metadata import VideoMetadata, VideoType

logger = logging.getLogger(__name__)

TWITCH_VIDEO_URL = "https://www.twitch.tv/videos/{video_id}"
TWITCH_CHANNEL_URL = "https://www.twitch.tv/{handle}"


@dataclass
class ChannelMetadata:
    name: str = ""
    display_name: str = ""
    profile_image_url: str = ""
    bio: str = ""
    twitch_id: str = ""


def lookup_channel_from_twitch(handle: str) -> ChannelMetadata:
    channel_metadata = ChannelMetadata(twitch_id=handle)

    url = TWITCH_CHANNEL_URL.format(handle=handle)
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    }

    try:
        response = requests.get(url, headers=headers, timeout=10)
    except requests.RequestException as e:
        logger.warning(f"Failed to fetch Twitch channel page: {e}")
        return channel_metadata

    if response.status_code != 200:
        logger.warning(f"Twitch channel page returned status {response.status_code}")
        return channel_metadata

    soup = BeautifulSoup(response.text, "html.parser")

    title_tag = soup.find("meta", property="og:title")
    if title_tag:
        content = title_tag.get("content", "")
        if " on Twitch" in content:
            channel_metadata.display_name = content.replace(" on Twitch", "").strip()
        else:
            channel_metadata.display_name = content
        channel_metadata.name = channel_metadata.display_name.replace(
            " - Twitch", ""
        ).strip()

    description_tag = soup.find("meta", property="og:description")
    if description_tag:
        channel_metadata.bio = description_tag.get("content", "")

    image_tag = soup.find("meta", property="og:image")
    if image_tag:
        channel_metadata.profile_image_url = image_tag.get("content", "")

    return channel_metadata


def get_channel_vods(handle: str) -> list:
    """Get recent VODs for a channel by scraping the channel's videos page."""
    import re

    url = f"https://www.twitch.tv/{handle}/videos"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    }

    try:
        response = requests.get(url, headers=headers, timeout=10)
    except requests.RequestException as e:
        logger.warning(f"Failed to fetch Twitch channel videos page: {e}")
        return []

    if response.status_code != 200:
        logger.warning(f"Twitch videos page returned status {response.status_code}")
        return []

    page_text = response.text
    vods = []

    video_pattern = r'"url":\s*"https://www\.twitch\.tv/videos/(\d+)"'
    url_matches = re.findall(video_pattern, page_text)

    upload_pattern = r'"uploadDate":\s*"([^"]+)"'
    date_matches = re.findall(upload_pattern, page_text)

    name_pattern = r'"name":\s*"([^"]+)"'
    name_matches = re.findall(name_pattern, page_text)

    for i, video_id in enumerate(url_matches):
        title = name_matches[i] if i < len(name_matches) else ""
        published_at = date_matches[i] if i < len(date_matches) else ""

        vods.append(
            {
                "id": video_id,
                "title": title,
                "published_at": published_at,
                "thumbnail": None,
            }
        )

    logger.info(f"[get_channel_vods] Found {len(vods)} VODs for {handle}")
    print(vods)
    return vods


def parse_twitch_datetime(date_str: str):
    """Parse Twitch datetime string to timezone-aware datetime."""
    if not date_str:
        return None
    try:
        return pendulum.parse(date_str)
    except Exception:
        return None


def lookup_video_from_twitch(twitch_video_id: str) -> VideoMetadata:
    video_metadata = VideoMetadata(twitch_id=twitch_video_id)

    url = TWITCH_VIDEO_URL.format(video_id=twitch_video_id)
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    }

    try:
        response = requests.get(url, headers=headers, timeout=10)
    except requests.RequestException as e:
        logger.warning(f"Failed to fetch Twitch page: {e}")
        return video_metadata

    if response.status_code != 200:
        logger.warning(f"Twitch page returned status {response.status_code}")
        return video_metadata

    soup = BeautifulSoup(response.text, "html.parser")

    title_tag = soup.find("meta", property="og:title")
    if title_tag:
        video_metadata.title = title_tag.get("content", "")

    description_tag = soup.find("meta", property="og:description")
    if description_tag:
        video_metadata.overview = description_tag.get("content", "")

    image_tag = soup.find("meta", property="og:image")
    if image_tag:
        video_metadata.cover_url = image_tag.get("content", "")

    duration_tag = soup.find("meta", property="og:video:duration")
    if duration_tag:
        video_metadata.base_run_time_seconds = int(duration_tag.get("content", 900))

    release_date_tag = soup.find("meta", property="og:video:release_date")
    if release_date_tag:
        try:
            video_metadata.upload_date = pendulum.parse(
                release_date_tag.get("content")
            ).date()
            video_metadata.year = video_metadata.upload_date.year
        except Exception:
            pass

    video_metadata.twitch_id = twitch_video_id
    video_metadata.video_type = VideoType.TWITCH.value

    title = video_metadata.title
    if title and " - " in title:
        channel_name = title.split(" - ")[-1].replace(" on Twitch", "").strip()
        if channel_name:
            try:
                from videos.models import Channel

                channel, _ = Channel.objects.get_or_create(
                    name=channel_name,
                    defaults={"name": channel_name},
                )
                video_metadata.channel_id = channel.id
            except Exception as e:
                logger.warning(f"Failed to get or create channel: {e}")

    return video_metadata
