import requests
import json
import os
import uuid
import datetime
import pytz

from jingrow.config import Config
from jingrow.utils.auth import get_jingrow_api_headers, get_jingrow_cloud_api_headers, get_jingrow_cloud_api_url
import jingrow

# AI 模型调用函数已移至 jingrow_cloud.py
from jingrow.utils.jingrow_cloud import call_ai_model

def log_info(message):
    """记录信息日志"""
    print(f"[INFO] {message}")

def log_error(message):
    """记录错误日志"""
    print(f"[ERROR] {message}")

def get_logged_user(session_cookie: str = None):
    """获取当前登录用户（基于会话cookie）。返回如 Administrator 或 user@example.com。"""
    try:
        api_url = f"{Config.jingrow_server_url}/api/action/jingrow.auth.get_logged_user"
        cookie = session_cookie
        if not cookie:
            return None
        headers = {
            "Content-Type": "application/json",
            "Accept": "application/json",
            "Cookie": f"sid={cookie}"
        }
        resp = requests.get(api_url, headers=headers, timeout=8)
        if resp.status_code == 200:
            data = resp.json()
            # 兼容 message 格式
            if isinstance(data, dict) and 'message' in data:
                return data['message']
            return data
        return None
    except Exception:
        return None

def upload_file_to_jingrow(file_data, filename, attached_to_pagetype=None, attached_to_name=None, attached_to_field=None):
    """
    上传文件到Jingrow服务器
    
    Args:
        file_data (bytes): 文件二进制数据
        filename (str): 文件名
        attached_to_pagetype (str, optional): 关联的页面类型
        attached_to_name (str, optional): 关联的记录名称
        attached_to_field (str, optional): 关联的字段名称
    
    Returns:
        dict: 上传结果
        {
            'success': bool,
            'file_url': str,  # 成功时返回文件URL
            'file_name': str, # 成功时返回文件名
            'error': str      # 失败时返回错误信息
        }
    """
    try:
        # 构建API URL
        api_url = f"{Config.jingrow_server_url}/api/action/upload_file"
        
        # 获取认证头信息
        headers = get_jingrow_api_headers()
        # 移除Content-Type，让requests自动设置multipart/form-data
        if 'Content-Type' in headers:
            del headers['Content-Type']
        
        # 准备请求数据 - Jingrow期望multipart/form-data格式
        files = {
            'file': (filename, file_data, 'application/octet-stream')
        }
        
        data = {
            'file_name': filename,
            'is_private': 0
        }
        
        # 如果有关联记录，添加到请求数据中
        if attached_to_pagetype and attached_to_name:
            data['pagetype'] = attached_to_pagetype
            data['docname'] = attached_to_name
            
        if attached_to_field:
            data['fieldname'] = attached_to_field
        
        # 发送请求
        response = requests.post(api_url, files=files, data=data, headers=headers, timeout=30)
        
        if response.status_code == 200:
            result = response.json()
            
            # 检查session是否过期
            if result.get('session_expired'):
                return {'success': False, 'error': 'Session已过期，请重新登录'}
            
            if result.get('message'):
                return {
                    'success': True,
                    'file_url': result['message'].get('file_url'),
                    'file_name': result['message'].get('file_name')
                }
            else:
                return {'success': False, 'error': 'API响应格式错误'}
        else:
            error_text = response.text
            log_error(f"API请求失败: {response.status_code}, 响应: {error_text}")
            return {'success': False, 'error': f'API请求失败 (HTTP {response.status_code}): {error_text}'}
            
    except Exception as e:
        return {'success': False, 'error': f'调用upload_file API异常: {str(e)}'}

def get_field_mapping_from_jingrow(pagetype):
    """
    从Jingrow获取字段的label到fieldname的映射
    Args:
        pagetype (str): 页面类型名称
    Returns:
        dict: {label: fieldname} 的映射字典
    """
    try:
        api_url = f"{Config.jingrow_server_url}/api/action/jingrow.ai.utils.jlocal.get_field_mapping"
        headers = get_jingrow_api_headers()
        data = {
            'pagetype': pagetype
        }
        
        response = requests.post(api_url, json=data, headers=headers, timeout=10)
        
        if response.status_code == 200:
            result = response.json()
            # 处理Jingrow API的响应格式
            if 'message' in result:
                result = result['message']
            
            if result.get('success'):
                return result.get('field_mapping', {})
            else:
                log_error(f"获取字段映射失败: {result.get('error', '未知错误')}")
                return {}
        else:
            log_error(f"获取字段映射失败: HTTP {response.status_code}")
            return {}
            
    except Exception as e:
        log_error(f"获取字段映射异常: {str(e)}")
        return {}

