import axios from 'axios';
import * as readline from 'readline';
import * as fs from 'fs';
import * as path from 'path';

// 视频生成模型配置 - 醒目位置
const MODEL = 'wanx2.1-t2v-turbo';

// 配置信息
interface Config {
  apiKey: string;
  videoGenerationApi: string;
  taskStatusApi: string;
}

// 从环境变量和配置文件读取配置
let config: Config = {
  apiKey: process.env.DASHSCOPE_API_KEY || '', // 从环境变量读取API密钥
  videoGenerationApi: 'https://dashscope.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis',
  taskStatusApi: 'https://dashscope.aliyuncs.com/api/v1/tasks/'
};

// 检查是否存在配置文件并读取
const configPath = path.join(__dirname, 'config.json');
if (fs.existsSync(configPath)) {
  try {
    const configData = JSON.parse(fs.readFileSync(configPath, 'utf8'));
    config = { ...config, ...configData };
    console.log('已加载配置文件');
  } catch (error) {
    console.warn('配置文件读取失败，使用默认配置', error);
  }
}

// API常量
const API_KEY = config.apiKey;
const VIDEO_GENERATION_API = config.videoGenerationApi;
const TASK_STATUS_API = config.taskStatusApi;

// API响应类型定义
interface TaskResponse {
  task_id?: string;
  output?: {
    task_id?: string;
    task_status?: string;
    video_url?: string;
    result?: {
      video_url?: string;
    };
    actual_prompt?: string;
  };
  task_status?: string;
  status?: string;
  message?: string;
}

// 创建命令行接口
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// 视频参数接口
interface VideoParams {
  prompt: string;
  size?: string;
  duration?: number;
}

// 创建视频生成任务
async function generateVideo(params: VideoParams): Promise<string> {
  console.log('正在发送视频生成请求...');
  
  try {
    const { prompt, size = '1280*720', duration = 5 } = params;
    
    // 验证提示词不能为空
    if (!prompt || prompt.trim() === '') {
      throw new Error('提示词不能为空');
    }
    
    // 创建视频生成任务
    const response = await axios.post(
      VIDEO_GENERATION_API,
      {
        model: MODEL,
        input: {
          prompt,
        },
        parameters: {
          size,
          duration,
          prompt_extend: true, // 启用提示词扩展
        },
      },
      {
        headers: {
          'Authorization': `Bearer ${API_KEY}`,
          'Content-Type': 'application/json',
          'X-DashScope-Async': 'enable',
        },
      }
    );
    
    const responseData = response.data as TaskResponse;
    
    // 检查是否有扩展提示词
    if (responseData.output?.actual_prompt) {
      console.log('系统扩展生成的提示词：');
      console.log(responseData.output.actual_prompt);
    }
    
    console.log('视频生成请求已发送，获取任务ID：');
    console.log(JSON.stringify(responseData, null, 2));
    
    // 检查响应格式并提取任务ID
    if (responseData.task_id) {
      return responseData.task_id;
    } else if (responseData.output?.task_id) {
      return responseData.output.task_id;
    } else {
      throw new Error('无法从响应中获取任务ID');
    }
  } catch (error: any) {
    console.error('视频生成请求失败：');
    if (axios.isAxiosError(error) && error.response) {
      console.error('API错误响应:', error.response.data);
      throw new Error(`视频生成失败: ${error.response.data.message || '未知错误'}`);
    }
    
    throw new Error(`视频生成失败: ${error.message || '未知错误'}`);
  }
}

// 查询视频生成任务状态
async function checkVideoStatus(taskId: string): Promise<any> {
  // 不输出查询日志，保持界面简洁
  
  try {
    // 查询任务状态
    const response = await axios.get(
      `${TASK_STATUS_API}${taskId}`,
      {
        headers: {
          'Authorization': `Bearer ${API_KEY}`,
          'Content-Type': 'application/json',
        },
      }
    );
    
    return response.data;
  } catch (error: any) {
    // 简化错误输出
    throw new Error(`查询失败: ${error.message || '未知错误'}`);
  }
}

