from breed_health_info import breed_health_info
from breed_noise_info import breed_noise_info

@dataclass
class UserPreferences:
    """使用者偏好設定的資料結構"""
    living_space: str  # "apartment", "house_small", "house_large"
    exercise_time: int  # minutes per day
    grooming_commitment: str  # "low", "medium", "high"
    experience_level: str  # "beginner", "intermediate", "advanced"
    has_children: bool
    noise_tolerance: str  # "low", "medium", "high"
    space_for_play: bool
    other_pets: bool
    climate: str  # "cold", "moderate", "hot"
    health_sensitivity: str = "medium"  # 設置默認值
    barking_acceptance: str = None

    def __post_init__(self):
        """在初始化後運行,用於設置派生值"""
        if self.barking_acceptance is None:
            self.barking_acceptance = self.noise_tolerance

    @staticmethod
    def calculate_breed_bonus(breed_info: dict, user_prefs: 'UserPreferences') -> float:
        """計算品種額外加分"""
        bonus = 0.0

        # 壽命加分
        try:
            lifespan = breed_info.get('Lifespan', '10-12 years')
            years = [int(x) for x in lifespan.split('-')[0].split()[0:1]]
            longevity_bonus = min(0.05, (max(years) - 10) * 0.01)
            bonus += longevity_bonus
        except:
            pass

        # 性格特徵加分
        temperament = breed_info.get('Temperament', '').lower()
        if user_prefs.has_children:
            if 'gentle' in temperament or 'patient' in temperament:
                bonus += 0.03

        # 適應性加分
        if breed_info.get('Size') == "Small" and user_prefs.living_space == "apartment":
            bonus += 0.02

        return bonus

    @staticmethod
    def calculate_additional_factors(breed_info: dict, user_prefs: 'UserPreferences') -> dict:
        """計算額外的排序因素"""
        factors = {
            'versatility': 0.0,
            'health_score': 0.0,
            'adaptability': 0.0
        }

        # 計算多功能性分數
        temperament = breed_info.get('Temperament', '').lower()
        versatile_traits = ['intelligent', 'adaptable', 'versatile', 'trainable']
        factors['versatility'] = sum(trait in temperament for trait in versatile_traits) / len(versatile_traits)

        # 計算健康分數(基於預期壽命)
        lifespan = breed_info.get('Lifespan', '10-12 years')
        try:
            years = [int(x) for x in lifespan.split('-')[0].split()[0:1]]
            factors['health_score'] = min(1.0, max(years) / 15)  # 標準化到0-1範圍
        except:
            factors['health_score'] = 0.5  # 預設值

        # 計算適應性分數
        size = breed_info.get('Size', 'Medium')
        factors['adaptability'] = {
            'Small': 0.9,
            'Medium': 0.7,
            'Large': 0.5,
            'Giant': 0.3
        }.get(size, 0.5)

        return factors