def get_field_value_from_jingrow(pagetype, name, fieldname):
    """
    从Jingrow获取字段的当前值
    Args:
        pagetype (str): 页面类型名称
        name (str): 记录名称
        fieldname (str): 字段名称
    Returns:
        str: 字段的当前值，如果为空则返回None
    """
    try:
        api_url = f"{Config.jingrow_server_url}/api/action/jingrow.ai.utils.jlocal.get_field_value"
        headers = get_jingrow_api_headers()
        data = {
            'pagetype': pagetype,
            'name': name,
            'fieldname': fieldname
        }
        
        response = requests.post(api_url, json=data, headers=headers, timeout=10)
        
        if response.status_code == 200:
            result = response.json()
            if 'message' in result:
                result = result['message']
            
            if result.get('success'):
                return result.get('value')
            else:
                log_error(f"获取字段值失败: {result.get('error', '未知错误')}")
                return None
        else:
            log_error(f"获取字段值失败: HTTP {response.status_code}")
            return None
            
    except Exception as e:
        log_error(f"获取字段值异常: {str(e)}")
        return None

def get_ai_settings_from_jingrow():
    try:
        # 使用新的API端点
        api_url = f"{Config.jingrow_server_url}/api/action/jingrow.ai.utils.jlocal.get_ai_settings"
        headers = get_jingrow_api_headers()
        
        response = requests.post(api_url, headers=headers, timeout=10)
        
        if response.status_code == 200:
            result = response.json()
            
            # 检查session是否过期
            if result.get('session_expired'):
                log_error("Session已过期，请重新登录")
                return None
            
            # 处理Jingrow API的响应格式
            if 'message' in result:
                result = result['message']
            
            if result.get('success'):
                return result.get('config', {})
            else:
                log_error(f"获取AI Settings失败: {result.get('error', '未知错误')}")
                return None
        else:
            log_error(f"获取AI Settings失败: HTTP {response.status_code}")
            return None
            
    except Exception as e:
        log_error(f"获取AI Settings配置异常: {str(e)}")
        return None

def get_agent_detail(name: str, session_cookie: str = None):
    """
    获取智能体详情
    Returns: dict 或 None
    """
    try:
        api_url = f"{Config.jingrow_server_url}/api/action/jingrow.ai.utils.jlocal.get_local_ai_agent_detail"
        
        # 统一使用系统级认证
        headers = get_jingrow_api_headers()
        if not headers:
            log_error("JINGROW_API_KEY 或 JINGROW_API_SECRET 未配置")
            return None
            
        payload = {"name": name}
        response = requests.post(api_url, headers=headers, json=payload, timeout=15)
        
        if response.status_code == 200:
            data = response.json()
            if isinstance(data, dict) and 'message' in data:
                message = data['message']
                if isinstance(message, dict) and message.get('success'):
                    return message.get('data')
            return data
        else:
            log_error(f"Failed to get agent detail: HTTP {response.status_code}: {response.text}")
            return None
            
    except Exception as e:
        log_error(f"获取智能体详情异常: {str(e)}")
        return None

def get_record(pagetype: str, name: str, session_cookie: str = None):
    """
    获取指定记录
    Returns: { 'success': bool, 'data': dict } 或 { 'success': False, 'error': str }
    """
    try:
        api_url = f"{Config.jingrow_server_url}/api/data/{pagetype}/{name}"
        
        # 统一使用系统级认证
        headers = get_jingrow_api_headers()
        if not headers:
            return {'success': False, 'error': 'JINGROW_API_KEY 或 JINGROW_API_SECRET 未配置'}
            
        response = requests.get(api_url, headers=headers, timeout=15)
        if response.status_code == 200:
            data = response.json()
            if isinstance(data, dict) and 'data' in data:
                return {'success': True, 'data': data['data']}
            return {'success': True, 'data': data}
        else:
            return {'success': False, 'error': f"HTTP {response.status_code}: {response.text}"}
    except Exception as e:
        return {'success': False, 'error': f"获取记录异常: {str(e)}"}

def create_record(pagetype: str, payload: dict):
    """
    创建记录
    Returns: { 'success': True, 'data': dict } 或 { 'success': False, 'error': str }
    """
    try:
        api_url = f"{Config.jingrow_server_url}/api/data/{pagetype}"
        headers = get_jingrow_api_headers()
        response = requests.post(api_url, json=payload, headers=headers, timeout=20)
        if response.status_code in (200, 201):
            data = response.json()
            if isinstance(data, dict) and 'data' in data:
                return {'success': True, 'data': data['data']}
            return {'success': True, 'data': data}
        else:
            return {'success': False, 'error': f"HTTP {response.status_code}: {response.text}"}
    except Exception as e:
        return {'success': False, 'error': f"创建记录异常: {str(e)}"}

