<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Wool-Tube</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #000066;
            min-height: 100vh;
            padding: 20px;
            transition: background 0.3s;
        }

        body.light-mode {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
        }

        h1 {
            color: white;
            text-align: center;
            margin-bottom: 30px;
            font-size: 2.5em;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 15px;
        }

        .logo {
            width: 80px;
            height: 80px;
            background: white;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 45px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.3);
            animation: float 3s ease-in-out infinite;
        }

        @keyframes float {
            0%, 100% { transform: translateY(0px); }
            50% { transform: translateY(-10px); }
        }

        .search-box {
            background: linear-gradient(135deg, #4a0e34 0%, #2d1b3d 100%);
            padding: 30px;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.3);
            margin-bottom: 30px;
            transition: background 0.3s;
        }

        body.light-mode .search-box {
            background: white;
        }

        .input-group {
            display: flex;
            gap: 10px;
            margin-bottom: 15px;
        }

        input[type="text"] {
            flex: 1;
            padding: 15px;
            border: 2px solid rgba(255,255,255,0.3);
            border-radius: 8px;
            font-size: 16px;
            transition: border-color 0.3s, background 0.3s;
            background: #000000;
            color: white;
        }

        body.light-mode input[type="text"] {
            background: white;
            color: #333;
            border: 2px solid #e0e0e0;
        }

        input[type="text"]::placeholder {
            color: rgba(255,255,255,0.5);
        }

        body.light-mode input[type="text"]::placeholder {
            color: rgba(0,0,0,0.5);
        }

        input[type="text"]:focus {
            outline: none;
            border-color: #7b1fa2;
            background: #1a1a1a;
        }

        body.light-mode input[type="text"]:focus {
            background: #f9f9f9;
            border-color: #7b1fa2;
        }

        button {
            padding: 15px 30px;
            background: linear-gradient(135deg, #7b1fa2 0%, #4a148c 100%);
            color: white;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            font-weight: bold;
            cursor: pointer;
            transition: transform 0.2s, box-shadow 0.2s;
        }

        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(123,31,162,0.5);
        }

        button:active {
            transform: translateY(0);
        }

        button:disabled {
            opacity: 0.5;
            cursor: not-allowed;
            transform: none;
        }

        .player-section {
            background: white;
            padding: 30px;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.3);
            margin-bottom: 30px;
        }

        #player {
            width: 100%;
            aspect-ratio: 16/9;
            border-radius: 10px;
            background: #000;
        }

        #playerContainer {
            width: 100%;
            aspect-ratio: 16/9;
            border-radius: 10px;
            overflow: hidden;
            background: #000;
        }

        video {
            width: 100%;
            height: 100%;
            border-radius: 10px;
        }

        .controls {
            display: flex;
            gap: 10px;
            margin-top: 15px;
            flex-wrap: wrap;
        }

        .controls button {
            flex: 1;
            min-width: 100px;
        }

        .quality-controls {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
            gap: 10px;
            margin-top: 15px;
        }

        .quality-controls button {
            min-width: 120px;
            padding: 12px 20px;
            font-size: 14px;
        }

        .quality-controls button.active {
            background: linear-gradient(135deg, #4CAF50 0%, #388E3C 100%);
            box-shadow: 0 3px 10px rgba(76,175,80,0.4);
        }

        .results {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
            gap: 20px;
        }

        .video-card {
            background: white;
            border-radius: 10px;
            overflow: hidden;
            box-shadow: 0 5px 15px rgba(0,0,0,0.2);
            cursor: pointer;
            transition: transform 0.3s, box-shadow 0.3s;
        }

        .video-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 25px rgba(0,0,0,0.3);
        }

        .video-card img {
            width: 100%;
            height: 180px;
            object-fit: cover;
        }

        .video-info {
            padding: 15px;
        }

        .video-title {
            font-weight: bold;
            margin-bottom: 8px;
            font-size: 14px;
            line-height: 1.4;
            display: -webkit-box;
            -webkit-line-clamp: 2;
            -webkit-box-orient: vertical;
            overflow: hidden;
        }

        .video-channel {
            color: #666;
            font-size: 12px;
        }

        .loading {
            text-align: center;
            color: white;
            font-size: 18px;
            margin: 20px 0;
        }

        .error {
            background: #ff5252;
            color: white;
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 20px;
        }

        .info {
            background: #4CAF50;
            color: white;
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 20px;
        }

        #currentVideo {
            text-align: center;
            margin-bottom: 15px;
            font-size: 18px;
            font-weight: bold;
            color: #333;
        }

        .stream-url {
            margin-top: 15px;
            padding: 10px;
            background: #f5f5f5;
            border-radius: 5px;
            font-size: 12px;
            word-break: break-all;
        }

        .api-note {
            font-size: 12px;
            color: rgba(255,255,255,0.9);
            margin-top: 10px;
            transition: color 0.3s;
        }

        body.light-mode .api-note {
            color: #666;
        }

        .theme-toggle {
            position: fixed;
            top: 20px;
            right: 20px;
            background: rgba(255,255,255,0.2);
            border: none;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            cursor: pointer;
            font-size: 24px;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s;
            box-shadow: 0 4px 10px rgba(0,0,0,0.3);
            z-index: 1000;
        }

        .theme-toggle:hover {
            transform: scale(1.1);
            background: rgba(255,255,255,0.3);
        }

        body.light-mode .theme-toggle {
            background: rgba(0,0,0,0.1);
        }

        body.light-mode .theme-toggle:hover {
            background: rgba(0,0,0,0.2);
        }
    </style>