def calculate_compatibility_score(breed_info: dict, user_prefs: UserPreferences) -> dict:
    """計算品種與使用者條件的相容性分數"""
    scores = {}
    try:
        # 1. 空間相容性計算
        def calculate_space_score(size, living_space, has_yard):
            base_scores = {
                "Small": {"apartment": 0.95, "house_small": 1.0, "house_large": 0.90},
                "Medium": {"apartment": 0.65, "house_small": 0.90, "house_large": 1.0},
                "Large": {"apartment": 0.35, "house_small": 0.75, "house_large": 1.0},
                "Giant": {"apartment": 0.15, "house_small": 0.55, "house_large": 1.0}
            }

            base_score = base_scores.get(size, base_scores["Medium"])[living_space]
            adjustments = 0

            # 特殊情況調整
            if living_space == "apartment":
                if size == "Small":
                    adjustments += 0.05
                elif size in ["Large", "Giant"]:
                    adjustments -= 0.15

            if has_yard and living_space in ["house_small", "house_large"]:
                adjustments += 0.05

            return min(1.0, max(0, base_score + adjustments))

        # 2. 運動相容性計算
        def calculate_exercise_score(breed_exercise_needs, user_exercise_time):
            exercise_needs = {
                'VERY HIGH': 120,
                'HIGH': 90,
                'MODERATE': 60,
                'LOW': 30,
                'VARIES': 60
            }

            breed_need = exercise_needs.get(breed_exercise_needs.strip().upper(), 60)
            difference = abs(user_exercise_time - breed_need) / breed_need

            if difference == 0:
                return 1.0
            elif difference <= 0.2:
                return 0.95
            elif difference <= 0.4:
                return 0.85
            elif difference <= 0.6:
                return 0.70
            elif difference <= 0.8:
                return 0.50
            else:
                return 0.30

        # 3. 美容需求計算
        def calculate_grooming_score(breed_grooming_needs, user_commitment, breed_size):
            base_scores = {
                "High": {"low": 0.3, "medium": 0.7, "high": 1.0},
                "Moderate": {"low": 0.5, "medium": 0.9, "high": 1.0},
                "Low": {"low": 1.0, "medium": 0.95, "high": 0.9}
            }

            base_score = base_scores.get(breed_grooming_needs, base_scores["Moderate"])[user_commitment]

            if breed_size == "Large" and user_commitment == "low":
                base_score *= 0.80
            elif breed_size == "Giant" and user_commitment == "low":
                base_score *= 0.70

            return base_score

        # 4. 經驗等級計算
        def calculate_experience_score(care_level, user_experience, temperament):
            base_scores = {
                "High": {"beginner": 0.3, "intermediate": 0.7, "advanced": 1.0},
                "Moderate": {"beginner": 0.6, "intermediate": 0.9, "advanced": 1.0},
                "Low": {"beginner": 0.9, "intermediate": 1.0, "advanced": 1.0}
            }

            score = base_scores.get(care_level, base_scores["Moderate"])[user_experience]

            temperament_lower = temperament.lower()
            if user_experience == "beginner":
                if any(trait in temperament_lower for trait in ['stubborn', 'independent', 'intelligent']):
                    score *= 0.80
                if any(trait in temperament_lower for trait in ['easy', 'gentle', 'friendly']):
                    score *= 1.15

            return min(1.0, score)

        def calculate_health_score(breed_name: str) -> float:
            if breed_name not in breed_health_info:
                return 0.5

            health_notes = breed_health_info[breed_name]['health_notes'].lower()

            # 嚴重健康問題
            severe_conditions = [
                'cancer', 'cardiomyopathy', 'epilepsy', 'dysplasia',
                'bloat', 'progressive', 'syndrome'
            ]

            # 中等健康問題
            moderate_conditions = [
                'allergies', 'infections', 'thyroid', 'luxation',
                'skin problems', 'ear'
            ]

            severe_count = sum(1 for condition in severe_conditions if condition in health_notes)
            moderate_count = sum(1 for condition in moderate_conditions if condition in health_notes)

            health_score = 1.0
            health_score -= (severe_count * 0.1)
            health_score -= (moderate_count * 0.05)

            # 特殊條件調整
            if user_prefs.has_children:
                if 'requires frequent' in health_notes or 'regular monitoring' in health_notes:
                    health_score *= 0.9

            if user_prefs.experience_level == 'beginner':
                if 'requires frequent' in health_notes or 'requires experienced' in health_notes:
                    health_score *= 0.8

            return max(0.3, min(1.0, health_score))

        def calculate_noise_score(breed_name: str, user_noise_tolerance: str) -> float:
            if breed_name not in breed_noise_info:
                return 0.5

            noise_info = breed_noise_info[breed_name]
            noise_level = noise_info['noise_level'].lower()


            # 基礎噪音分數矩陣
            noise_matrix = {
                'low': {'low': 1.0, 'medium': 0.8, 'high': 0.6},
                'medium': {'low': 0.7, 'medium': 1.0, 'high': 0.8},
                'high': {'low': 0.4, 'medium': 0.7, 'high': 1.0}
            }

            # 從噪音矩陣獲取基礎分數
            base_score = noise_matrix.get(noise_level, {'low': 0.7, 'medium': 0.7, 'high': 0.7})[user_noise_tolerance]

            # 特殊情況調整
            special_adjustments = 0
            if user_prefs.has_children and noise_level == 'high':
                special_adjustments -= 0.1
            if user_prefs.living_space == 'apartment':
                if noise_level == 'high':
                    special_adjustments -= 0.15
                elif noise_level == 'medium':
                    special_adjustments -= 0.05

            final_score = base_score + special_adjustments
            return max(0.3, min(1.0, final_score))

        # 計算所有基礎分數
        scores = {
            'space': calculate_space_score(breed_info['Size'], user_prefs.living_space, user_prefs.space_for_play),
            'exercise': calculate_exercise_score(breed_info.get('Exercise Needs', 'Moderate'), user_prefs.exercise_time),
            'grooming': calculate_grooming_score(breed_info.get('Grooming Needs', 'Moderate'), user_prefs.grooming_commitment.lower(), breed_info['Size']),
            'experience': calculate_experience_score(breed_info.get('Care Level', 'Moderate'), user_prefs.experience_level, breed_info.get('Temperament', '')),
            'health': calculate_health_score(breed_info.get('Breed', '')),
            'noise': calculate_noise_score(breed_info.get('Breed', ''), user_prefs.noise_tolerance)
        }

        # 更新權重配置
        weights = {
            'space': 0.20,
            'exercise': 0.20,
            'grooming': 0.15,
            'experience': 0.15,
            'health': 0.15,
            'noise': 0.15
        }

        # 基礎分數計算
        base_score = sum(score * weights[category]
                        for category, score in scores.items()
                        if category != 'overall')

        # 額外調整
        adjustments = 0

        # 1. 適應性加分
        if breed_info.get('Adaptability', 'Medium') == 'High':
            adjustments += 0.02

        # 2. 氣候相容性
        if user_prefs.climate in breed_info.get('Suitable Climate', '').split(','):
            adjustments += 0.02

        # 3. 其他寵物相容性
        if user_prefs.other_pets and breed_info.get('Good with Other Pets') == 'Yes':
            adjustments += 0.02

        final_score = min(1.0, max(0, base_score + adjustments))
        scores['overall'] = round(final_score, 4)

        # 四捨五入所有分數
        for key in scores:
            scores[key] = round(scores[key], 4)

        return scores

    except Exception as e:
        print(f"Error in calculate_compatibility_score: {str(e)}")
        return {k: 0.5 for k in ['space', 'exercise', 'grooming', 'experience', 'health', 'noise', 'overall']}