import { NextResponse } from 'next/server';

import { getConfig } from '@/lib/config';

export const runtime = 'nodejs';

/**
 * M3U8 代理接口
 * 用于外部播放器访问,会执行去广告逻辑并处理相对链接
 * GET /api/proxy-m3u8?url=<原始m3u8地址>&source=<播放源>&token=<鉴权token>
 */
export async function GET(request: Request) {
  try {
    const { searchParams } = new URL(request.url);
    const m3u8Url = searchParams.get('url');
    const source = searchParams.get('source') || '';
    const token = searchParams.get('token');

    // Token 鉴权：如果环境变量设置了 token，则必须验证
    const envToken = process.env.NEXT_PUBLIC_PROXY_M3U8_TOKEN;
    if (envToken && envToken.trim() !== '') {
      if (!token || token !== envToken) {
        return NextResponse.json(
          { error: '无效的访问令牌' },
          { status: 401 }
        );
      }
    }

    if (!m3u8Url) {
      return NextResponse.json(
        { error: '缺少必要参数: url' },
        { status: 400 }
      );
    }

    // 获取当前请求的 origin
    const requestUrl = new URL(request.url);
    const origin = `${requestUrl.protocol}//${requestUrl.host}`;

    // 获取原始 m3u8 内容
    const response = await fetch(m3u8Url, {
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
      },
    });

    if (!response.ok) {
      return NextResponse.json(
        { error: '获取 m3u8 文件失败' },
        { status: response.status }
      );
    }

    let m3u8Content = await response.text();

    // 执行去广告逻辑
    const config = await getConfig();
    const customAdFilterCode = config.SiteConfig?.CustomAdFilterCode || '';

    if (customAdFilterCode && customAdFilterCode.trim()) {
      try {
        // 移除 TypeScript 类型注解,转换为纯 JavaScript
        const jsCode = customAdFilterCode
          .replace(/(\w+)\s*:\s*(string|number|boolean|any|void|never|unknown|object)\s*([,)])/g, '$1$3')
          .replace(/\)\s*:\s*(string|number|boolean|any|void|never|unknown|object)\s*\{/g, ') {')
          .replace(/(const|let|var)\s+(\w+)\s*:\s*(string|number|boolean|any|void|never|unknown|object)\s*=/g, '$1 $2 =');

        // 创建并执行自定义函数
        const customFunction = new Function('type', 'm3u8Content',
          jsCode + '\nreturn filterAdsFromM3U8(type, m3u8Content);'
        );
        m3u8Content = customFunction(source, m3u8Content);
      } catch (err) {
        console.error('执行自定义去广告代码失败,使用默认规则:', err);
        // 继续使用默认规则
        m3u8Content = filterAdsFromM3U8Default(source, m3u8Content);
      }
    } else {
      // 使用默认去广告规则
      m3u8Content = filterAdsFromM3U8Default(source, m3u8Content);
    }

    // 处理 m3u8 中的相对链接
    m3u8Content = resolveM3u8Links(m3u8Content, m3u8Url, source, origin, token || '');

    // 返回处理后的 m3u8 内容
    return new NextResponse(m3u8Content, {
      headers: {
        'Content-Type': 'application/vnd.apple.mpegurl',
        'Access-Control-Allow-Origin': '*',
        'Cache-Control': 'no-cache',
      },
    });
  } catch (error) {
    console.error('代理 m3u8 失败:', error);
    return NextResponse.json(
      { error: '代理失败', details: (error as Error).message },
      { status: 500 }
    );
  }
}

/**
 * 默认去广告规则
 */
function filterAdsFromM3U8Default(type: string, m3u8Content: string): string {
  if (!m3u8Content) return '';

  // 按行分割M3U8内容
  const lines = m3u8Content.split('\n');
  const filteredLines = [];

  let nextdelete = false;
  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];

    if (nextdelete) {
      nextdelete = false;
      continue;
    }

    // 只过滤#EXT-X-DISCONTINUITY标识
    if (!line.includes('#EXT-X-DISCONTINUITY')) {
      if (
        type === 'ruyi' &&
        (line.includes('EXTINF:5.640000') ||
          line.includes('EXTINF:2.960000') ||
          line.includes('EXTINF:3.480000') ||
          line.includes('EXTINF:4.000000') ||
          line.includes('EXTINF:0.960000') ||
          line.includes('EXTINF:10.000000') ||
          line.includes('EXTINF:1.266667'))
      ) {
        nextdelete = true;
        continue;
      }

      filteredLines.push(line);
    }
  }

  return filteredLines.join('\n');
}

/**
 * 将 m3u8 中的相对链接转换为绝对链接，并将子 m3u8 链接转为代理链接
 */
function resolveM3u8Links(m3u8Content: string, baseUrl: string, source: string, proxyOrigin: string, token: string): string {
  const lines = m3u8Content.split('\n');
  const resolvedLines = [];

  // 解析基础URL
  const base = new URL(baseUrl);
  const baseDir = base.href.substring(0, base.href.lastIndexOf('/') + 1);

  let isNextLineUrl = false;

  for (let i = 0; i < lines.length; i++) {
    let line = lines[i];

    // 处理 EXT-X-KEY 标签中的 URI
    if (line.startsWith('#EXT-X-KEY:')) {
      // 提取 URI 部分
      const uriMatch = line.match(/URI="([^"]+)"/);
      if (uriMatch && uriMatch[1]) {
        let keyUri = uriMatch[1];

        // 转换为绝对路径
        if (!keyUri.startsWith('http://') && !keyUri.startsWith('https://')) {
          if (keyUri.startsWith('/')) {
            keyUri = `${base.protocol}//${base.host}${keyUri}`;
          } else {
            keyUri = new URL(keyUri, baseDir).href;
          }

          // 替换原来的 URI
          line = line.replace(/URI="[^"]+"/, `URI="${keyUri}"`);
        }
      }
      resolvedLines.push(line);
      continue;
    }

    // 注释行直接保留
    if (line.startsWith('#')) {
      resolvedLines.push(line);
      // 检查是否是 EXT-X-STREAM-INF，下一行将是子 m3u8
      if (line.startsWith('#EXT-X-STREAM-INF:')) {
        isNextLineUrl = true;
      }
      continue;
    }

    // 空行直接保留
    if (line.trim() === '') {
      resolvedLines.push(line);
      continue;
    }

    // 处理 URL 行
    let url = line.trim();

    // 1. 先转换为绝对 URL
    if (!url.startsWith('http://') && !url.startsWith('https://')) {
      if (url.startsWith('/')) {
        // 以 / 开头，相对于域名根目录
        url = `${base.protocol}//${base.host}${url}`;
      } else {
        // 相对于当前目录
        url = new URL(url, baseDir).href;
      }
    }

    // 2. 检查是否是子 m3u8，如果是，转换为代理链接
    const isM3u8 = url.includes('.m3u8') || isNextLineUrl;
    if (isM3u8) {
      const tokenParam = token ? `&token=${encodeURIComponent(token)}` : '';
      url = `${proxyOrigin}/api/proxy-m3u8?url=${encodeURIComponent(url)}${source ? `&source=${encodeURIComponent(source)}` : ''}${tokenParam}`;
    }

    resolvedLines.push(url);
    isNextLineUrl = false;
  }

  return resolvedLines.join('\n');
}
