import json
import sys
import os
import io
import requests
import time
import random
import re
import uuid
import urllib.request
import urllib3
import traceback
from pathlib import Path
from urllib.parse import urlparse
from PIL import Image
import mimetypes
from typing import Dict, List, Any, Optional

import jingrow
from jingrow.ai.api.translate import get_translated_prompts
from jingrow.ai.utils.utils import update_status_progress, update_progress, send_notification, is_valid_image_url, get_new_image_url, upload_image, get_jingrow_api_headers, get_jingrow_api_url

# 从Ai Settings获取Midjourney配置
try:
    api_url = jingrow.db.get_single_value("Ai Settings", "midjourney_api_url")
    application_id = jingrow.db.get_single_value("Ai Settings", "midjourney_application_id")
    data_id = jingrow.db.get_single_value("Ai Settings", "midjourney_data_id")
    data_version = jingrow.db.get_single_value("Ai Settings", "midjourney_data_version")
    session_id = jingrow.db.get_single_value("Ai Settings", "midjourney_session_id")
    midjourney_suffix = jingrow.db.get_single_value("Ai Settings", "midjourney_suffix")
    add_title_to_image_name = jingrow.db.get_single_value("Ai Settings", "add_title_to_image_name") or 0

    # 代理设置 - 如果需要可以在Ai Settings中配置
    http_proxy = jingrow.db.get_single_value("Ai Settings", "http_proxy")
    https_proxy = jingrow.db.get_single_value("Ai Settings", "https_proxy")

    # 获取Midjourney选项配置
    midjourney_options_str = jingrow.db.get_single_value("Ai Settings", "midjourney_options")
    if midjourney_options_str:
        try:
            midjourney_options = json.loads(midjourney_options_str)
        except:
            midjourney_options = {"ar": "1:1", "v": "6.1"}
    else:
        midjourney_options = {"ar": "1:1", "v": "6.1"}
    

except Exception as e:
    jingrow.log_error("获取Midjourney配置失败", f"错误: {str(e)}")
    traceback.print_exc()