def update_record(pagetype: str, name: str, payload: dict):
    """
    更新记录（覆盖写）
    Returns: { 'success': True, 'data': dict } 或 { 'success': False, 'error': str }
    """
    try:
        api_url = f"{Config.jingrow_server_url}/api/data/{pagetype}/{name}"
        headers = get_jingrow_api_headers()
        response = requests.put(api_url, json=payload, headers=headers, timeout=20)
        if response.status_code in (200, 202):
            data = response.json()
            if isinstance(data, dict) and 'data' in data:
                return {'success': True, 'data': data['data']}
            return {'success': True, 'data': data}
        else:
            return {'success': False, 'error': f"HTTP {response.status_code}: {response.text}"}
    except Exception as e:
        return {'success': False, 'error': f"更新记录异常: {str(e)}"}


def update_local_job(data: dict):
    """
    更新 Local Job 记录
    """
    return push_local_job_to_jingrow(data)


def push_local_job_to_jingrow(data: dict):
    """
    通过 Jingrow 动作接口推送/更新 Local Job（写入 Jingrow 端 Redis）。
    Returns: { 'success': True } or { 'success': False, 'error': str }
    """
    try:
        api_url = f"{Config.jingrow_server_url}/api/action/jingrow.core.pagetype.local_job.local_job.push_local_job"
        
        # 统一使用系统级认证
        headers = get_jingrow_api_headers()
        if not headers:
            return {'success': False, 'error': 'JINGROW_API_KEY 或 JINGROW_API_SECRET 未配置'}
        
        headers.setdefault("X-Requested-With", "XMLHttpRequest")

        # 指定站点（多站点部署时避免落到错误站点）
        site_name = getattr(Config, "JINGROW_SITE", None) or os.getenv("JINGROW_SITE")
        if site_name:
            headers["X-Frappe-Site-Name"] = site_name
        log_info(f"[JFLOW->JINGROW] 准备推送 Local Job: job_id={data.get('job_id')} status={data.get('status')} queue={data.get('queue')}")
        resp = requests.post(api_url, json=data, headers=headers, timeout=10)
        if resp.status_code == 200:
            body = resp.json()
            # 兼容 message 包裹
            if isinstance(body, dict) and 'message' in body:
                body = body['message']
            if isinstance(body, dict) and body.get('success'):
                log_info(f"[JFLOW->JINGROW] 推送成功: job_id={data.get('job_id')} status={data.get('status')}")
                return {'success': True}
            log_error(f"[JFLOW->JINGROW] 推送失败(body): {body}")
            return {'success': False, 'error': str(body)}
        log_error(f"[JFLOW->JINGROW] 推送失败(HTTP): {resp.status_code} {resp.text}")
        return {'success': False, 'error': f"HTTP {resp.status_code}: {resp.text}"}
    except Exception as e:
        log_error(f"[JFLOW->JINGROW] 推送异常: {str(e)}")
        return {'success': False, 'error': f"推送 Local Job 失败: {str(e)}"}

def delete_record(pagetype: str, name: str):
    """
    删除记录
    Returns: { 'success': True } 或 { 'success': False, 'error': str }
    """
    try:
        api_url = f"{Config.jingrow_server_url}/api/data/{pagetype}/{name}"
        headers = get_jingrow_api_headers()
        response = requests.delete(api_url, headers=headers, timeout=15)
        if response.status_code in (200, 202):
            return {'success': True}
        else:
            return {'success': False, 'error': f"HTTP {response.status_code}: {response.text}"}
    except Exception as e:
        return {'success': False, 'error': f"删除记录异常: {str(e)}"}

def map_fields_by_labels(field_map: list, ai_outputs: dict, label_to_fieldname: dict) -> dict:
    """
    根据 field_map 将 ai_outputs 映射为记录字段数据。
    - field_map: [{ 'from': '来源字段', 'to': '目标label或字段名' }]
    - ai_outputs: 上游节点聚合的输出
    - label_to_fieldname: 来自 Jingrow 的 label 到字段名映射
    返回: dict 记录字段数据
    """
    record_data = {}
    fieldname_set = set(label_to_fieldname.values())
    for mapping in field_map or []:
        source_key = mapping.get('from')
        to_raw = mapping.get('to')
        if not source_key or to_raw is None:
            continue
        value = ai_outputs.get(source_key)
        if value is None:
            continue
        # 目标字段既支持label也支持字段名
        to_field = label_to_fieldname.get(str(to_raw).strip())
        if not to_field and str(to_raw).strip() in fieldname_set:
            to_field = str(to_raw).strip()
        if not to_field:
            continue
        record_data[to_field] = value
    return record_data

