"""
门墩儿数据解析模块

该模块提供门墩儿人才数据的解析和处理功能。
"""

import logging
from datetime import datetime
import json
import os
from typing import Dict, Any, Optional, List
import re
from app.core.data_parse.time_utils import get_east_asia_time_str, get_east_asia_timestamp, get_east_asia_isoformat, get_east_asia_date_str


def parse_menduner_data(data_source: str, data_type: str = 'json') -> Dict[str, Any]:
    """
    解析门墩儿人才数据
    
    Args:
        data_source (str): 数据源（文件路径或JSON字符串）
        data_type (str): 数据类型，可选值：'json', 'file', 'api'
        
    Returns:
        Dict[str, Any]: 解析结果
    """
    try:
        logging.info(f"开始解析门墩儿数据，类型: {data_type}")
        
        raw_data = None
        
        if data_type == 'file':
            # 从文件读取数据
            if not os.path.exists(data_source):
                return {
                    'success': False,
                    'error': f'数据文件不存在: {data_source}',
                    'data': None
                }
            
            with open(data_source, 'r', encoding='utf-8') as f:
                raw_data = f.read()
                
        elif data_type == 'json':
            # 直接处理JSON字符串
            raw_data = data_source
            
        elif data_type == 'api':
            # TODO: 实现API数据获取逻辑
            raw_data = data_source
        
        # 解析数据
        if raw_data:
            parsed_data = _process_menduner_content(raw_data)
            
            result = {
                'success': True,
                'error': None,
                'data': {
                    'talent_profiles': parsed_data,
                    'parse_time': get_east_asia_isoformat(),
                    'source_type': data_type,
                    'total_count': len(parsed_data) if isinstance(parsed_data, list) else 1
                }
            }
            
            logging.info(f"门墩儿数据解析完成，共解析 {result['data']['total_count']} 条记录")
            return result
        
        return {
            'success': False,
            'error': '无法获取有效数据',
            'data': None
        }
        
    except Exception as e:
        error_msg = f"解析门墩儿数据失败: {str(e)}"
        logging.error(error_msg, exc_info=True)
        
        return {
            'success': False,
            'error': error_msg,
            'data': None
        }


def _process_menduner_content(raw_content: str) -> List[Dict[str, Any]]:
    """
    处理门墩儿原始数据内容
    
    Args:
        raw_content (str): 原始数据内容
        
    Returns:
        List[Dict[str, Any]]: 处理后的人才档案列表
    """
    try:
        # 尝试解析JSON格式
        try:
            json_data = json.loads(raw_content)
            if isinstance(json_data, list):
                return [_normalize_talent_profile(item) for item in json_data]
            elif isinstance(json_data, dict):
                return [_normalize_talent_profile(json_data)]
        except json.JSONDecodeError:
            pass
        
        # 如果不是JSON，尝试按行解析
        lines = raw_content.strip().split('\n')
        profiles = []
        
        for line in lines:
            line = line.strip()
            if line:
                profile = _parse_talent_line(line)
                if profile:
                    profiles.append(profile)
        
        return profiles
        
    except Exception as e:
        logging.error(f"处理门墩儿数据内容失败: {str(e)}")
        return []


def _normalize_talent_profile(raw_profile: Dict[str, Any]) -> Dict[str, Any]:
    """
    标准化人才档案数据
    
    Args:
        raw_profile (Dict[str, Any]): 原始档案数据
        
    Returns:
        Dict[str, Any]: 标准化后的档案数据
    """
    normalized = {
        'name': raw_profile.get('name', ''),
        'phone': _normalize_phone(raw_profile.get('phone', '')),
        'email': _normalize_email(raw_profile.get('email', '')),
        'position': raw_profile.get('position', ''),
        'company': raw_profile.get('company', ''),
        'location': raw_profile.get('location', ''),
        'experience_years': raw_profile.get('experience_years', 0),
        'skills': raw_profile.get('skills', []),
        'education': raw_profile.get('education', ''),
        'source': 'menduner',
        'processed_time': get_east_asia_isoformat(),
        'raw_data': raw_profile
    }
    
    return normalized