# 禁用不安全请求警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class Midjourney:
    def __init__(self, channel_id, oauth_token):
        self.API_URL = api_url
        self.APPLICATION_ID = application_id
        self.DATA_ID = data_id
        self.DATA_VERSION = data_version
        self.SESSION_ID = session_id
        
        self.channel_id = channel_id
        self.oauth_token = oauth_token

        # 设置代理 - 仅当代理配置存在且不为空时才使用
        self.proxies = {}
        if http_proxy and http_proxy.strip():
            self.proxies['http'] = http_proxy
        if https_proxy and https_proxy.strip():
            self.proxies['https'] = https_proxy

        self.client = requests.Session()
        self.client.headers.update({
            'Authorization': oauth_token
        })
        # 为会话设置代理 - 仅当代理不为空时
        if self.proxies:
            self.client.proxies.update(self.proxies)

        try:
            response = self.client.get(f'{self.API_URL}/channels/{self.channel_id}')
            data = response.json()
            
            self.guild_id = data['guild_id']
            response = self.client.get(f'{self.API_URL}/users/@me')
            data = response.json()
            
            self.user_id = data['id']
        except Exception as e:
            jingrow.log_error("初始化Midjourney客户端失败", f"错误: {str(e)}")
            traceback.print_exc()
            raise Exception(f"初始化Midjourney客户端失败: {str(e)}")

    @staticmethod
    def first_where(array, key, value=None):
        for item in array:
            if callable(key) and key(item):
                return item
            if isinstance(key, str) and item[key].startswith(value):
                return item
        return None

    # 使用给定的提示词生成图像请求
    def imagine(self, prompt, seed=None, pg_name=None, pagetype=None):
        params = {
            'type': 2,
            'application_id': self.APPLICATION_ID,
            'guild_id': self.guild_id,
            'channel_id': self.channel_id,
            'session_id': self.SESSION_ID,
            'data': {
                'version': self.DATA_VERSION,
                'id': self.DATA_ID,
                'name': 'imagine',
                'type': 1,
                'options': [{
                    'type': 3,
                    'name': 'prompt',
                    'value': prompt
                }],
                'application_command': {
                    'id': self.DATA_ID,
                    'application_id': self.APPLICATION_ID,
                    'version': self.DATA_VERSION,
                    'default_member_permissions': None,
                    'type': 1,
                    'nsfw': False,
                    'name': 'imagine',
                    'description': 'Create images with Midjourney',
                    'dm_permission': True,
                    'options': [{
                        'type': 3,
                        'name': 'prompt',
                        'description': 'The prompt to imagine',
                        'required': True
                    }]
                },
                'attachments': []
            }
        }

        try:
            r = self.client.post(f'{self.API_URL}/interactions', json=params)
            time.sleep(20)  # 初始等待时间

            imagine_message = None

            count = 0
            while imagine_message is None:
                imagine_message = self.get_imagine(prompt, count, seed, pg_name, pagetype)
                if imagine_message is None:
                    time.sleep(3)  # 每次循环等待时间
                    count += 1
                    if count > 60:
                        break

            return imagine_message
        except Exception as e:
            jingrow.log_error("发送Imagine请求失败", f"错误: {str(e)}")
            traceback.print_exc()
            raise Exception(f"发送Imagine请求失败: {str(e)}")

    # 获取生成图像的消息
    def get_imagine(self, prompt, count=0, seed=None, pg_name=None, pagetype=None):
        try:
            # 获取最近的5条消息
            response = self.client.get(f'{self.API_URL}/channels/{self.channel_id}/messages?limit=5')
            data = response.json()
            
            def criteria(item):
                # 检查进度信息并更新
                if seed is not None and f"--seed {seed}" in item['content'] and pg_name and pagetype:
                    # 匹配百分比，支持多种格式：(93%) 或 93%
                    progress_match = re.search(r'(?:\(|（)?(\d+)%(?:\)|）)?', item['content'])
                    if progress_match:
                        progress_value = int(progress_match.group(1))
                        # 更新进度
                        update_progress(pg_name, progress_value, pagetype)
                        # 如果是进行中的消息，返回False继续查找完成的消息
                        if "%" in item['content']:
                            return False
                
                # 排除进行中消息
                if "%" in item['content']:
                    return False
                    
                # seed 匹配
                if seed is not None:
                    seed_pattern = f"--seed {seed}"
                    if seed_pattern not in item['content']:
                        return False
                return True

            raw_message = self.first_where(data, criteria)

            if raw_message is None:
                return None
                
            r_final = {
                'id': raw_message['id'],
                'prompt': prompt,
                'raw_message': raw_message
            }
            
            return r_final
        except Exception as e:
            jingrow.log_error("获取通道消息失败", f"错误: {str(e)}")
            return None

    # 生成图像并返回生成的消息ID
    def generate(self, prompt, options={}, sources={}, pg_name=None, pagetype=None):
        try:
            prompt = prompt.strip()

            # 只在没有设置时才使用默认值
            if "ar" not in options or options['ar'] == "":
                options['ar'] = '3:2'

            if "seed" not in options or options['seed'] == "":
                options['seed'] = random.randint(0, 4294967295)

            # Force seed as last parameter in the dict
            seed = options.pop('seed')
            options['seed'] = seed

            parameter = ""
            no_value_key = ['relax', 'fast', 'turbo', 'raw', 'tile']
            for key, value in options.items():
                if key in no_value_key:
                    parameter += f" --{key}"
                else:
                    parameter += f" --{key} {value}"

            # Image sources
            if 'images' in sources:
                prompt = " ".join(sources['images']) + " " + prompt

            # Add omni reference
            if 'omni' in sources and len(sources['omni']) > 0:
                prompt = prompt + " --oref " + " ".join(sources['omni'])

            # Add caracters
            if 'caracters' in sources and len(sources['caracters']) > 0:
                prompt = prompt + " --cref " + " ".join(sources['caracters'])

            # Add styles
            if 'styles' in sources and len(sources['styles']) > 0:
                prompt = prompt + " --sref " + " ".join(sources['styles'])

            # On ajoute une seed pour éviter les doublons
            prompt = prompt + parameter
            
            imagine = self.imagine(prompt, seed, pg_name, pagetype)

            return {
                'imagine_message_id': imagine['id'],
                'raw_message': imagine['raw_message'],
                'seed': seed
            }
        except Exception as e:
            jingrow.log_error("生成图像失败", f"错误: {str(e)}")
            traceback.print_exc()
            raise Exception(f"生成图像失败: {str(e)}")

    # 从提示词中提取参数和来源
    def get_parameter_from_prompt(self, prompt):
        sources = {}
        # Get all sources from prompt
        # Get --sref http://xxxx, http://xxxx, http://xxxx
        sources['styles'] = []
        styles_match = re.search(r'--sref\s+((?:https?://\S+(?:,\s*)?)+)', prompt)
        if styles_match:
            sources['styles'] = re.findall(r'https?://\S+', styles_match.group(0))
            prompt = prompt[:styles_match.start()] + prompt[styles_match.end():]

        # Get --cref http://xxxx, http://xxxx, http://xxxx
        sources['caracters'] = []
        caracters_match = re.search(r'--cref\s+((?:https?://\S+(?:,\s*)?)+)', prompt)
        if caracters_match:
            sources['caracters'] = re.findall(r'https?://\S+', caracters_match.group(0))
            prompt = prompt[:caracters_match.start()] + prompt[caracters_match.end():]

        # Get all parameters from prompt
        parameters = re.findall(r'--(\w+\s[\w.:]+)', prompt)
        # Clean prompt
        for parameter in parameters:
            prompt = prompt.replace(f'--{parameter}', '')

        # Delete multiple spaces
        prompt = re.sub(' {2,}', ' ', prompt)
        prompt = prompt.strip()
        return {parameter.split(' ')[0].replace('--', ''): parameter.split(' ')[1] for parameter in
                parameters}, sources, prompt