def get_record_list(pagetype: str, filters: list = None, fields: list = None, limit: int = None):
    """
    列表查询记录
    - filters: 形如 [[field, op, value], ...]
    - fields:  需要返回的字段列表，例如 ["name"]
    Returns: { 'success': True, 'data': list } 或 { 'success': False, 'error': str }
    """
    try:
        base_url = f"{Config.jingrow_server_url}/api/data/{pagetype}"
        params = {}
        if filters:
            params['filters'] = json.dumps(filters, ensure_ascii=False)
        if fields:
            params['fields'] = json.dumps(fields, ensure_ascii=False)
        if isinstance(limit, int) and limit > 0:
            params['limit'] = str(limit)
        headers = get_jingrow_api_headers()
        response = requests.get(base_url, params=params, headers=headers, timeout=20)
        if response.status_code == 200:
            data = response.json()
            # 兼容不同返回格式
            if isinstance(data, dict) and 'data' in data:
                return {'success': True, 'data': data['data']}
            if isinstance(data, list):
                return {'success': True, 'data': data}
            return {'success': True, 'data': [data]}
        else:
            return {'success': False, 'error': f"HTTP {response.status_code}: {response.text}"}
    except Exception as e:
        return {'success': False, 'error': f"列表查询异常: {str(e)}"}

def get_page_meta(pagetype: str):

    try:
        api_url = f"{Config.jingrow_server_url}/api/action/jingrow.ai.utils.jlocal.get_meta"
        headers = get_jingrow_api_headers()
        payload = {"pagetype": pagetype}
        response = requests.post(api_url, json=payload, headers=headers, timeout=10)
        if response.status_code == 200:
            result = response.json()
            # 处理服务端 action 的包裹格式
            if isinstance(result, dict) and 'message' in result:
                result = result['message']
            if isinstance(result, dict) and result.get('success'):
                return {'success': True, 'data': result.get('data', {})}
            return {'success': False, 'error': result.get('error', '获取Meta失败') if isinstance(result, dict) else '获取Meta失败'}
        else:
            return {'success': False, 'error': f"HTTP {response.status_code}: {response.text}"}
    except Exception as e:
        return {'success': False, 'error': f"获取Meta异常: {str(e)}"}

def get_record_id(pagetype: str, filters: list = None, field: str = None, value: str = None, site: str = None):
    """
    按条件获取单条记录的 name 值。
    - 传入 filters（二维数组）优先；否则用 field+value 生成等值过滤；可选附加 site 条件。
    返回: { 'success': True, 'name': str } 或 { 'success': False, 'error': str }
    """
    try:
        query_filters = []
        if isinstance(filters, list) and filters:
            query_filters = filters
        elif field and (value is not None):
            query_filters = [[field, '=', value]]
        if site:
            query_filters.append(['site', '=', site])

        res = get_record_list(pagetype, filters=query_filters, fields=['name'], limit=1)
        if not res.get('success'):
            return {'success': False, 'error': res.get('error', '查询失败')}
        data = res.get('data') or []
        if not data:
            return {'success': False, 'error': '未找到记录'}
        name = (data[0] or {}).get('name')
        if not name:
            return {'success': False, 'error': '记录缺少name字段'}
        return {'success': True, 'name': name}
    except Exception as e:
        return {'success': False, 'error': f'获取记录name失败: {str(e)}'}

def get_jingrow_system_timezone():
    """
    获取 Jingrow 系统时区设置
    
    Returns:
        pytz.BaseTzInfo: 时区对象
    """
    try:
        headers = get_jingrow_api_headers()
        if not headers:
            return _get_default_timezone()
            
        url = f"{Config.jingrow_server_url}/api/action/jingrow.core.pagetype.system_settings.system_settings.load"
        response = requests.post(url, headers=headers, timeout=5)
        
        if response.status_code == 200:
            timezone_name = response.json().get('message', {}).get('defaults', {}).get('time_zone')
            if timezone_name:
                return pytz.timezone(timezone_name)
                
    except (requests.RequestException, pytz.exceptions.UnknownTimeZoneError, KeyError):
        pass
        
    return _get_default_timezone()

def get_single_pagetype(pagetype: str):
    """获取single类型pagetype记录"""
    try:
        api_url = f"{Config.jingrow_server_url}/api/action/jingrow.ai.utils.jlocal.get_single_pagetype"
        response = requests.post(api_url, json={"pagetype": pagetype}, headers=get_jingrow_api_headers(), timeout=10)
        
        if response.status_code == 200:
            result = response.json().get('message', response.json())
            return {'success': True, 'config': result.get('config', {})} if result.get('success') else {'success': False, 'error': result.get('error', '获取失败')}
        return {'success': False, 'error': f"HTTP {response.status_code}"}
    except Exception as e:
        return {'success': False, 'error': str(e)}

def _get_default_timezone():
    """获取默认时区"""
    return datetime.datetime.now().astimezone().tzinfo