def _normalize_talent_to_card_format(raw_profile: Dict[str, Any]) -> Dict[str, Any]:
    """
    将门墩儿人才数据标准化为名片格式，与任务解析结果.txt中的data字段格式一致
    
    Args:
        raw_profile (Dict[str, Any]): 原始门墩儿档案数据
        
    Returns:
        Dict[str, Any]: 标准化后的名片格式数据
    """
    import json
    
    # 从raw_profile中提取基本信息
    name_zh = raw_profile.get('name_zh', '')
    email = raw_profile.get('email', '')
    mobile = raw_profile.get('mobile', '')
    birthday = raw_profile.get('birthday', '')
    age = raw_profile.get('age', '')
    career_path = raw_profile.get('career_path', [])
    
    # 从career_path中找到最后一个数组元素，提取hotel_zh和title_zh
    hotel_zh = ''
    title_zh = ''
    if career_path and isinstance(career_path, list) and len(career_path) > 0:
        last_career = career_path[-1]
        if isinstance(last_career, dict):
            hotel_zh = last_career.get('hotel_zh', '')
            title_zh = last_career.get('title_zh', '')
    
    # 从id和userId组合成JSON字符串
    id_value = raw_profile.get('id', '')
    userId_value = raw_profile.get('userId', '')
    id_json = json.dumps({"id": id_value, "userId": userId_value}, ensure_ascii=False)
    
    # 直接使用原始career_path
    
    # 按照任务解析结果.txt的data字段格式组装数据
    normalized = {
        "address_en": raw_profile.get('address_en', ''),
        "address_zh": raw_profile.get('address_zh', ''),
        "affiliation": raw_profile.get('affiliation', []),
        "age": age,
        "gender": raw_profile.get('gender', ''),
        "birthday": birthday,
        "brand_group": raw_profile.get('brand_group', ''),
        "career_path": career_path,
        "email": _normalize_email(email),
        "hotel_en": raw_profile.get('hotel_en', ''),
        "hotel_zh": hotel_zh,
        "mobile": _normalize_phone(mobile),
        "name_en": raw_profile.get('name_en', ''),
        "name_zh": name_zh,
        "native_place": raw_profile.get('native_place', ''),
        "phone": raw_profile.get('phone', ''),
        "postal_code_en": raw_profile.get('postal_code_en', ''),
        "postal_code_zh": raw_profile.get('postal_code_zh', ''),
        "residence": raw_profile.get('residence', ''),
        "title_en": raw_profile.get('title_en', ''),
        "title_zh": title_zh,
        "image_path": id_json,
        "origin_source": [{
            "task_type": "招聘",
            "minio_path": id_json,
            "source_date": get_east_asia_date_str()
        }]
    }
    
    return normalized


def _parse_talent_line(line: str) -> Optional[Dict[str, Any]]:
    """
    解析单行人才信息
    
    Args:
        line (str): 包含人才信息的文本行
        
    Returns:
        Optional[Dict[str, Any]]: 解析后的人才信息，如果解析失败返回None
    """
    try:
        # TODO: 根据门墩儿数据的具体格式实现解析逻辑
        # 这里提供一个基础的解析示例
        
        # 简单的分隔符解析（假设用制表符或逗号分隔）
        if '\t' in line:
            parts = line.split('\t')
        elif ',' in line:
            parts = line.split(',')
        else:
            parts = [line]
        
        if len(parts) >= 3:
            return {
                'name': parts[0].strip(),
                'phone': parts[1].strip() if len(parts) > 1 else '',
                'position': parts[2].strip() if len(parts) > 2 else '',
                'company': parts[3].strip() if len(parts) > 3 else ''
            }
        
        return None
        
    except Exception as e:
        logging.error(f"解析人才信息行失败: {str(e)}")
        return None


def _normalize_phone(phone: str) -> str:
    """
    标准化电话号码格式
    
    Args:
        phone (str): 原始电话号码
        
    Returns:
        str: 标准化后的电话号码
    """
    if not phone:
        return ''
    
    # 移除所有非数字字符
    digits = re.sub(r'\D', '', phone)
    
    # 中国手机号码格式化
    if len(digits) == 11 and digits.startswith('1'):
        return f"{digits[:3]}-{digits[3:7]}-{digits[7:]}"
    
    return phone


def _normalize_email(email: str) -> str:
    """
    标准化邮箱地址
    
    Args:
        email (str): 原始邮箱地址
        
    Returns:
        str: 标准化后的邮箱地址
    """
    if not email:
        return ''
    
    # 基础邮箱格式验证
    email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    if re.match(email_pattern, email.strip()):
        return email.strip().lower()
    
    return email