# 将一张大图切割成四张子图
def split_image_into_four(image_data):
    """
    将Midjourney生成的拼接图片分割成四张单独的图片
    简单的四象限分割：上下各一半，左右各一半
    
    Args:
        image_data: 图像二进制数据
        
    Returns:
        包含四张子图像数据的列表
    """
    try:
        # 从二进制数据创建图像对象
        img = Image.open(io.BytesIO(image_data))
        width, height = img.size
        
        # 确认图像尺寸足够大可以分割
        if width < 500 or height < 500:
            jingrow.log_error("图像尺寸太小无法分割", f"尺寸: {width}x{height}, 需要宽度和高度都大于500px")
            return None
        
        # 计算每个象限的尺寸 - 简单的四象限分割
        half_width = width // 2
        half_height = height // 2
        
        # 分割图像为四个象限
        top_left = img.crop((0, 0, half_width, half_height))
        top_right = img.crop((half_width, 0, width, half_height))
        bottom_left = img.crop((0, half_height, half_width, height))
        bottom_right = img.crop((half_width, half_height, width, height))
        
        # 将每个象限转换为二进制数据
        quadrants = []
        for quadrant in [top_left, top_right, bottom_left, bottom_right]:
            buffer = io.BytesIO()
            quadrant.save(buffer, format="PNG")
            quadrants.append(buffer.getvalue())
            
        return quadrants
    except Exception as e:
        jingrow.log_error("分割图像失败", f"错误: {str(e)}")
        traceback.print_exc()
        return None

