from urllib.parse import quote
from base.spider import Spider
import requests
from bs4 import BeautifulSoup
import re
import json

class Spider(Spider):
    def __init__(self):
        super().__init__()
        self.session = requests.Session()
        self.session.headers.update({
            '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',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
            'Accept-Encoding': 'gzip, deflate, br',
            'Connection': 'keep-alive',
            'Upgrade-Insecure-Requests': '1'
        })

    def getName(self):
        return "喜马拉雅"

    def init(self, extend):
        pass

    def homeContent(self, filter):
        categories = [
            {"type_id": "有声书", "type_name": "有声书"},
            {"type_id": "广播剧", "type_name": "广播剧"},
            {"type_id": "娱乐", "type_name": "娱乐"},
            {"type_id": "儿童", "type_name": "儿童"},
            {"type_id": "音乐", "type_name": "音乐"},
            {"type_id": "相声评书", "type_name": "相声评书"},
            {"type_id": "个人成长", "type_name": "个人成长"}
        ]
        return {"class": categories}

    def searchContent(self, key, quick, pg="1"):
        """搜索功能 - 使用网页搜索"""
        try:
            page = int(pg)
            # 喜马拉雅搜索页面
            search_url = f"https://www.ximalaya.com/search/{quote(key)}/album/{page}"
            
            response = self.session.get(search_url, timeout=10)
            response.encoding = 'utf-8'
            
            if response.status_code == 200:
                soup = BeautifulSoup(response.text, 'html.parser')
                albums = []
                
                # 解析搜索结果 - 根据实际HTML结构调整
                album_items = soup.select('.search-album-list .search-album-item') or \
                             soup.select('.album-item') or \
                             soup.select('.search-item')
                
                for item in album_items:
                    try:
                        # 提取专辑信息
                        title_elem = item.select_one('.title a, .album-name a, .title-link')
                        if not title_elem:
                            continue
                            
                        title = title_elem.get_text(strip=True)
                        album_url = title_elem.get('href', '')
                        album_id = re.search(r'/album/(\d+)', album_url)
                        album_id = album_id.group(1) if album_id else ''
                        
                        # 封面图
                        cover_elem = item.select_one('img')
                        cover = cover_elem.get('src', '') if cover_elem else ''
                        if cover and cover.startswith('//'):
                            cover = 'https:' + cover
                        
                        # 主播
                        author_elem = item.select_one('.author a, .nickname')
                        author = author_elem.get_text(strip=True) if author_elem else ''
                        
                        if album_id:
                            albums.append({
                                "vod_id": album_id,
                                "vod_name": title,
                                "vod_pic": cover,
                                "vod_remarks": author
                            })
                    except:
                        continue
                
                # 如果没解析到结果，尝试使用移动端API
                if not albums:
                    return self._search_mobile_api(key, page)
                
                return {
                    'list': albums,
                    'page': page,
                    'pagecount': 999,
                    'limit': 20,
                    'total': len(albums)
                }
                
        except Exception as e:
            print(f"搜索错误: {e}")
            return {'list': []}

    def _search_mobile_api(self, key, page):
        """使用移动端API搜索（备用）"""
        try:
            url = "https://m.ximalaya.com/search-api/v1/search"
            params = {
                'kw': key,
                'page': page,
                'per_page': 20,
                'type': 'album'
            }
            headers = {
                'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15',
                'Referer': 'https://m.ximalaya.com/'
            }
            
            response = requests.get(url, params=params, headers=headers, timeout=8)
            data = response.json()
            
            albums = []
            if data.get('data') and data['data'].get('albums'):
                for album in data['data']['albums']:
                    albums.append({
                        "vod_id": str(album.get('id', '')),
                        "vod_name": album.get('title', ''),
                        "vod_pic": album.get('coverUrl', ''),
                        "vod_remarks": album.get('nickname', '')
                    })
            
            return {
                'list': albums,
                'page': page,
                'pagecount': 999,
                'limit': 20,
                'total': len(albums)
            }
        except:
            return {'list': []}

    def detailContent(self, ids):
        """获取专辑详情"""
        try:
            album_id = ids[0]
            
            # 尝试使用移动端API获取详情
            api_url = f"https://m.ximalaya.com/album/{album_id}"
            headers = {
                'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15',
                'Referer': 'https://m.ximalaya.com/'
            }
            
            response = self.session.get(api_url, headers=headers, timeout=10)
            response.encoding = 'utf-8'
            
            soup = BeautifulSoup(response.text, 'html.parser')
            
            # 提取专辑信息
            title = soup.select_one('.title, .album-name, h1')
            title = title.get_text(strip=True) if title else ''
            
            cover = soup.select_one('.cover img, .album-cover img')
            cover = cover.get('src', '') if cover else ''
            if cover and cover.startswith('//'):
                cover = 'https:' + cover
            
            author = soup.select_one('.author-name, .nickname, .announcer')
            author = author.get_text(strip=True) if author else ''
            
            desc = soup.select_one('.desc, .album-desc, .intro')
            desc = desc.get_text(strip=True) if desc else ''
            
            # 获取音轨列表
            tracks = self._get_tracks(album_id)
            
            # 构造播放列表
            play_urls = []
            for track in tracks[:100]:  # 限制集数
                track_title = track.get('title', '')
                track_id = track.get('id', '')
                play_urls.append(f"{track_title}${album_id}_{track_id}")
            
            play_from = "喜马拉雅"
            play_url = '#'.join(play_urls) if play_urls else ''
            
            return {'list': [{
                "vod_id": album_id,
                "vod_name": title,
                "vod_pic": cover,
                "vod_actor": author,
                "vod_year": "",
                "vod_content": desc,
                "vod_remarks": f"共{len(tracks)}集",
                "vod_play_from": play_from,
                "vod_play_url": play_url
            }]}
            
        except Exception as e:
            print(f"详情错误: {e}")
            return {'list': []}

    def _get_tracks(self, album_id):
        """获取专辑音轨列表"""
        try:
            # 使用喜马拉雅API获取音轨
            api_url = f"https://m.ximalaya.com/album/{album_id}/tracks"
            params = {
                'page': 1,
                'per_page': 100
            }
            headers = {
                'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15',
                'Referer': 'https://m.ximalaya.com/'
            }
            
            response = requests.get(api_url, params=params, headers=headers, timeout=8)
            
            if response.status_code == 200:
                data = response.json()
                if data.get('data') and data['data'].get('tracks'):
                    return [{
                        'id': track.get('id'),
                        'title': track.get('title', '')
                    } for track in data['data']['tracks']]
            
            # 如果API失败，尝试解析HTML
            url = f"https://www.ximalaya.com/album/{album_id}"
            response = self.session.get(url, timeout=10)
            soup = BeautifulSoup(response.text, 'html.parser')
            
            tracks = []
            track_items = soup.select('.track-item, .sound-item, .audio-item')
            for item in track_items:
                title_elem = item.select_one('.track-title, .title')
                if title_elem:
                    track_id = item.get('data-id', '') or re.search(r'sound/(\d+)', str(item))
                    track_id = track_id.group(1) if isinstance(track_id, re.Match) else track_id
                    tracks.append({
                        'id': track_id,
                        'title': title_elem.get_text(strip=True)
                    })
            
            return tracks
            
        except Exception as e:
            print(f"获取音轨错误: {e}")
            return []

    def playerContent(self, flag, id, vipFlags):
        """获取播放地址"""
        try:
            # 解析ID: albumId_trackId
            if '_' in id:
                album_id, track_id = id.split('_', 1)
            else:
                track_id = id
                album_id = ''
            
            # 获取播放地址
            play_url = self._get_play_url(track_id)
            
            # 获取封面
            pic_url = ''
            if album_id:
                pic_url = self._get_cover(album_id)
            
            return {
                "parse": 0,
                "playUrl": '',
                "url": play_url,
                "header": {
                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                    'Referer': 'https://www.ximalaya.com/'
                },
                "pic": pic_url
            }
            
        except Exception as e:
            print(f"播放错误: {e}")
            return {
                "parse": 0, 
                "playUrl": '', 
                "url": '', 
                "header": {
                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                    'Referer': 'https://www.ximalaya.com/'
                }
            }

    def _get_play_url(self, track_id):
        """获取音轨播放地址"""
        try:
            # 使用喜马拉雅官方API获取播放地址
            api_url = f"https://www.ximalaya.com/revision/api/v1/voice/audio_url"
            params = {
                'voice_id': track_id,
                'type': 1  # 1: m4a, 0: mp3
            }
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                'Referer': 'https://www.ximalaya.com/',
                'X-Requested-With': 'XMLHttpRequest'
            }
            
            response = requests.get(api_url, params=params, headers=headers, timeout=8)
            
            if response.status_code == 200:
                data = response.json()
                if data.get('data') and data['data'].get('url'):
                    return data['data']['url']
            
            # 备用：使用移动端API
            api_url = f"https://m.ximalaya.com/v1/voice/{track_id}"
            response = requests.get(api_url, headers={
                'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15'
            }, timeout=8)
            
            if response.status_code == 200:
                data = response.json()
                if data.get('data') and data['data'].get('play_url'):
                    return data['data']['play_url']
            
            return ""
            
        except Exception as e:
            print(f"获取播放地址错误: {e}")
            return ""

    def _get_cover(self, album_id):
        """获取专辑封面"""
        try:
            url = f"https://www.ximalaya.com/album/{album_id}"
            response = self.session.get(url, timeout=5)
            soup = BeautifulSoup(response.text, 'html.parser')
            
            cover = soup.select_one('.album-cover img, .cover img')
            if cover:
                src = cover.get('src', '')
                if src and src.startswith('//'):
                    src = 'https:' + src
                return src
            return ""
        except:
            return ""

    def categoryContent(self, cid, pg, filter, ext):
        """分类浏览"""
        try:
            page = int(pg)
            # 使用分类搜索
            return self.searchContent(cid, quick=False, pg=page)
        except:
            return {'list': []}

    def localProxy(self, param):
        return []