def validate_menduner_data(data: Dict[str, Any]) -> Dict[str, Any]:
    """
    验证门墩儿人才数据的完整性和有效性（名片格式）
    
    Args:
        data (Dict[str, Any]): 待验证的名片格式人才数据
        
    Returns:
        Dict[str, Any]: 验证结果
    """
    try:
        errors = []
        warnings = []
        
        # 必填字段检查（按名片格式）
        required_fields = ['name_zh']
        for field in required_fields:
            if not data.get(field):
                errors.append(f"缺少必填字段: {field}")
        
        # 可选但建议填写的字段
        recommended_fields = ['mobile', 'title_zh', 'hotel_zh']
        for field in recommended_fields:
            if not data.get(field):
                warnings.append(f"建议填写字段: {field}")
        
        # 格式验证
        if data.get('mobile'):
            mobile = data['mobile']
            # 移除所有非数字字符进行验证
            digits_only = re.sub(r'\D', '', mobile)
            if digits_only and not re.match(r'^1[3-9]\d{9}$', digits_only):
                warnings.append("手机号码格式可能不正确")
        
        if data.get('email'):
            email = data['email']
            if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', email):
                errors.append("邮箱格式不正确")
        
        # 验证数组字段
        if data.get('affiliation') is not None and not isinstance(data['affiliation'], list):
            errors.append("affiliation字段必须是数组格式")
        
        if data.get('career_path') is not None and not isinstance(data['career_path'], list):
            errors.append("career_path字段必须是数组格式")
        
        # 验证年龄字段
        if data.get('age') is not None:
            age = data['age']
            if not isinstance(age, int) or age < 0 or age > 150:
                warnings.append("年龄值可能不合理")
        
        return {
            'is_valid': len(errors) == 0,
            'errors': errors,
            'warnings': warnings,
            'score': max(0, 100 - len(errors) * 20 - len(warnings) * 5)
        }
        
    except Exception as e:
        logging.error(f"验证门墩儿数据失败: {str(e)}")
        return {
            'is_valid': False,
            'errors': [f"验证过程出错: {str(e)}"],
            'warnings': [],
            'score': 0
        }