def call_japi_midjourney(prompt: str, config: Dict = None, callback = None) -> Dict:

    try:
        # 获取API URL
        api_url = f"{get_jingrow_api_url()}/jmidjourney/generate"
        
        headers = get_jingrow_api_headers()
        if not headers:
            error_message = "Jingrow API 未设置，请在 AI设置 中设置 Jingrow Api Key 和 Jingrow Api Secret"
            send_notification(error_message)
            return {"success": False, "message": error_message}
        
        # 准备请求数据
        request_data = {
            "prompt": prompt,
            "config": config or {}
        }
        
        images_data = []
        total_processed = 0
        total_success = 0
        
        response = requests.post(
            api_url, 
            json=request_data, 
            headers=headers, 
            stream=True
        )
        
        if response.status_code != 200:
            try:
                error_data = response.json()
                error_message = error_data.get("message") or error_data.get("error") or f"API请求失败 (HTTP {response.status_code})"
            except:
                error_message = f"API请求失败 (HTTP {response.status_code})"
            
            if response.status_code in [401, 403]:
                auth_error_message = "API认证失败，请检查 Jingrow Api Key 和 Jingrow Api Secret 是否正确"
                send_notification(auth_error_message)
                return {"success": False, "message": auth_error_message}
            
            send_notification(f"API请求失败: {error_message}")
            return {"success": False, "message": error_message}
        
        for line in response.iter_lines():
            if line:
                try:
                    result = json.loads(line.decode('utf-8'))
                    
                    # 处理进度更新
                    if result.get('status') == 'progress':
                        progress = result.get('progress', 0)
                        if callback:
                            callback({
                                "status": "progress",
                                "progress": progress,
                                "seed": result.get('seed')
                            })
                        continue
                    
                    # 处理最终结果
                    if result.get('status') == 'success' and 'image_urls' in result:
                        for image_url in result['image_urls']:
                            # 下载图片
                            img_resp = requests.get(image_url, timeout=30)
                            if img_resp.status_code == 200:
                                img_data = img_resp.content
                                
                                if callback:
                                    callback({
                                        "success": True,
                                        "image_data": img_data,
                                        "image_url": image_url
                                    })
                                else:
                                    images_data.append({
                                        "image_data": img_data,
                                        "image_url": image_url
                                    })
                                total_success += 1
                            else:
                                error_message = f"下载图片失败: HTTP {img_resp.status_code}"
                                if callback:
                                    callback({
                                        "success": False,
                                        "message": error_message
                                    })
                        total_processed += 1
                    else:
                        error_message = result.get('message', '未知错误')
                        if "余额不足" in error_message:
                            send_notification(f"{error_message}")
                            return {"success": False, "message": error_message}
                        elif callback:
                            callback({
                                "success": False,
                                "message": error_message
                            })
                except Exception as e:
                    jingrow.log_error("解析API响应失败", str(e))
                    continue
        
        if callback:
            return {
                "success": True,
                "total_processed": total_processed,
                "total_success": total_success
            }
            
        if not images_data and not callback:
            return {"success": False, "message": "未能获取到任何图像数据"}
        
        return {"success": True, "data": images_data}
        
    except Exception as e:
        jingrow.log_error("API异常", f"调用Midjourney API异常：{str(e)}")
        return {"success": False, "message": f"调用Midjourney API异常：{str(e)}"}

