# -*- coding: utf-8 -*-
# by @嗷呜
import json
import random
import sys
from base64 import b64encode, b64decode
from concurrent.futures import ThreadPoolExecutor

# 引入 RSA 加解密所需模块
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5

sys.path.append('..')
from base.spider import Spider

class Spider(Spider):

    def init(self, extend=""):
        did = self.getdid()
        self.headers.update({'deviceId': did})
        token = self.gettk()
        self.headers.update({'token': token})

    def getName(self):
        pass

    def isVideoFormat(self, url):
        pass

    def manualVideoCheck(self):
        pass

    def destroy(self):
        pass

    # 1. 修改为主机域名
    host = 'http://qkys.qukanwh.com'

    # 2. 同步原脚本的配置请求头
    headers = {
        'HOST': 'qkys.qukanwh.com',
        'User-Agent': 'okhttp/4.12.0',
        'client': 'app',
        'deviceType': 'Android',
        'Referer': ''
    }

    # 3. 导入原脚本中的 RSA 密钥对与配置
    publicKey_str = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCoYt0BP77U+DM08BiI/QbSRIfxijXo85BTPqIM1Ow8BNwhLETzRIZ+dEwdWDbydG/PspgBAfRpGaYVdJYtvaC2JnoO8+Ik6qMWojfEJxSFLa0Pb0A892tun4gsxoEMjcreZ+YGyaBxAfqX0BSMfdrOgIYaZQjYrw9TRLlUT31QoQIDAQAB\n-----END PUBLIC KEY-----"
    privateKey_str = "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCquQQ5r6+yJI8CDFkXRp8vUsdD45ov8EP12ooLs56ca2DQXaSNGS9910bAPVA9chkp0mKIvKqjAsHz5Tl9EeNPblarGEeJUIxpxZtiSqNTpvtiD/TjhpzuHYic7RAfQ/h7p/ypE8ymU42pYjsB5t26Mv6XgkLV+jzrSf73HlCuS0iMyLmt6zz3Mw9izM13EpB8iFLtfbbYymycKTx4RAmPQLwhNGex/AlUIYxXP4R2yyaa4W6mEtc6aME2QuzJFxPgP3HJ9NBx/LWVn4skxWjZ7zg+VRQRHnjyVaSLu3Z5gN5ITWCyE32qaHJa6WBahZj5jWhRyAG1bQ+xKJa8lBL5AgMBAAECggEAUwv9SjJ0PSwbhNuM2w23kcWquROWhYtTA91zGY4esehqB/IFgb2mpIh8Gje5OKqwIu/8jpd4SiOlRYdUF8sD0DfUYRZGdj2AkFNX6tBz8tVfo6wvbB6naA1lzzBij1L5JO3qsjS3cJFkb+kg2yP66AC2Z+0tpfk8eRhdtshAZwfcd1DEGt1uAvYL1eaUK9HRvpt9lPeGcHERDl2hBd4uyaF0K1O+zF9y59nYbTySWPxRZq3sFEE85xRMlstD7YZi7W2gKvMFRD4/FKmrZ3m7aKJRITtyKOyyPcYmepNv3Qv7kk59Pg38n2WWQ0Ra/bCH3E48YNCnQvZMpitkTfJhoQKBgQDbnROOYTP8OTJ6f/qhoGjxeO3x1VOaOp8l0x7b0SCfoqNGS0Cyiqj72BmJtPMPqSTjn6MmNzqbg1KOdhXyzNozs+i5ccW1M56j96mr5I/Z0FpE3oyIHNfDDBlf9M8YQqEF9oYxniYYft9oapO7cRQkHER6qpvnHTavwlv4m78CXwKBgQDHAjs2YlpKDdI1lcbZJCc7TwtH+Pd2bUki8YXafWNcPhITQHbOZjr310eK1QJC6GJncjkOqbX7yv3ivvTO35FZTQhuA1xEG1P00FG8bE0tHYPIwQHi9y0eA5cieMdo8E6XYria1mw/3fqSQEsfZyJlR32JQIoGAipM8iO1X2nZpwKBgDkMFIhnt5lNQk+P7wsNIDWZtDWdtJnboHuy29E+Abt2A/O+mI/IdRz2hau/1WO8DFkUnszOi+rZshhPlGP90rCbi1igtTrcrdjp/KkqNjPea5R4OwkgdOu1uOG0NheXNzzVTQaWjk7Opjn5dWa7eP/oV+GFb/oZHJuLYVizHGsBAoGADA7rjZEKDYCm4w5PPSr+oY5ZjaPdQrS+gLqHtMRyN82fBMGcMUdqfUfzEstzVqCEDeaS5HuOBlK3bXzKkppjUTjksN3NQmcxgBz7RuJ9DqXCLXDcb2cwuafYCYOt+YLOEEgwDVm+t2P44dG5e46hO+fICH/7nP+WlpD5buz4GfMCgYB57r3g/6hi9WUDnfc7ZAzWMqR0EhJVYKYy+KFEtdIPzhkkIHq5RASe88E9kzoGoZFdb3tIjvGZWcHerirrqWkMsuQtP/Qi0zjieid5tAPj+r4kbiCVTw0E0jnmPBzGInQi7lpeTTKnG1fbyS5lBS+WmHfIuzpECgCkxhaT+LJJkg==\n-----END PRIVATE KEY-----"

    # RSA 公钥加密实现
    def rsa_encrypt(self, text):
        try:
            key = RSA.import_key(self.publicKey_str)
            cipher = PKCS1_v1_5.new(key)
            cipher_text = cipher.encrypt(text.encode('utf-8'))
            return b64encode(cipher_text).decode('utf-8')
        except Exception as e:
            print(f"RSA加密失败: {e}")
            return ""

    # RSA 私钥解密实现
    def rsa_decrypt(self, text):
        try:
            key = RSA.import_key(self.privateKey_str)
            cipher = PKCS1_v1_5.new(key)
            raw_bytes = b64decode(text.encode('utf-8'))
            
            decrypted = b""
            offset = 0
            while offset < len(raw_bytes):
                chunk = raw_bytes[offset:offset + 256]
                decrypted += cipher.decrypt(chunk, None)
                offset += 256
            return decrypted.decode('utf-8')
        except Exception as e:
            print(f"RSA解密失败: {e}")
            return ""

    def homeContent(self, filter):
        data = self.post(f"{self.host}/api/v1/app/screen/screenType", headers=self.headers).json()
        result = {}
        cate = {
            "类型": "type",
            "地区": "area",
            "年份": "year"
        }
        sort = {
            'key': 'sort',
            'name': '排序',
            'value': [{'n': '最新', 'v': 'NEWEST'}, {'n': '热门', 'v': 'HOT'}, {'n': '收藏', 'v': 'COLLECT'}]
        }
        classes = []
        filters = {}
        for k in data.get('data', []):
            classes.append({
                'type_name': k['name'],
                'type_id': str(k['id'])
            })
            filters[str(k['id'])] = []
            for v in k.get('children', []):
                if v['name'] in cate:
                    filters[str(k['id'])].append({
                        'name': v['name'],
                        'key': cate[v['name']],
                        'value': [{'n': i['name'], 'v': i['name']} for i in v.get('children', [])]
                    })
            filters[str(k['id'])].append(sort)
        result['class'] = classes
        result['filters'] = filters
        return result

    def homeVideoContent(self):
        jdata = {
            "condition": {
                "sreecnTypeEnum": "NEWEST"
            },
            "pageNum": 1,
            "pageSize": 40
        }
        data = self.post(f"{self.host}/api/v1/app/screen/screenMovie", headers=self.headers, json=jdata).json()
        return {'list': self.getlist(data.get('data', {}).get('records', []))}

    def categoryContent(self, tid, pg, filter, extend):
        # 保持最纯粹的条件字段，移除任何空字符串占位
        condition = {
            'sreecnTypeEnum': 'NEWEST',
            'typeId': int(tid) if str(tid).isdigit() else tid
        }
        
        if extend:
            if 'sort' in extend:
                condition['sreecnTypeEnum'] = extend.pop('sort')
            condition.update(extend)
            
        jdata = {
            'condition': condition,
            'pageNum': int(pg),
            'pageSize': 40,
        }
        
        try:
            data = self.post(f"{self.host}/api/v1/app/screen/screenMovie", headers=self.headers, json=jdata).json()
            result = {}
            if data and data.get('data') and 'records' in data['data']:
                result['list'] = self.getlist(data['data']['records'])
            else:
                result['list'] = []
            result['page'] = pg
            result['pagecount'] = 9999
            result['limit'] = 40
            result['total'] = 999999
            return result
        except Exception as e:
            print(f"分类获取错误: {e}")
            return {'list': [], 'page': pg}

    def detailContent(self, ids):
        ids = ids[0].split('@@')
        jdata = {"id": int(ids[0]), "typeId": ids[-1]}
        v = self.post(f"{self.host}/api/v1/app/play/movieDesc", headers=self.headers, json=jdata).json()
        v = v.get('data', {})
        vod = {
            'type_name': v.get('typeId', ''),
            'vod_year': v.get('year', ''),
            'vod_area': v.get('area', ''),
            'vod_actor': v.get('star', ''),
            'vod_director': v.get('director', ''),
            'vod_content': v.get('introduce', ''),
            'vod_play_from': '',
            'vod_play_url': ''
        }

        play_params = {
            "id": int(ids[0]),
            "source": 0,
            "typeId": ids[-1]
        }
        encrypt_payload = {"key": self.rsa_encrypt(json.dumps(play_params))}
        
        c_res = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=encrypt_payload).json()
        decrypted_play_str = self.rsa_decrypt(c_res.get('data', ''))
        if not decrypted_play_str:
            return {'list': [vod]}
            
        decrypted_play_data = json.loads(decrypted_play_str)
        l = decrypted_play_data.get('moviePlayerList', [])
        if not l:
            return {'list': [vod]}
            
        n = {str(i['id']): i['moviePlayerName'] for i in l}
        
        m = play_params.copy()
        m.update({'playerId': l[0]['id']})
        
        first_source_payload = {"key": self.rsa_encrypt(json.dumps(m))}
        first_res = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=first_source_payload).json()
        
        decrypted_first_str = self.rsa_decrypt(first_res.get('data', ''))
        if decrypted_first_str:
            decrypted_first_episode = json.loads(decrypted_first_str)
            pd = self.getv(m, decrypted_first_episode.get('episodeList', []))
        else:
            pd = {}
        
        if len(l) > 1:
            with ThreadPoolExecutor(max_workers=len(l)-1) as executor:
                future_to_player = {executor.submit(self.getd, play_params, player): player for player in l[1:]}
                for future in future_to_player:
                    try:
                        o, p = future.result()
                        if p:
                            pd.update(self.getv(o, p))
                    except Exception as e:
                        print(f"多线路请求失败: {e}")
        w, e = [], []
        for i, x in pd.items():
            if x:
                w.append(n.get(i, '未知线路'))
                e.append(x)
        vod['vod_play_from'] = '$$$'.join(w)
        vod['vod_play_url'] = '$$$'.join(e)
        return {'list': [vod]}

    def searchContent(self, key, quick, pg="1"):
        jdata = {
            "condition": {
                "value": str(key)
            },
            "pageNum": int(pg),
            "pageSize": 40
        }
        try:
            data = self.post(f"{self.host}/api/v1/app/search/searchMovie", headers=self.headers, json=jdata).json()
            return {'list': self.getlist(data.get('data', {}).get('records', [])), 'page': pg}
        except Exception as e:
            print(f"搜索请求失败: {e}")
            return {'list': [], 'page': pg}

    def playerContent(self, flag, id, vipFlags):
        raw_id_str = self.d64(id)
        if not raw_id_str:
            return {'parse': 0, 'url': ''}
        jdata = json.loads(raw_id_str)
        encrypt_payload = {"key": self.rsa_encrypt(json.dumps(jdata))}
        data = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=encrypt_payload).json()
        
        try:
            decrypted_url_data = json.loads(self.rsa_decrypt(data.get('data', '')))
            playerUrl = decrypted_url_data.get('url', '')
            if not playerUrl:
                return {'parse': 0, 'url': ''}
            
            params = {'playerUrl': playerUrl, 'playerId': jdata['playerId']}
            pd = self.fetch(f"{self.host}/api/v1/app/play/analysisMovieUrl", headers=self.headers, params=params).json()
            url, p = pd.get('data', ''), 0
        except Exception as e:
            print(f"解析流媒体直链失败: {e}")
            url, p = "", 0
        return {'parse': p, 'url': url, 'header': {'User-Agent': 'okhttp/4.12.0'}}

    def localProxy(self, param):
        pass

    def liveContent(self, url):
        pass

    def gettk(self):
        self.headers.update({'deviceId': self.getdid()})
        try:
            data = self.fetch(f"{self.host}/api/v1/app/user/visitorInfo", headers=self.headers).json()
            return data.get('data', {}).get('token', '')
        except:
            return ""

    def getdid(self):
        did = self.getCache('ldid')
        if not did:
            hex_chars = '0123456789abcdef'
            did = ''.join(random.choice(hex_chars) for _ in range(16))
            self.setCache('ldid', did)
        return did

    def getd(self, jdata, player):
        x = jdata.copy()
        x.update({'playerId': player['id']})
        encrypt_payload = {"key": self.rsa_encrypt(json.dumps(x))}
        response = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=encrypt_payload).json()
        decrypted_str = self.rsa_decrypt(response.get('data', ''))
        if decrypted_str:
            decrypted_episode = json.loads(decrypted_str)
            return x, decrypted_episode.get('episodeList', [])
        return x, []

    def getv(self, d, c):
        f = {str(d['playerId']): ''}
        g = []
        for i in c:
            j = d.copy()
            j.update({'episodeId': i['id']})
            g.append(f"{i['episode']}${self.e64(json.dumps(j))}")
        f[str(d['playerId'])] = '#'.join(g)
        return f

    def getlist(self, data):
        videos = []
        for i in data:
            if not i.get('id'):
                continue
            videos.append({
                'vod_id': f"{i['id']}@@{i.get('typeId', '')}",
                'vod_name': i.get('name', ''),
                'vod_pic': i.get('cover', ''),
                'vod_year': i.get('year', ''),
                'vod_remarks': i.get('totalEpisode', '')
            })
        return videos

    def e64(self, text):
        try:
            return b64encode(text.encode('utf-8')).decode('utf-8')
        except:
            return ""

    def d64(self, encoded_text):
        try:
            return b64decode(encoded_text.encode('utf-8')).decode('utf-8')
        except:
            return ""