// 轮询任务状态直到完成
async function pollTaskUntilComplete(taskId: string, intervalMs: number = 5000, maxAttempts: number = 30): Promise<TaskResponse> {
  console.log(`开始轮询任务状态...`);
  
  let attempts = 0;
  let errorCount = 0; // 连续错误计数
  const startTime = Date.now();
  const maxWaitTimeMs = 6 * 60 * 1000; // 最多等待6分钟
  
  // 轮询任务状态
  while (attempts < maxAttempts) {
    attempts++;
    
    // 检查总体超时
    if (Date.now() - startTime > maxWaitTimeMs) {
      throw new Error(`任务等待超时(${maxWaitTimeMs/60000}分钟)，请稍后手动查询结果`);
    }
    
    try {
      const statusResult = await checkVideoStatus(taskId) as TaskResponse;
      
      // 重置错误计数
      errorCount = 0;
      
      // 根据API响应结构获取状态
      const status = statusResult.task_status || 
                    (statusResult.output && statusResult.output.task_status) ||
                    statusResult.status;
      
      // 计算已等待时间（秒）
      const waitedSeconds = Math.floor((Date.now() - startTime) / 1000);
      
      // 简化的状态输出
      console.log(`等待中，已等待${waitedSeconds}秒...状态: ${status}`);
      
      // 如果任务完成或失败，返回结果
      if (status === 'SUCCEEDED') {
        console.log('任务已成功完成！');
        return statusResult;
      } else if (status === 'FAILED') {
        console.log('任务失败');
        throw new Error(`任务失败: ${statusResult.message || '未知错误'}`);
      } else if (!status) {
        console.log('无法获取任务状态');
      }
      
      // 等待指定时间后再次查询
      await new Promise(resolve => setTimeout(resolve, intervalMs));
    } catch (error: any) {
      errorCount++;
      const waitedSeconds = Math.floor((Date.now() - startTime) / 1000);
      console.log(`等待中，已等待${waitedSeconds}秒...状态: ERROR (错误 ${errorCount}/3)`);
      
      // 连续多次查询失败，抛出异常
      if (errorCount >= 3) {
        throw new Error(`连续查询失败${errorCount}次，请检查网络或任务ID`);
      }
      
      await new Promise(resolve => setTimeout(resolve, intervalMs));
    }
  }
  
  throw new Error(`达到最大轮询次数(${maxAttempts})，任务尚未完成`);
}

// 用户交互函数
function promptUser(question: string): Promise<string> {
  return new Promise((resolve) => {
    rl.question(question, (answer) => {
      resolve(answer);
    });
  });
}

// 主函数
async function main() {
  try {
    console.log('=== 阿里云视频生成工具 ===');
    console.log(`当前使用的API密钥: ${API_KEY.substring(0, 5)}***${API_KEY.substring(API_KEY.length - 4)}`);
    
    // 获取用户输入并验证
    let prompt = '';
    while (!prompt || prompt.trim() === '') {
      prompt = await promptUser('请输入视频生成提示词: ');
      if (!prompt || prompt.trim() === '') {
        console.log('提示词不能为空，请重新输入');
      }
    }
    
    // 验证视频尺寸
    let size = await promptUser('请输入视频尺寸 (默认 1280*720): ') || '1280*720';
    // 检查尺寸格式
    if (!/^\d+\*\d+$/.test(size)) {
      console.log(`尺寸格式不正确，将使用默认大小 1280*720`);
      size = '1280*720';
    }
    
    // 验证视频时长
    const durationStr = await promptUser('请输入视频时长(秒) (默认 5秒): ') || '5';
    let duration = parseInt(durationStr);
    
    // 检查时长是否有效
    if (isNaN(duration) || duration <= 0 || duration > 60) {
      console.log(`输入的时长无效，使用默认时长 5秒`);
      duration = 5;
    }
    
    console.log(`\n生成视频参数:\n- 提示词: ${prompt}\n- 尺寸: ${size}\n- 时长: ${duration}秒`);
    
    // 创建视频生成任务
    const taskId = await generateVideo({ prompt, size, duration });
    
    if (!taskId) {
      throw new Error('未能获取有效的任务ID，请检查API响应');
    }
    
    console.log(`任务已创建，ID: ${taskId}`);
    
    // 默认执行轮询任务状态
    try {
      // 设置轮询间隔为5秒，最多30次尝试
      const result = await pollTaskUntilComplete(taskId, 5000, 30);
      
      // 显示生成的视频URL
      if (result.output?.video_url) {
        console.log(`\n视频生成成功！\n视频URL: ${result.output.video_url}`);
      } else if (result.output?.result?.video_url) {
        console.log(`\n视频生成成功！\n视频URL: ${result.output.result.video_url}`);
      } else {
        console.log('\n视频生成成功，但未获取到视频URL');
        console.log('完整响应数据:');
        console.log(JSON.stringify(result, null, 2));
      }
      
      // 显示扩展提示词(如果有)
      if (result.output?.actual_prompt) {
        console.log('\n系统扩展生成的完整提示词:');
        console.log(result.output.actual_prompt);
      }
    } catch (error: any) {
      console.error(`\n轮询任务状态失败: ${error.message}`);
      console.error('请记下任务ID，稍后使用API手动查询结果');
      console.log(`任务ID: ${taskId}`);
    }
  } catch (error: any) {
    console.error(`\n错误: ${error.message}`);
    
    if (error.response?.data) {
      console.error('API错误详情:');
      console.error(JSON.stringify(error.response.data, null, 2));
    }
  } finally {
    // 关闭readline接口
    rl.close();
    console.log('\n程序执行完毕');
  }
}

// 运行主函数
main();