def process_midjourney_task(pg_name, pagetype):
    try:
        # 获取页面对象
        pg = jingrow.get_pg(pagetype, pg_name)
        if not pg:
            jingrow.log_error("处理Midjourney任务失败", f"找不到文档: {pagetype} {pg_name}")
            return False

        # 从页面对象获取提示词
        prompts = None
        
        # 如果英文提示词存在，直接使用
        if hasattr(pg, "prompts") and pg.prompts:
            prompts = pg.prompts
        # 如果中文提示词存在，翻译后使用
        elif hasattr(pg, "prompts_zh") and pg.prompts_zh:
            prompts = get_translated_prompts(pg.prompts_zh)
        
        if not prompts:
            jingrow.log_error("Midjourney任务失败", f"没有提供有效的提示词: {pagetype} {pg_name}")
            if hasattr(pg, "status"):
                pg.status = "任务未完成"
                pg.save()
                jingrow.db.commit()
            return False

        # 如果seamless_pattern为真，添加--tile参数
        if hasattr(pg, "seamless_pattern") and pg.seamless_pattern:
            prompts = f"{prompts} --tile"

        # 更新状态为"任务进行中"
        update_status_progress(pagetype, pg_name, "任务进行中", 0)

        # 准备图像URL列表
        image_urls = []
        
        # 获取并上传参考图片到中间服务器
        if hasattr(pg, "reference_image_1") and is_valid_image_url(pg.reference_image_1):
            full_image_url = pg.reference_image_1
            if not full_image_url.startswith("http"):
                full_image_url = f"{jingrow.utils.get_url()}{pg.reference_image_1}"
            new_image_url = get_new_image_url(full_image_url)
            image_urls.append(new_image_url)
        
        if hasattr(pg, "reference_image_2") and is_valid_image_url(pg.reference_image_2):
            full_image_url = pg.reference_image_2
            if not full_image_url.startswith("http"):
                full_image_url = f"{jingrow.utils.get_url()}{pg.reference_image_2}"
            new_image_url = get_new_image_url(full_image_url)
            image_urls.append(new_image_url)

        if hasattr(pg, "reference_image_3") and is_valid_image_url(pg.reference_image_3):
            full_image_url = pg.reference_image_3
            if not full_image_url.startswith("http"):
                full_image_url = f"{jingrow.utils.get_url()}{pg.reference_image_3}"
            new_image_url = get_new_image_url(full_image_url)
            image_urls.append(new_image_url)
        
        if hasattr(pg, "reference_image_4") and is_valid_image_url(pg.reference_image_4):
            full_image_url = pg.reference_image_4
            if not full_image_url.startswith("http"):
                full_image_url = f"{jingrow.utils.get_url()}{pg.reference_image_4}"
            new_image_url = get_new_image_url(full_image_url)
            image_urls.append(new_image_url)

        # 从配置读取选项
        options = midjourney_options.copy()
        
        # 生成随机种子
        seed = random.randint(1000000000, 9999999999)
        options["seed"] = seed

        # 准备JAPI请求配置
        config = {
            "options": options,
            "image_urls": image_urls
        }
        
        # 如果有参考图像，设置图像权重
        if image_urls and hasattr(pg, "image_weight") and pg.image_weight is not None and 0 < pg.image_weight <= 3:
            config["image_weight"] = pg.image_weight

        jingrow_midjourney = jingrow.db.get_single_value("Ai Settings", "jingrow_midjourney")

        # 根据配置选择使用JAPI还是Discord API
        if jingrow_midjourney:
            processed_count = 0
            success_count = 0
            
            def handle_image_result(result):
                nonlocal processed_count, success_count
                
                if result.get("status") == "progress":
                    # 直接使用服务器返回的进度值
                    progress = result.get("progress", 0)
                    update_progress(pg_name, progress, pagetype)
                    return
                
                if not result.get("success", False):
                    processed_count += 1
                    return
                
                # 生成唯一文件名
                unique_id = str(uuid.uuid4())[:4]
                fields_to_include = ""
                
                if hasattr(pg, "serial_number") and pg.serial_number:
                    fields_to_include += f"{pg.serial_number}_"
                    
                # 只有当add_title_to_image_name为真时，才把title添加到文件名中
                if int(add_title_to_image_name) and hasattr(pg, "title") and pg.title:
                    fields_to_include += f"{pg.title}_"
                    
                image_filename = f"{fields_to_include}{pg_name}_{midjourney_suffix}_{unique_id}_{seed}_{success_count+1}.png"
                
                # 上传图片
                if upload_image(pg_name, result.get("image_data"), image_filename, pagetype):
                    success_count += 1
                
                processed_count += 1
            
            # 调用JAPI处理图片
            api_result = call_japi_midjourney(prompts, config=config, callback=handle_image_result)
            
            if not api_result.get("success", False):
                error_message = api_result.get("message", "未知错误")
                
                if "余额不足" in error_message:
                    update_status_progress(pagetype, pg_name, "任务未完成", 0)
                    if hasattr(pg, "api_error"):
                        pg.api_error = "credit_insufficient"
                        pg.save()
                        jingrow.db.commit()
                    
                    send_notification(f"任务未完成：{error_message}")
                    return False
                
                update_status_progress(pagetype, pg_name, "任务未完成", 0)
                send_notification(f"API调用失败: {error_message}")
                return False
            
            if success_count == 0:
                update_status_progress(pagetype, pg_name, "任务未完成", 0)
                send_notification("未成功生成任何图像")
                return False
                
        else:
            # 使用原有的Discord API
            discord_channel_id = jingrow.db.get_single_value("Ai Settings", "discord_channel_id")
            ai_settings = jingrow.get_single("Ai Settings")
            discord_user_token = ai_settings.get_password("discord_user_token")

            if not discord_channel_id or not discord_user_token:
                jingrow.log_error("处理Midjourney任务失败", "Discord配置不完整")
                if hasattr(pg, "status"):
                    pg.status = "任务未完成"
                    pg.save()
                    jingrow.db.commit()
                return False

            # 初始化Midjourney客户端
            midjourney = Midjourney(discord_channel_id, discord_user_token)

            # 准备图像URL列表
            if image_urls:
                prompt = " ".join(image_urls) + " " + prompts
                # 如果有图片权重设置，添加到 options 中
                if hasattr(pg, "image_weight") and pg.image_weight is not None and 0 < pg.image_weight <= 3:
                    options["iw"] = pg.image_weight
            else:
                prompt = prompts

            # 生成图像并返回生成的消息ID
            result = midjourney.generate(prompt, options, {}, pg_name, pagetype)
            
            imagine_message_id = result['imagine_message_id']
            raw_message = result['raw_message']
            seed = result['seed']

            # 确保生成的消息包含正确的seed
            if f"--seed {seed}" not in raw_message['content']:
                jingrow.log_error("Seed不匹配", f"消息内容: {raw_message['content'][:200]}...")
                raise Exception("Seed不匹配！该消息不属于当前任务。")

            # 设置代理用于下载Discord图片
            proxies = {}
            if http_proxy and http_proxy.strip():
                proxies['http'] = http_proxy
            if https_proxy and https_proxy.strip():
                proxies['https'] = https_proxy
                
            # 从原始消息中获取合并图像URL
            original_image_url = None
            if 'attachments' in raw_message and len(raw_message['attachments']) > 0:
                original_image_url = raw_message['attachments'][0]['url']
            
            if not original_image_url:
                jingrow.log_error("获取原始图像URL失败", "原始消息中没有找到图像附件")
                raise Exception("无法获取原始图像URL")
                
            # 下载原始合并图像
            try:
                if proxies:
                    response = requests.get(original_image_url, proxies=proxies, timeout=30)
                else:
                    response = requests.get(original_image_url, timeout=30)
                    
                if response.status_code != 200:
                    jingrow.log_error("原始图像下载失败", f"状态码: {response.status_code}")
                    raise Exception(f"下载原始图像失败: 状态码 {response.status_code}")
                    
                original_image_data = response.content
            except Exception as e:
                jingrow.log_error("下载原始图像失败", f"错误: {str(e)}")
                raise Exception(f"下载原始图像失败: {str(e)}")
                  
            # 分割原始图像为四个象限
            image_quadrants = split_image_into_four(original_image_data)
            if not image_quadrants:
                jingrow.log_error("分割图像失败", "无法将原始图像分割为四个部分")
                raise Exception("分割图像失败")

            # 上传四个分割后的图像到Jingrow
            for i, quadrant_data in enumerate(image_quadrants):
                try:
                    # 生成唯一文件名
                    unique_id = str(uuid.uuid4())[:4]
                    fields_to_include = ""
                    
                    if hasattr(pg, "serial_number") and pg.serial_number:
                        fields_to_include += f"{pg.serial_number}_"
                        
                    # 只有当add_title_to_image_name为真时，才把title添加到文件名中
                    if int(add_title_to_image_name) and hasattr(pg, "title") and pg.title:
                        fields_to_include += f"{pg.title}_"
                        
                    image_filename = f"{fields_to_include}{pg_name}_{midjourney_suffix}_{unique_id}_{seed}_{i+1}.png"
                    
                    # 使用utils.py中的upload_image函数
                    upload_image(pg_name, quadrant_data, image_filename, pagetype)
                except Exception as e:
                    jingrow.log_error(f"处理图像 {i+1} 失败", f"错误: {str(e)}")
                    traceback.print_exc()
                    continue
        
        # 更新状态为"已出图"
        current_pg = jingrow.get_pg(pagetype, pg_name)
        if hasattr(current_pg, "status"):
            current_pg.status = "已出图"
            if hasattr(current_pg, "progress"):
                current_pg.progress = 100
            current_pg.save()
            jingrow.db.commit()
        
        # 更新任务状态
        update_status_progress(pagetype, pg_name, "已出图", 100)
        
        return True
        
    except Exception as e:
        jingrow.log_error("处理Midjourney任务时发生异常", f"{pagetype}:{pg_name}, 错误: {str(e)}")
        traceback.print_exc()
        update_status_progress(pagetype, pg_name, "任务未完成", 0)
        return False 