</head>
<body>
    <button class="theme-toggle" onclick="toggleTheme()" id="themeToggle">🌙</button>
    
    <div class="container">
        <h1>
            <div class="logo">🐑</div>
            Wool-Tube
        </h1>
        
        <div class="search-box">
            <div class="input-group">
                <input type="text" id="apiKey" placeholder="Google API Key(オプション)">
            </div>
            <div class="input-group">
                <input type="text" id="searchQuery" placeholder="検索キーワードまたはYouTube URLを入力" onkeypress="if(event.key==='Enter') searchVideos()">
                <button onclick="searchVideos()">🔍 検索</button>
            </div>
            <div class="api-note">
                ※Google API Keyを入力すると、YouTube Data API v3で検索します(より正確な検索結果)<br>
                APIキーなしでも、代替APIで検索可能です<br>
                🌐 GitHub Pages対応: CORSプロキシ経由で通信します
            </div>
        </div>

        <div class="player-section" id="playerSection" style="display: none;">
            <div id="currentVideo"></div>
            <div id="playerContainer">
                <iframe id="player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
            </div>
            <div class="controls">
                <button onclick="setPlayMode('stream')" id="btnStream">🎬 ストリーム再生</button>
                <button onclick="setPlayMode('embed')">📺 埋め込み再生</button>
                <button onclick="setPlayMode('nocookie')">🍪 No Cookie</button>
                <button onclick="setPlayMode('education')">📚 Education</button>
            </div>
            <div class="controls">
                <button onclick="downloadVideo('video')" id="btnDownloadVideo">📥 動画DL</button>
                <button onclick="downloadVideo('audio')" id="btnDownloadAudio">🎵 音声DL</button>
            </div>
            <div class="quality-controls" id="qualityControls" style="display: none;"></div>
            <div class="stream-url" id="streamUrl"></div>
            <div style="margin-top: 10px; padding: 10px; background: #1a1a1a; border-radius: 5px; color: #00ff00; font-family: monospace; font-size: 11px; max-height: 200px; overflow-y: auto; display: none;" id="debugLog"></div>
        </div>

        <div id="loading" class="loading" style="display: none;">読み込み中...</div>
        <div id="error" class="error" style="display: none;"></div>
        <div id="info" class="info" style="display: none;"></div>
        
        <div class="results" id="results"></div>
    </div>

    <script>
        let currentVideoId = null;
        let availableStreams = [];
        let currentPlayMode = 'embed';
        let debugMessages = [];
        let currentQuality = null;
        
        function addDebug(msg) {
            debugMessages.push(`[${new Date().toLocaleTimeString()}] ${msg}`);
            const debugLog = document.getElementById('debugLog');
            if (debugLog) {
                debugLog.style.display = 'block';
                debugLog.innerHTML = debugMessages.slice(-15).join('<br>');
            }
            console.log(msg);
        }
        
        // CORSプロキシ設定
        const CORS_PROXIES = [
            'https://api.allorigins.win/raw?url=',
            'https://corsproxy.io/?',
            'https://api.codetabs.com/v1/proxy?quest='
        ];
        let currentProxyIndex = 0;

        function getProxiedUrl(url) {
            const proxy = CORS_PROXIES[currentProxyIndex];
            return `${proxy}${encodeURIComponent(url)}`;
        }

        function rotateProxy() {
            currentProxyIndex = (currentProxyIndex + 1) % CORS_PROXIES.length;
            addDebug(`🔄 プロキシ切り替え: ${CORS_PROXIES[currentProxyIndex]}`);
        }

        const streamAPIs = [
            {
                name: 'Invidious',
                servers: [
                    'https://nyc1.iv.ggtyler.dev',
                    'https://invid-api.poketube.fun',
                    'https://cal1.iv.ggtyler.dev',
                    'https://invidious.nikkosphere.com',
                    'https://lekker.gay',
                    'https://invidious.f5.si',
                    'https://invidious.lunivers.trade',
                    'https://pol1.iv.ggtyler.dev',
                    'https://eu-proxy.poketube.fun',
                    'https://iv.melmac.space',
                    'https://invidious.reallyaweso.me',
                    'https://invidious.dhusch.de',
                    'https://usa-proxy2.poketube.fun',
                    'https://id.420129.xyz',
                    'https://invidious.darkness.service',
                    'https://iv.datura.network',
                    'https://invidious.jing.rocks',
                    'https://invidious.private.coffee',
                    'https://youtube.mosesmang.com',
                    'https://iv.duti.dev',
                    'https://invidious.projectsegfau.lt',
                    'https://invidious.perennialte.ch',
                    'https://invidious.einfachzocken.eu',
                    'https://invidious.adminforge.de',
                    'https://inv.nadeko.net',
                    'https://invidious.esmailelbob.xyz',
                    'https://invidious.0011.lt',
                    'https://invidious.ducks.party',
                    'https://invidious.fdn.fr',
                    'https://invidious.privacydev.net',
                    'https://iv.nboeck.de',
                    'https://invidious.protokolla.fi',
                    'https://invidious.slipfox.xyz',
                    'https://inv.bp.projectsegfau.lt',
                    'https://yt.artemislena.eu',
                    'https://invidious.flokinet.to',
                    'https://invidious.kavin.rocks',
                    'https://vid.puffyan.us',
                    'https://inv.riverside.rocks',
                    'https://invidious.tiekoetter.com',
                    'https://inv.vern.cc',
                    'https://invidious.nerdvpn.de',
                    'https://inv.us.projectsegfau.lt',
                    'https://invidious.lunar.icu',
                    'https://inv.in.projectsegfau.lt',
                    'https://yt.drgnz.club',
                    'https://inv.tux.pizza',
                    'https://iv.ggtyler.dev',
                    'https://inv.citw.lgbt',
                    'https://inv.odyssey346.dev',
                    'https://yewtu.be',
                    'https://invidious.snopyta.org',
                    'https://vid.mint.lgbt',
                    'https://invidious.sethforprivacy.com',
                    'https://invidious.namazso.eu'
                ],
                getUrl: (server, videoId) => `${server}/api/v1/videos/${videoId}`,
                parseResponse: (data) => {
                    const streams = [];
                    
                    if (data.formatStreams && data.formatStreams.length > 0) {
                        data.formatStreams.forEach(s => {
                            if (s.url) {
                                streams.push({ 
                                    url: s.url, 
                                    quality: s.qualityLabel || s.quality || 'unknown', 
                                    type: 'Invidious',
                                    hasAudio: true
                                });
                            }
                        });
                    }
                    
                    if (data.adaptiveFormats && data.adaptiveFormats.length > 0) {
                        data.adaptiveFormats.forEach(s => {
                            if (s.url && s.type && s.type.includes('video')) {
                                streams.push({ 
                                    url: s.url, 
                                    quality: s.qualityLabel || 'auto', 
                                    type: 'Invidious',
                                    hasAudio: false
                                });
                            }
                        });
                    }
                    
                    return streams;
                }
            },
            {
                name: 'Piped',
                servers: [
                    'https://pipedapi.kavin.rocks',
                    'https://api-piped.mha.fi',
                    'https://pipedapi.tokhmi.xyz',
                    'https://pipedapi.adminforge.de',
                    'https://api.piped.projectsegfau.lt',
                    'https://pipedapi.pfcd.me',
                    'https://api.piped.privacydev.net',
                    'https://pipedapi.in.projectsegfau.lt',
                    'https://pipedapi.osphost.fi'
                ],
                getUrl: (server, videoId) => `${server}/streams/${videoId}`,
                parseResponse: (data) => {
                    if (!data.videoStreams) return [];
                    return data.videoStreams.map(s => ({
                        url: s.url,
                        quality: s.quality,
                        type: 'Piped',
                        hasAudio: true
                    }));
                }
            },
            {
                name: 'Poké',
                servers: [
                    'https://poke.tchncs.de',
                    'https://poke.ggtyler.dev',
                    'https://poke.privacydev.net'
                ],
                getUrl: (server, videoId) => `${server}/api/v1/videos/${videoId}`,
                parseResponse: (data) => {
                    const streams = [];
                    if (data.formatStreams) {
                        data.formatStreams.forEach(s => {
                            if (s.url) streams.push({ 
                                url: s.url, 
                                quality: s.qualityLabel || s.quality, 
                                type: 'Poké',
                                hasAudio: true
                            });
                        });
                    }
                    return streams;
                }
            },
            {
                name: 'Tubo',
                servers: [
                    'https://tubo.migalmoreno.com',
                    'https://tubo.reallyaweso.me'
                ],
                getUrl: (server, videoId) => `${server}/api/streams/${videoId}`,
                parseResponse: (data) => {
                    if (!data.videoStreams) return [];
                    return data.videoStreams.map(s => ({
                        url: s.url,
                        quality: s.quality,
                        type: 'Tubo',
                        hasAudio: true
                    }));
                }
            },
            {
                name: 'ViewTube',
                servers: ['https://api.viewtube.io'],
                getUrl: (server, videoId) => `${server}/videos/${videoId}`,
                parseResponse: (data) => {
                    if (!data.adaptiveFormats) return [];
                    return data.adaptiveFormats
                        .filter(f => f.mimeType && f.mimeType.includes('video') && f.url)
                        .map(f => ({
                            url: f.url,
                            quality: f.qualityLabel || 'auto',
                            type: 'ViewTube',
                            hasAudio: false
                        }));
                }
            },
            {
                name: 'FreeTube',
                servers: [
                    'https://api.freetube.app',
                    'https://freetube-api.vercel.app'
                ],
                getUrl: (server, videoId) => `${server}/api/v1/videos/${videoId}`,
                parseResponse: (data) => {
                    const streams = [];
                    
                    if (data.formatStreams && data.formatStreams.length > 0) {
                        data.formatStreams.forEach(s => {
                            if (s.url) {
                                streams.push({ 
                                    url: s.url, 
                                    quality: s.qualityLabel || s.quality, 
                                    type: 'FreeTube',
                                    hasAudio: true
                                });
                            }
                        });
                    }
                    
                    if (data.adaptiveFormats && data.adaptiveFormats.length > 0) {
                        data.adaptiveFormats.forEach(s => {
                            if (s.url && s.type && s.type.includes('video')) {
                                streams.push({ 
                                    url: s.url, 
                                    quality: s.qualityLabel || 'auto', 
                                    type: 'FreeTube',
                                    hasAudio: false
                                });
                            }
                        });
                    }
                    
                    return streams;
                }
            },
            {
                name: 'CloudTube',
                servers: [
                    'https://tube.cadence.moe',
                    'https://cloudtube.rknight.me'
                ],
                getUrl: (server, videoId) => `${server}/api/v1/videos/${videoId}`,
                parseResponse: (data) => {
                    const streams = [];
                    if (data.formatStreams) {
                        data.formatStreams.forEach(s => {
                            if (s.url) {
                                streams.push({ 
                                    url: s.url, 
                                    quality: s.qualityLabel || s.quality, 
                                    type: 'CloudTube',
                                    hasAudio: true
                                });
                            }
                        });
                    }
                    if (data.adaptiveFormats) {
                        data.adaptiveFormats.forEach(s => {
                            if (s.url && s.type && s.type.includes('video')) {
                                streams.push({ 
                                    url: s.url, 
                                    quality: s.qualityLabel || 'auto', 
                                    type: 'CloudTube',
                                    hasAudio: false
                                });
                            }
                        });
                    }
                    return streams;
                }
            },
            {
                name: 'LightTube',
                servers: [
                    'https://tube.kuylar.dev'
                ],
                getUrl: (server, videoId) => `${server}/api/player?v=${videoId}`,
                parseResponse: (data) => {
                    if (!data.formats) return [];
                    return data.formats
                        .filter(f => f.url)
                        .map(f => ({
                            url: f.url,
                            quality: f.quality || f.qualityLabel || 'auto',
                            type: 'LightTube',
                            hasAudio: true
                        }));
                }
            },
            {
                name: 'Clipious',
                servers: [
                    'https://api.clipious.app'
                ],
                getUrl: (server, videoId) => `${server}/videos/${videoId}`,
                parseResponse: (data) => {
                    const streams = [];
                    if (data.formatStreams) {
                        data.formatStreams.forEach(s => {
                            if (s.url) {
                                streams.push({ 
                                    url: s.url, 
                                    quality: s.qualityLabel || s.quality, 
                                    type: 'Clipious',
                                    hasAudio: true
                                });
                            }
                        });
                    }
                    return streams;
                }
            },
            {
                name: 'YTMous',
                servers: [
                    'https://ytmous.vercel.app'
                ],
                getUrl: (server, videoId) => `${server}/api/video/${videoId}`,
                parseResponse: (data) => {
                    if (!data.formats) return [];
                    return data.formats
                        .filter(f => f.mimeType && f.mimeType.includes('video') && f.url)
                        .map(f => ({
                            url: f.url,
                            quality: f.qualityLabel || f.quality || 'auto',
                            type: 'YTMous',
                            hasAudio: true
                        }));
                }
            },
            {
                name: 'YT-DLP',
                servers: [
                    'https://yt-dl-test.vercel.app',
                    'https://youtube-dl-api.vercel.app'
                ],
                getUrl: (server, videoId) => `${server}/api/info?url=https://www.youtube.com/watch?v=${videoId}`,
                parseResponse: (data) => {
                    if (!data.formats) return [];
                    return data.formats
                        .filter(f => f.url && f.vcodec && f.vcodec !== 'none')
                        .map(f => ({
                            url: f.url,
                            quality: f.height ? `${f.height}p` : (f.format_note || 'auto'),
                            type: 'YT-DLP',
                            hasAudio: f.acodec && f.acodec !== 'none',
                            format_id: f.format_id,
                            ext: f.ext
                        }));
                }
            },
            {
                name: 'GoogleVideo',
                servers: ['https://corsproxy.io/?'],
                getUrl: (server, videoId) => `${server}https://www.youtube.com/get_video_info?video_id=${videoId}`,
                parseResponse: (data) => {
                    try {
                        const params = new URLSearchParams(data);
                        const playerResponse = JSON.parse(params.get('player_response') || '{}');
                        
                        if (!playerResponse.streamingData) return [];
                        
                        const streams = [];
                        const streamingData = playerResponse.streamingData;
                        
                        if (streamingData.formats) {
                            streamingData.formats.forEach(f => {
                                if (f.url) {
                                    streams.push({
                                        url: f.url,
                                        quality: f.qualityLabel || f.quality || 'auto',
                                        type: 'GoogleVideo',
                                        hasAudio: true,
                                        itag: f.itag
                                    });
                                }
                            });
                        }
                        
                        if (streamingData.adaptiveFormats) {
                            streamingData.adaptiveFormats.forEach(f => {
                                if (f.url && f.mimeType && f.mimeType.includes('video')) {
                                    streams.push({
                                        url: f.url,
                                        quality: f.qualityLabel || 'auto',
                                        type: 'GoogleVideo',
                                        hasAudio: false,
                                        itag: f.itag
                                    });
                                }
                            });
                        }
                        
                        return streams;
                    } catch (err) {
                        console.error('GoogleVideo parse error:', err);
                        return [];
                    }
                }
            },
            {
                name: 'Cobalt',
                servers: [
                    'https://api.cobalt.tools',
                    'https://co.wuk.sh'
                ],
                getUrl: (server, videoId) => `${server}/api/json`,
                parseResponse: (data) => {
                    if (!data.url) return [];
                    return [{
                        url: data.url,
                        quality: data.quality || 'max',
                        type: 'Cobalt',
                        hasAudio: true
                    }];
                },
                customFetch: async (server, videoId) => {
                    const url = server;
                    const proxiedUrl = getProxiedUrl(url);
                    
                    const response = await fetch(proxiedUrl, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Accept': 'application/json'
                        },
                        body: JSON.stringify({
                            url: `https://www.youtube.com/watch?v=${videoId}`,
                            vQuality: 'max'
                        }),
                        signal: AbortSignal.timeout(8000)
                    });
                    return response;
                }
            },
            {
                name: 'Y2Mate',
                servers: [
                    'https://www.y2mate.com/mates/analyzeV2/ajax'
                ],
                getUrl: (server, videoId) => server,
                parseResponse: (data) => {
                    if (!data.links || !data.links.mp4) return [];
                  const streams = [];
                    Object.entries(data.links.mp4).forEach(([quality, info]) => {
                        if (info.url) {
                            streams.push({
                                url: info.url,
                                quality: quality,
                                type: 'Y2Mate',
                                hasAudio: true
                            });
                        }
                    });
                    return streams;
                },
                customFetch: async (server, videoId) => {
                    const formData = new FormData();
                    formData.append('k_query', `https://www.youtube.com/watch?v=${videoId}`);
                    formData.append('k_page', 'home');
                    formData.append('hl', 'en');
                    formData.append('q_auto', '0');
                    
                    const proxiedUrl = getProxiedUrl(server);
                    
                    const response = await fetch(proxiedUrl, {
                        method: 'POST',
                        body: formData,
                        signal: AbortSignal.timeout(8000)
                    });
                    return response;
                }
            },
            {
                name: 'SaveFrom',
                servers: [
                    'https://savefrom.net/download'
                ],
                getUrl: (server, videoId) => `${server}?url=https://www.youtube.com/watch?v=${videoId}`,
                parseResponse: (data) => {
                    if (!data.url || !Array.isArray(data.url)) return [];
                    return data.url
                        .filter(u => u.url && u.type === 'video')
                        .map(u => ({
                            url: u.url,
                            quality: u.quality || u.name || 'auto',
                            type: 'SaveFrom',
                            hasAudio: true
                        }));
                }
            },
            {
                name: 'SSYoutube',
                servers: [
                    'https://ssyoutube.com/api/convert'
                ],
                getUrl: (server, videoId) => server,
                parseResponse: (data) => {
                    if (!data.formats) return [];
                    return data.formats
                        .filter(f => f.url)
                        .map(f => ({
                            url: f.url,
                            quality: f.qualityLabel || f.quality || 'auto',
                            type: 'SSYoutube',
                            hasAudio: true
                        }));
                },
                customFetch: async (server, videoId) => {
                    const proxiedUrl = getProxiedUrl(server);
                    
                    const response = await fetch(proxiedUrl, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({
                            url: `https://www.youtube.com/watch?v=${videoId}`
                        }),
                        signal: AbortSignal.timeout(8000)
                    });
                    return response;
                }
            },
            {
                name: 'KeepVid',
                servers: [
                    'https://keepvid.pro/api/video'
                ],
                getUrl: (server, videoId) => `${server}?url=https://www.youtube.com/watch?v=${videoId}`,
                parseResponse: (data) => {
                    if (!data.formats) return [];
                    return data.formats
                        .filter(f => f.url && f.type === 'video')
                        .map(f => ({
                            url: f.url,
                            quality: f.quality || 'auto',
                            type: 'KeepVid',
                            hasAudio: true
                        }));
                }
            },
            {
                name: 'YouTubeToMP3',
                servers: [
                    'https://youtubetomp3music.com/api/convert'
                ],
                getUrl: (server, videoId) => server,
                parseResponse: (data) => {
                    if (!data.url) return [];
                    return [{
                        url: data.url,
                        quality: data.quality || 'default',
                        type: 'YouTubeToMP3',
                        hasAudio: true
                    }];
                },
                customFetch: async (server, videoId) => {
                    const proxiedUrl = getProxiedUrl(server);
                    
                    const response = await fetch(proxiedUrl, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({
                            url: `https://www.youtube.com/watch?v=${videoId}`,
                            format: 'mp4'
                        }),
                        signal: AbortSignal.timeout(8000)
                    });
                    return response;
                }
            },
            {
                name: 'YTBGoat',
                servers: [
                    'https://ytbgoat.com/api/video'
                ],
                getUrl: (server, videoId) => `${server}/${videoId}`,
                parseResponse: (data) => {
                    if (!data.streams) return [];
                    return data.streams
                        .filter(s => s.url)
                        .map(s => ({
                            url: s.url,
                            quality: s.quality || s.resolution || 'auto',
                            type: 'YTBGoat',
                            hasAudio: s.hasAudio !== false
                        }));
                }
            },
            {
                name: 'loader.to',
                servers: [
                    'https://loader.to/ajax/download.php'
                ],
                getUrl: (server, videoId) => server,
                parseResponse: (data) => {
                    if (!data.url) return [];
                    return [{
                        url: data.url,
                        quality: 'default',
                        type: 'loader.to',
                        hasAudio: true
                    }];
                },
                customFetch: async (server, videoId) => {
                    const formData = new FormData();
                    formData.append('url', `https://www.youtube.com/watch?v=${videoId}`);
                    
                    const proxiedUrl = getProxiedUrl(server);
                    
                    const response = await fetch(proxiedUrl, {
                        method: 'POST',
                        body: formData,
                        signal: AbortSignal.timeout(8000)
                    });
                    return response;
                }
            }
        ];
        
        function toggleTheme() {
            const body = document.body;
            const themeToggle = document.getElementById('themeToggle');
            
            body.classList.toggle('light-mode');
            
            if (body.classList.contains('light-mode')) {
                themeToggle.textContent = '☀️';
            } else {
                themeToggle.textContent = '🌙';
            }
        }

        async function searchVideos() {
            const query = document.getElementById('searchQuery').value.trim();
            const apiKey = document.getElementById('apiKey').value.trim();
            const loading = document.getElementById('loading');
            const error = document.getElementById('error');
            const info = document.getElementById('info');
            const results = document.getElementById('results');

            error.style.display = 'none';
            info.style.display = 'none';
            results.innerHTML = '';

            if (!query) {
                showError('検索キーワードまたはURLを入力してください');
                return;
            }

            const videoIdMatch = query.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&\s]+)/);
            if (videoIdMatch) {
                playVideo(videoIdMatch[1], 'YouTube動画');
                return;
            }

            loading.style.display = 'block';
            showInfo('検索中...');

            if (apiKey) {
                try {
                    const response = await fetch(
                        `https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=12&q=${encodeURIComponent(query)}&type=video&key=${apiKey}`,
                        { signal: AbortSignal.timeout(10000) }
                    );

                    if (response.ok) {
                        const data = await response.json();
                        if (data.items && data.items.length > 0) {
                            displayGoogleResults(data.items);
                            loading.style.display = 'none';
                            showInfo('Google YouTube Data API で検索しました');
                            return;
                        }
                    }
                } catch (err) {
                    console.log('Google API error:', err);
                }
            }

            showError('検索に失敗しました。YouTube URLを直接入力するか、Google API Keyを入力してみてください。');
            loading.style.display = 'none';
        }

        function displayGoogleResults(items) {
            const results = document.getElementById('results');
            
            items.forEach(item => {
                const videoId = item.id.videoId;
                const card = document.createElement('div');
                card.className = 'video-card';
                card.onclick = () => playVideo(videoId, item.snippet.title);

                const thumbnail = item.snippet.thumbnails.medium.url;

                card.innerHTML = `
                    <img src="${thumbnail}" alt="${item.snippet.title}">
                    <div class="video-info">
                        <div class="video-title">${item.snippet.title}</div>
                        <div class="video-channel">${item.snippet.channelTitle}</div>
                    </div>
                `;

                results.appendChild(card);
            });
        }

        function playVideo(videoId, title) {
            const playerSection = document.getElementById('playerSection');
            const currentVideo = document.getElementById('currentVideo');
            const btnStream = document.getElementById('btnStream');

            currentVideoId = videoId;
            availableStreams = [];
            debugMessages = [];
            currentQuality = null;
            
            addDebug(`🎬 動画ID: ${videoId}`);
            addDebug(`📝 タイトル: ${title}`);
            
            playerSection.style.display = 'block';
            currentVideo.textContent = title;

            const playerContainer = document.getElementById('playerContainer');
            playerContainer.innerHTML = `<iframe id="player" width="100%" height="100%" src="https://www.youtube.com/embed/${videoId}?autoplay=1" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`;
            
            const streamUrl = document.getElementById('streamUrl');
            streamUrl.textContent = `埋め込み再生中 | https://www.youtube.com/watch?v=${videoId}`;
            
            addDebug('✅ 埋め込みプレーヤー作成完了');

            btnStream.disabled = true;
            btnStream.textContent = '🎬 取得中...';
            
            addDebug('🔍 ストリーム情報の取得を開始...');
            
            fetchStreamUrls(videoId).then(streams => {
                if (streams.length > 0) {
                    availableStreams = streams;
                    btnStream.disabled = false;
                    btnStream.textContent = '🎬 ストリーム再生';
                    addDebug(`✅ ${streams.length}個のストリームを取得成功!`);
                    addDebug(`📊 API: ${streams[0].type}`);
                    addDebug(`🎚️ 画質: ${streams.map(s => s.quality).join(', ')}`);
                    showInfo(`ストリーム再生が利用可能です(${streams[0].type})`);
                    
                    // ストリーム取得後、自動的にストリーム再生モードに切り替え
                    addDebug('🚀 自動的にストリーム再生を開始します');
                    setPlayMode('stream');
                } else {
                    btnStream.disabled = true;
                    btnStream.textContent = '🎬 利用不可';
                    addDebug('❌ ストリーム取得失敗');
                    addDebug('💡 埋め込み再生をご利用ください');
                }
            }).catch(err => {
                addDebug(`❌ エラー: ${err.message}`);
                btnStream.disabled = true;
                btnStream.textContent = '🎬 エラー';
            });

            playerSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
        }

        async function fetchStreamUrls(videoId) {
            let attemptCount = 0;
            const maxAttempts = streamAPIs.reduce((sum, api) => sum + api.servers.length, 0);
            
            addDebug(`🌐 ${maxAttempts}個のエンドポイントを試行`);
            
            for (const api of streamAPIs) {
                addDebug(`\n📡 ${api.name} API (${api.servers.length}サーバー)`);
                
                for (const server of api.servers) {
                    attemptCount++;
                    try {
                        addDebug(`  [${attemptCount}/${maxAttempts}] ${server.replace('https://', '')}`);
                        
                        let response;
                        
                        if (api.customFetch) {
                            response = await api.customFetch(server, videoId);
                        } else {
                            const apiUrl = api.getUrl(server, videoId);
                            const proxiedUrl = getProxiedUrl(apiUrl);
                            
                            try {
                                response = await fetch(proxiedUrl, {
                                    signal: AbortSignal.timeout(8000)
                                });
                            } catch (proxyErr) {
                                addDebug(`    ⚠️ プロキシ1失敗、再試行...`);
                                rotateProxy();
                                const retryUrl = getProxiedUrl(apiUrl);
                                response = await fetch(retryUrl, {
                                    signal: AbortSignal.timeout(8000)
                                });
                            }
                        }
                        
                        addDebug(`    → HTTP ${response.status}`);
                        
                        if (!response.ok) {
                            continue;
                        }
                        
                        const contentType = response.headers.get('content-type');
                        let data;
                        
                        if (contentType && contentType.includes('application/json')) {
                            data = await response.json();
                        } else {
                            data = await response.text();
                        }
                        
                        addDebug(`    → データ取得成功`);
                        
                        const streams = api.parseResponse(data);
                        
                        if (streams.length > 0) {
                            addDebug(`    ✅ ${streams.length}個のストリーム取得!`);
                            streams.slice(0, 3).forEach((s, i) => {
                                addDebug(`      [${i+1}] ${s.quality} ${s.hasAudio ? '🔊' : '🔇'}`);
                            });
                            return streams;
                        } else {
                            addDebug(`    ⚠️ ストリーム0個`);
                        }
                    } catch (err) {
                        if (err.name === 'AbortError') {
                            addDebug(`    ⏱️ タイムアウト(8秒)`);
                        } else {
                            addDebug(`    ❌ ${err.message}`);
                        }
                        continue;
                    }
                }
            }
            
            addDebug('\n❌ すべてのAPIで失敗しました');
            return [];
        }

        function setPlayMode(mode) {
            if (!currentVideoId) {
                addDebug('❌ 動画IDがありません');
                return;
            }

            currentPlayMode = mode;
            const playerContainer = document.getElementById('playerContainer');
            const streamUrl = document.getElementById('streamUrl');
            const qualityControls = document.getElementById('qualityControls');

            streamUrl.textContent = '';
            qualityControls.style.display = 'none';

            addDebug(`\n🎮 再生モード切り替え: ${mode}`);

            if (mode === 'stream') {
                if (availableStreams.length === 0) {
                    showError('ストリーム情報が取得できていません');
                    addDebug('❌ ストリーム情報なし');
                    return;
                }
                
                addDebug(`📺 video要素を作成`);
                playerContainer.innerHTML = '<video id="player" controls autoplay style="width:100%;height:100%;"></video>';
                qualityControls.style.display = 'grid';
                
                // 画質オプションを動的に生成
                createQualityButtons();
                
                // 最高画質で自動再生
                playBestQuality();
                return;
            }

            addDebug(`📺 iframe埋め込みを作成: ${mode}`);
            
            let embedUrl = '';

            if (mode === 'embed') {
                embedUrl = `https://www.youtube.com/embed/${currentVideoId}?autoplay=1`;
                streamUrl.textContent = `埋め込み再生 | https://www.youtube.com/watch?v=${currentVideoId}`;
            } else if (mode === 'nocookie') {
                embedUrl = `https://www.youtube-nocookie.com/embed/${currentVideoId}?autoplay=1`;
                streamUrl.textContent = `No Cookie埋め込み | プライバシー重視`;
            } else if (mode === 'education') {
                const eduParams = [
                    'autoplay=1',
                    'mute=0',
                    'controls=1',
                    'start=0',
                    'playsinline=1',
                    'showinfo=0',
                    'rel=0',
                    'iv_load_policy=3',
                    'modestbranding=1',
                    'fs=1',
                    'cc_load_policy=0',
                    'enablejsapi=1'
                ].join('&');
                embedUrl = `https://www.youtube.com/embed/${currentVideoId}?${eduParams}`;
                streamUrl.textContent = `Education埋め込み | 教育プラットフォーム向け設定`;
            }

            playerContainer.innerHTML = `<iframe id="player" width="100%" height="100%" src="${embedUrl}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`;
            
            addDebug(`✅ 埋め込み完了: ${embedUrl}`);
        }

        function createQualityButtons() {
            const qualityControls = document.getElementById('qualityControls');
            qualityControls.innerHTML = '';
            
            // 音声付きストリームを優先
            const audioStreams = availableStreams.filter(s => s.hasAudio);
            const sortableStreams = audioStreams.length > 0 ? audioStreams : availableStreams;
            
            // 画質ごとにグループ化
            const qualityMap = new Map();
            sortableStreams.forEach(stream => {
                const quality = String(stream.quality);
                if (!qualityMap.has(quality)) {
                    qualityMap.set(quality, stream);
                }
            });
            
            // 画質を数値でソート
            const sortedQualities = Array.from(qualityMap.entries()).sort((a, b) => {
                const getQualityValue = (q) => {
                    const match = q.match(/(\d+)/);
                    return match ? parseInt(match[1]) : 0;
                };
                return getQualityValue(b[0]) - getQualityValue(a[0]);
            });
            
            addDebug(`🎚️ ${sortedQualities.length}個の画質オプションを生成`);
            
            // 各画質のボタンを作成
            sortedQualities.forEach(([quality, stream], index) => {
                const button = document.createElement('button');
                button.textContent = `${quality} ${stream.hasAudio ? '🔊' : '🔇'}`;
                button.onclick = () => changeQualityByIndex(index);
                button.dataset.index = index;
                qualityControls.appendChild(button);
            });
        }

        function playBestQuality() {
            changeQualityByIndex(0);
        }

        function changeQualityByIndex(index) {
            const audioStreams = availableStreams.filter(s => s.hasAudio);
            const sortableStreams = audioStreams.length > 0 ? audioStreams : availableStreams;
            
            // 画質ごとにグループ化
            const qualityMap = new Map();
            sortableStreams.forEach(stream => {
                const quality = String(stream.quality);
                if (!qualityMap.has(quality)) {
                    qualityMap.set(quality, stream);
                }
            });
            
            // 画質を数値でソート
            const sortedQualities = Array.from(qualityMap.entries()).sort((a, b) => {
                const getQualityValue = (q) => {
                    const match = q.match(/(\d+)/);
                    return match ? parseInt(match[1]) : 0;
                };
                return getQualityValue(b[0]) - getQualityValue(a[0]);
            });
            
            if (index >= sortedQualities.length) {
                addDebug('❌ 無効なインデックス');
                return;
            }
            
            const [quality, selectedStream] = sortedQualities[index];
            currentQuality = quality;
            
            // ボタンのアクティブ状態を更新
            const qualityControls = document.getElementById('qualityControls');
            const buttons = qualityControls.querySelectorAll('button');
            buttons.forEach((btn, i) => {
                if (i === index) {
                    btn.classList.add('active');
                } else {
                    btn.classList.remove('active');
                }
            });
            
            playStream(selectedStream);
        }

        function changeQuality(qualityLevel) {
            if (availableStreams.length === 0) return;
            
            addDebug(`\n🎚️ 画質変更: ${qualityLevel}`);
            
            const audioStreams = availableStreams.filter(s => s.hasAudio);
            const sortableStreams = audioStreams.length > 0 ? audioStreams : availableStreams;
            
            const sortedStreams = [...sortableStreams].sort((a, b) => {
                const getQualityValue = (q) => {
                    const match = String(q).match(/(\d+)/);
                    return match ? parseInt(match[1]) : 0;
                };
                return getQualityValue(b.quality) - getQualityValue(a.quality);
            });

            let selectedStream;
            
            switch(qualityLevel) {
                case 'best':
                    selectedStream = sortedStreams[0];
                    break;
                case 'high':
                    selectedStream = sortedStreams.find(s => {
                        const q = String(s.quality);
                        return q.includes('720') || q.includes('480');
                    }) || sortedStreams[Math.floor(sortedStreams.length / 2)];
                    break;
                case 'medium':
                    selectedStream = sortedStreams.find(s => {
                        const q = String(s.quality);
                        return q.includes('360') || q.includes('240');
                    }) || sortedStreams[sortedStreams.length - 1];
                    break;
            }

            if (selectedStream) {
                playStream(selectedStream);
            }
        }

        function playStream(stream) {
            const player = document.getElementById('player');
            const streamUrl = document.getElementById('streamUrl');
            
            if (!stream || !stream.url) {
                addDebug('❌ ストリームの選択に失敗');
                showError('ストリームの読み込みに失敗しました');
                return;
            }
            
            addDebug(`✅ 選択: ${stream.quality} (${stream.hasAudio ? '音声あり' : '音声なし'})`);
            addDebug(`🔗 URL: ${stream.url.substring(0, 80)}...`);
            
            player.src = stream.url;
            player.play().then(() => {
                addDebug('▶️ 再生開始');
            }).catch(e => {
                addDebug(`❌ 再生エラー: ${e.message}`);
                showError('ストリームの再生に失敗しました');
            });
            
            streamUrl.textContent = `画質: ${stream.quality} | API: ${stream.type} ${stream.hasAudio ? '🔊' : '🔇'}`;
        }

        async function downloadVideo(type) {
            if (!currentVideoId) {
                showError('動画が選択されていません');
                return;
            }

            addDebug(`\n📥 ダウンロード開始: ${type}`);
            
            const btnDownloadVideo = document.getElementById('btnDownloadVideo');
            const btnDownloadAudio = document.getElementById('btnDownloadAudio');
            
            btnDownloadVideo.disabled = true;
            btnDownloadAudio.disabled = true;
            btnDownloadVideo.textContent = '⏳ 処理中...';
            btnDownloadAudio.textContent = '⏳ 処理中...';

            try {
                let downloadUrl = null;
                
                if (availableStreams.length > 0) {
                    addDebug('🔍 取得済みストリームURLを使用');
                    const stream = availableStreams.find(s => s.hasAudio) || availableStreams[0];
                    if (stream) {
                        downloadUrl = stream.url;
                        addDebug(`✅ ストリームURL使用: ${stream.quality}`);
                    }
                }
                
                if (!downloadUrl) {
                    addDebug('🔍 新規取得を試行');
                    const streams = await fetchStreamUrls(currentVideoId);
                    if (streams.length > 0) {
                        const stream = streams.find(s => s.hasAudio) || streams[0];
                        downloadUrl = stream.url;
                        addDebug(`✅ 新規URL取得: ${stream.quality}`);
                    }
                }

                if (downloadUrl) {
                    addDebug('📥 ダウンロード開始...');
                    
                    const a = document.createElement('a');
                    a.href = downloadUrl;
                    a.download = `${currentVideoId}.${type === 'audio' ? 'mp3' : 'mp4'}`;
                    a.target = '_blank';
                    a.rel = 'noopener noreferrer';
                    
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                    
                    showInfo(`${type === 'video' ? '動画' : '音声'}のダウンロードを開始しました`);
                    addDebug('✅ ダウンロードリンククリック完了');
                } else {
                    throw new Error('ダウンロードURLの取得に失敗しました');
                }
            } catch (err) {
                addDebug(`❌ ダウンロード失敗: ${err.message}`);
                showError('ダウンロードに失敗しました。ストリーム再生をお試しください。');
            } finally {
                btnDownloadVideo.disabled = false;
                btnDownloadAudio.disabled = false;
                btnDownloadVideo.textContent = '📥 動画DL';
                btnDownloadAudio.textContent = '🎵 音声DL';
            }
        }

        function showError(message) {
            const error = document.getElementById('error');
            error.textContent = message;
            error.style.display = 'block';
            setTimeout(() => {
                error.style.display = 'none';
            }, 5000);
        }

        function showInfo(message) {
            const info = document.getElementById('info');
            info.textContent = message;
            info.style.display = 'block';
            setTimeout(() => {
                info.style.display = 'none';
            }, 3000);
        }
    </script>
</body>
</html>