def batch_process_menduner_data(data_list: List[Dict[str, Any]], task_id=None, task_type=None) -> Dict[str, Any]:
    """
    批量处理门墩儿人才数据
    
    Args:
        data_list (List[Dict[str, Any]]): 待处理的人才数据列表（已废弃，现在从数据库读取）
        task_id (str, optional): 任务ID，用于从数据库读取task_source
        task_type (str, optional): 任务类型
        
    Returns:
        Dict[str, Any]: 批量处理结果，格式与parse_result保持一致
    """
    try:
        # 根据task_id从parse_task_repository表读取记录
        if not task_id:
            return {
                "processed_time": get_east_asia_isoformat(),
                "results": [],
                "summary": {
                    "failed_count": 0,
                    "success_count": 0,
                    "success_rate": 0,
                    "total_files": 0
                },
                "error": "缺少task_id参数"
            }
        
        # 导入数据库模型
        from app.models.parse_models import ParseTaskRepository
        from app import db
        
        # 查询对应的任务记录
        task_record = ParseTaskRepository.query.get(task_id)
        if not task_record:
            return {
                "processed_time": get_east_asia_isoformat(),
                "results": [],
                "summary": {
                    "failed_count": 0,
                    "success_count": 0,
                    "success_rate": 0,
                    "total_files": 0
                },
                "error": f"未找到task_id为{task_id}的任务记录"
            }
        
        # 获取task_source作为需要处理的数据列表
        task_source = task_record.task_source
        if not task_source or not isinstance(task_source, list):
            return {
                "processed_time": get_east_asia_isoformat(),
                "results": [],
                "summary": {
                    "failed_count": 0,
                    "success_count": 0,
                    "success_rate": 0,
                    "total_files": 0
                },
                "error": "task_source为空或格式不正确"
            }
        
        results = []
        success_count = 0
        failed_count = 0
        parsed_record_ids = []  # 收集成功解析的记录ID
        
        logging.info(f"开始批量处理门墩儿人才数据，共 {len(task_source)} 条记录")
        
        # 逐一处理每条数据
        for i, data in enumerate(task_source):
            try:
                # 只处理parse_flag为1的记录
                if not isinstance(data, dict) or data.get('parse_flag') != 1:
                    logging.debug(f"跳过第 {i+1} 条数据，parse_flag不为1或格式不正确")
                    continue
                
                logging.debug(f"处理第 {i+1}/{len(task_source)} 条数据")
                
                # 标准化数据为名片格式
                normalized = _normalize_talent_to_card_format(data)
                
                # 验证数据
                validation = validate_menduner_data(normalized)
                
                if validation.get('is_valid', False):
                    # 记录成功解析的人才信息到parsed_talents表
                    try:
                        from app.core.data_parse.parse_task import record_parsed_talent
                        record_result = record_parsed_talent(normalized, task_id, task_type)
                        if record_result.get('success'):
                            # 收集成功解析的记录ID
                            parsed_record = record_result.get('data', {})
                            if parsed_record and 'id' in parsed_record:
                                parsed_record_ids.append(str(parsed_record['id']))
                            logging.info(f"成功记录人才信息到parsed_talents表: {normalized.get('name_zh', '')}")
                            
                            # 更新task_source中对应记录的parse_flag和status
                            data['parse_flag'] = 0
                            data['status'] = '解析成功'
                        else:
                            logging.warning(f"记录人才信息失败: {record_result.get('message', '')}")
                            # 更新task_source中对应记录的parse_flag和status
                            data['parse_flag'] = 1
                            data['status'] = '解析失败'
                    except Exception as record_error:
                        logging.error(f"调用record_parsed_talent函数失败: {str(record_error)}")
                        # 更新task_source中对应记录的parse_flag和status
                        data['parse_flag'] = 1
                        data['status'] = '解析失败'
                    
                    success_count += 1
                    results.append({
                        "data": normalized,
                        "error": None,
                        "filename": data.get('filename', f'menduner_record_{i}.json'),
                        "index": i,
                        "message": "门墩儿数据解析成功",
                        "minio_path": data.get('minio_path', ''),
                        "object_key": data.get('object_key', f'menduner_data/record_{i}.json'),
                        "success": True
                    })
                    logging.debug(f"成功处理第 {i+1} 条数据")
                else:
                    failed_count += 1
                    error_messages = validation.get('errors', ['验证失败'])
                    
                    # 更新task_source中对应记录的parse_flag和status
                    data['parse_flag'] = 1
                    data['status'] = '解析失败'
                    
                    results.append({
                        "data": None,
                        "error": '; '.join(error_messages),
                        "filename": data.get('filename', f'menduner_record_{i}.json'),
                        "index": i,
                        "message": "门墩儿数据解析失败",
                        "minio_path": data.get('minio_path', ''),
                        "object_key": data.get('object_key', f'menduner_data/record_{i}.json'),
                        "success": False
                    })
                    logging.warning(f"处理第 {i+1} 条数据失败: {'; '.join(error_messages)}")
                    
            except Exception as item_error:
                failed_count += 1
                error_msg = f"处理门墩儿数据失败: {str(item_error)}"
                logging.error(error_msg, exc_info=True)
                
                # 更新task_source中对应记录的parse_flag和status
                if isinstance(data, dict):
                    data['parse_flag'] = 1
                    data['status'] = '解析失败'
                
                results.append({
                    "data": None,
                    "error": error_msg,
                    "filename": data.get('filename', f'menduner_record_{i}.json') if isinstance(data, dict) else f'menduner_record_{i}.json',
                    "index": i,
                    "message": "门墩儿数据解析失败",
                    "minio_path": data.get('minio_path', '') if isinstance(data, dict) else '',
                    "object_key": data.get('object_key', f'menduner_data/record_{i}.json') if isinstance(data, dict) else f'menduner_data/record_{i}.json',
                    "success": False
                })
        
        # 根据处理结果更新task_status
        if failed_count == 0:
            task_status = '解析成功'
        elif success_count == 0:
            task_status = '解析失败'
        else:
            task_status = '部分解析成功'
        
        # 所有task_source记录处理完成后，将更新后的task_source和task_status保存到数据库
        try:
            task_record.task_source = task_source
            task_record.task_status = task_status
            task_record.parse_count = success_count
            task_record.parse_result = {
                'success_count': success_count,
                'failed_count': failed_count,
                'parsed_record_ids': parsed_record_ids,
                'processed_time': get_east_asia_isoformat()
            }
            db.session.commit()
            logging.info(f"成功更新task_id为{task_id}的任务记录，task_status={task_status}，处理成功{success_count}条，失败{failed_count}条")
        except Exception as update_error:
            logging.error(f"更新任务记录失败: {str(update_error)}")
            db.session.rollback()
        
        # 组装最终结果
        if failed_count == 0:
            return {
                'code': 200,
                'success': True,
                'message': f'批量处理完成，全部 {success_count} 个文件处理成功',
                'data': {
                    'success_count': success_count,
                    'failed_count': failed_count,
                    'parsed_record_ids': parsed_record_ids
                }
            }
        elif success_count == 0:
            return {
                'code': 500,
                'success': False,
                'message': f'批量处理失败，全部 {failed_count} 个文件处理失败',
                'data': {
                    'success_count': success_count,
                    'failed_count': failed_count,
                    'parsed_record_ids': parsed_record_ids
                }
            }
        else:
            return {
                'code': 206,  # Partial Content
                'success': True,
                'message': f'批量处理部分成功，成功 {success_count} 个，失败 {failed_count} 个',
                'data': {
                    'success_count': success_count,
                    'failed_count': failed_count,
                    'parsed_record_ids': parsed_record_ids
                }
            }
            
    except Exception as e:
        error_msg = f"批量处理门墩儿数据失败: {str(e)}"
        logging.error(error_msg, exc_info=True)
        
        batch_result = {
            'summary': {
                'total_files': len(data_list) if data_list else 1,
                'success_count': 0,
                'failed_count': len(data_list) if data_list else 1,
                'success_rate': 0
            },
            'results': [],
            'processed_time': get_east_asia_isoformat()
        }
        
        return {
            'code': 500,
            'success': False,
            'message': error_msg,
            'data': batch_result
        } 