@jingrow.whitelist()
def process_midjourney_node_task(prompt: str, config: Dict = None) -> Dict:
    """
    专门为AI绘画节点设计的Midjourney处理函数
    根据jingrow_midjourney配置自动选择使用JAPI还是Discord API
    
    Args:
        prompt: 提示词
        config: 配置参数，包含options等
        
    Returns:
        Dict: 包含success状态和图像数据或错误信息的字典
    """
    try:
        if not prompt:
            return {"success": False, "message": "提示词不能为空"}
            
        config = config or {}
        # 从全局配置开始，然后用传入的配置覆盖
        options = midjourney_options.copy()
        if "options" in config:
            options.update(config.get("options", {}))
        
        # 设置默认选项（如果全局配置中也没有）
        if "ar" not in options or options['ar'] == "":
            options['ar'] = '1:1'
        if "seed" not in options or options['seed'] == "":
            options['seed'] = random.randint(0, 4294967295)
        
        jingrow_midjourney = jingrow.db.get_single_value("Ai Settings", "jingrow_midjourney")
        
        # 根据配置选择使用JAPI还是Discord API
        if jingrow_midjourney:
            # 使用JAPI
            images_data = []
            
            def handle_image_result(result):
                nonlocal images_data
                
                if result.get("status") == "progress":
                    # 进度更新，AI节点中暂时不需要处理
                    return
                
                if not result.get("success", False):
                    return
                
                # 收集图像数据
                if result.get("image_data"):
                    images_data.append({
                        "image_data": result.get("image_data"),
                        "image_url": result.get("image_url")
                    })
            
            # 调用JAPI处理图片
            api_result = call_japi_midjourney(prompt, config=config, callback=handle_image_result)
            
            if not api_result.get("success", False):
                error_message = api_result.get("message", "未知错误")
                return {"success": False, "message": error_message}
            
            if not images_data:
                return {"success": False, "message": "未成功生成任何图像"}
                
            return {"success": True, "data": images_data}
            
        else:
            # 使用Discord API
            discord_channel_id = jingrow.db.get_single_value("Ai Settings", "discord_channel_id")
            ai_settings = jingrow.get_single("Ai Settings")
            discord_user_token = ai_settings.get_password("discord_user_token")

            if not discord_channel_id or not discord_user_token:
                return {"success": False, "message": "Discord配置不完整，请在AI设置中配置discord_channel_id和discord_user_token"}

            # 初始化Midjourney客户端
            midjourney = Midjourney(discord_channel_id, discord_user_token)

            # 处理sources参数（参考图片）
            sources = config.get("sources", {})
            
            # 处理负面提示词
            if config.get("negative_prompt"):
                prompt = f"{prompt} --no {config.get('negative_prompt')}"
                
            # 生成图像并返回生成的消息ID
            result = midjourney.generate(prompt, options, sources, None, None)
            
            imagine_message_id = result['imagine_message_id']
            raw_message = result['raw_message']
            seed = result['seed']

            # 确保生成的消息包含正确的seed
            if f"--seed {seed}" not in raw_message['content']:
                jingrow.log_error("Seed不匹配", f"消息内容: {raw_message['content'][:200]}...")
                return {"success": False, "message": "Seed不匹配！该消息不属于当前任务。"}

            # 设置代理用于下载Discord图片
            proxies = {}
            if http_proxy and http_proxy.strip():
                proxies['http'] = http_proxy
            if https_proxy and https_proxy.strip():
                proxies['https'] = https_proxy
                
            # 从原始消息中获取合并图像URL
            original_image_url = None
            if 'attachments' in raw_message and len(raw_message['attachments']) > 0:
                original_image_url = raw_message['attachments'][0]['url']
            
            if not original_image_url:
                return {"success": False, "message": "无法获取原始图像URL"}
                
            # 下载原始合并图像
            try:
                if proxies:
                    response = requests.get(original_image_url, proxies=proxies, timeout=30)
                else:
                    response = requests.get(original_image_url, timeout=30)
                    
                if response.status_code != 200:
                    return {"success": False, "message": f"下载原始图像失败: 状态码 {response.status_code}"}
                    
                original_image_data = response.content
            except Exception as e:
                return {"success": False, "message": f"下载原始图像失败: {str(e)}"}
                  
            # 分割原始图像为四个象限
            image_quadrants = split_image_into_four(original_image_data)
            if not image_quadrants:
                return {"success": False, "message": "分割图像失败"}

            # 准备返回的图像数据
            images_data = []
            for i, quadrant_data in enumerate(image_quadrants):
                images_data.append({
                    "image_data": quadrant_data,
                    "image_url": None  # Discord模式下没有URL
                })
                
            return {"success": True, "data": images_data}
        
    except Exception as e:
        jingrow.log_error("处理Midjourney节点任务时发生异常", f"错误: {str(e)}")
        traceback.print_exc()
        return {"success": False, "message": f"处理Midjourney任务异常：{str(e)}"} 