import axios from "axios";
import CryptoJS from "crypto-js";

class YunDrive {
    constructor() {
        this.regex = /https:\/\/yun.139.com\/shareweb\/#\/w\/i\/([^&]+)/;
        this.x = CryptoJS.enc.Utf8.parse("PVGDwmcvfs1uV3d1");
        this.baseUrl = 'https://share-kd-njs.yun.139.com/yun-share/richlifeApp/devapp/IOutLink/';
        this.baseHeader = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
            'Accept': 'application/json, text/plain, */*',
            'Content-Type': 'application/json',
            'hcy-cool-flag': '1',
            'x-deviceinfo': '||3|12.27.0|chrome|131.0.0.0|5c7c68368f048245e1ce47f1c0f8f2d0||windows 10|1536X695|zh-CN|||'
        };
        this.linkID = '';
        this.cache = {}; // 添加缓存对象
    }

    encrypt(data) {
        let t = CryptoJS.lib.WordArray.random(16), n = "";
        if ("string" == typeof data) {
            const o = CryptoJS.enc.Utf8.parse(data);
            n = CryptoJS.AES.encrypt(o, this.x, {iv: t, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7});
        } else if (typeof data === 'object' && data !== null) {
            const a = JSON.stringify(data), s = CryptoJS.enc.Utf8.parse(a);
            n = CryptoJS.AES.encrypt(s, this.x, {iv: t, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7});
        }
        return CryptoJS.enc.Base64.stringify(t.concat(n.ciphertext));
    }

    decrypt(data) {
        const t = CryptoJS.enc.Base64.parse(data), n = t.clone(), i = n.words.splice(4);
        n.init(n.words), t.init(i);
        const o = CryptoJS.enc.Base64.stringify(t),
            a = CryptoJS.AES.decrypt(o, this.x, {iv: n, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7}),
            s = a.toString(CryptoJS.enc.Utf8);
        return s.toString();
    }

    async getShareID(url) {
        const matches = this.regex.exec(url) || /https:\/\/caiyun.139.com\/m\/i\?([^&]+)/.exec(url);
        if (matches && matches[1]) {
            this.linkID = matches[1];
        }
    }

    async getShareInfo(pCaID) {
        if (!this.linkID) {
            console.error('linkID is not set. Please call getShareID first.');
            return null;
        }
        const cacheKey = `${this.linkID}-${pCaID}`;
        if (this.cache[cacheKey]) {
            return this.cache[cacheKey];
        }
        let data = JSON.stringify(this.encrypt(JSON.stringify({
            "getOutLinkInfoReq": {
                "account": "",
                "linkID": this.linkID,
                "passwd": "",
                "caSrt": 0,
                "coSrt": 0,
                "srtDr": 1,
                "bNum": 1,
                "pCaID": pCaID,
                "eNum": 200
            },
            "commonAccountInfo": {"account": "", "accountType": 1}
        })));
        try {
            const resp = await axios.post(this.baseUrl + 'getOutLinkInfoV6', data, {headers: this.baseHeader});
            if (resp.status !== 200) {
                return null;
            }
            const json = JSON.parse(this.decrypt(resp.data)).data;
            this.cache[cacheKey] = json; // 缓存结果
            return json;
        } catch (error) {
            console.error('Error processing share info:', error);
            return null;
        }
    }

    async getShareData(url) {
        if (!url) {
            return {};
        }
        const isValidUrl = url.startsWith('http');
        let pCaID = isValidUrl ? 'root' : url;
        if (isValidUrl) {
            await this.getShareID(url);
        }
        let file = {};
        let fileInfo = await this.getShareFile(pCaID);
        if (fileInfo && Array.isArray(fileInfo)) {
            await Promise.all(fileInfo.map(async (item) => {
                if (!(item.name in file)) {
                    file[item.name] = [];
                }
                let filelist = await this.getShareUrl(item.path);
                if (filelist && filelist.length > 0) {
                    file[item.name].push(...filelist);
                }
            }));
        }
        for (let key in file) {
            if (file[key].length === 0) {
                delete file[key];
            }
        }
        if (Object.keys(file).length === 0) {
            file['root'] = await this.getShareFile(url);
            if (file['root'] && Array.isArray(file['root'])) {
                file['root'] = file['root'].filter(item => item && Object.keys(item).length > 0);
            }
        }
        return file;
    }

    async getShareFile(pCaID) {
        if (!pCaID) {
            return null;
        }
        try {
            const isValidUrl = pCaID.startsWith('http');
            pCaID = isValidUrl ? 'root' : pCaID;
            const json = await this.getShareInfo(pCaID);
            if (!json || !json.caLst) {
                return null;
            }
            const caLst = json?.caLst;
            const names = caLst.map(it => it.caName);
            const rootPaths = caLst.map(it => it.path);
            const filterRegex = /App|活动中心|免费|1T空间|免流/;
            const videos = [];
            if (caLst && caLst.length > 0) {
                names.forEach((name, index) => {
                    if (!filterRegex.test(name)) {
                        videos.push({name: name, path: rootPaths[index]});
                    }
                });
                let result = await Promise.all(rootPaths.map(async (path) => this.getShareFile(path)));
                result = result.filter(item => item !== undefined && item !== null);
                return [...videos, ...result.flat()];
            }
        } catch (error) {
            console.error('Error processing share data:', error);
            return null;
        }
    }

    async getShareUrl(pCaID) {
        try {
            const json = await this.getShareInfo(pCaID);
            if (!json || !('coLst' in json)) {
                return null;
            }
            const coLst = json.coLst;
            if (coLst !== null) {
                const filteredItems = coLst.filter(it => it && it.coType === 3);
                return filteredItems.map(it => ({
                    name: it.coName,
                    contentId: it.coID,
                    linkID: this.linkID
                }));
            } else if (json.caLst !== null) {
                const rootPaths = json.caLst.map(it => it.path);
                let result = await Promise.all(rootPaths.map(path => this.getShareUrl(path)));
                result = result.filter(item => item && item.length > 0);
                return result.flat();
            }
        } catch (error) {
            console.error('Error processing share URL:', error);
            return null;
        }
    }

    async getSharePlay(contentId, linkID) {
        let data = {
            "getContentInfoFromOutLinkReq": {
                "contentId": contentId,
                "linkID": linkID,
                "account": ""
            },
            "commonAccountInfo": {
                "account": "",
                "accountType": 1
            }
        };
        let resp = await axios.post(this.baseUrl + 'getContentInfoFromOutLink', data, {
            headers: {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
                'Accept': 'application/json, text/plain, */*',
                'Accept-Encoding': 'gzip, deflate, br, zstd',
                'Content-Type': 'application/json'
            }
        })
        if (resp.status === 200 && resp.data.data !== null) {
            let data = resp.data
            return data.data.contentInfo.presentURL
        }

    }
}

export const Yun = new YunDrive();
