from django.utils import timezone

from .models import SiteConfiguration, Partner, SocialMediaLink, CarouselSlide, ProgramStatistic
from apps.universities.models import University
from apps.news.models import NewsArticle, NewsCategory, Event
from apps.team.models import Person, Professor, PhDStudent, MasterStudent
from apps.research.models import ResearchArea, ResearchProject
from apps.program.models import (
    ApplicationCall, Scholarship, AdmissionRequirement,
    FAQItem, ApplicationTimeline, Program
)
from traduction.helpers import prefetch_translations


class SettingsProxy:
    """
    Proxy pour acceder aux parametres CMS comme des attributs.

    Permet d'utiliser settings.site_name au lieu de Setting.get('site-name').
    Compatible avec le systeme de traduction.

    Mapping des anciens noms (SiteConfiguration) vers les nouveaux slugs (Setting):
        site_name -> site-name
        tagline -> site-tagline
        phone -> site-phone
        email -> site-email
        address -> site-address
        facebook_url -> social-facebook
        twitter_url -> social-twitter
        linkedin_url -> social-linkedin
        youtube_url -> social-youtube
        meta_description -> seo-meta-description
        meta_keywords -> seo-meta-keywords
    """

    # Mapping attribut -> slug (pour compatibilite avec SiteConfiguration)
    SLUG_MAPPING = {
        'site_name': 'site-name',
        'tagline': 'site-tagline',
        'phone': 'site-phone',
        'email': 'site-email',
        'address': 'site-address',
        'facebook_url': 'social-facebook',
        'twitter_url': 'social-twitter',
        'linkedin_url': 'social-linkedin',
        'youtube_url': 'social-youtube',
        'instagram_url': 'social-instagram',
        'meta_description': 'seo-meta-description',
        'meta_keywords': 'seo-meta-keywords',
    }

    def __init__(self, language_code=None):
        self._cache = {}
        self._language_code = language_code
        self._loaded = False

    def _load_settings(self):
        """Charge tous les settings en une seule requete."""
        if self._loaded:
            return

        from cms.models import Setting
        from traduction.helpers import prefetch_translations

        settings = Setting.objects.filter(is_active=True).select_related('type')

        # Prefetch des traductions si langue specifiee
        if self._language_code:
            prefetch_translations(list(settings), language_code=self._language_code)

        for setting in settings:
            # Stocker par slug
            self._cache[setting.slug] = setting
            # Stocker aussi par attribut mappe (pour compatibilite)
            for attr, slug in self.SLUG_MAPPING.items():
                if slug == setting.slug:
                    self._cache[attr] = setting

        self._loaded = True

    def __getattr__(self, name):
        """Acces aux settings comme attributs."""
        if name.startswith('_'):
            raise AttributeError(name)

        self._load_settings()

        # Convertir underscore en tiret si necessaire
        slug = self.SLUG_MAPPING.get(name, name.replace('_', '-'))

        if slug in self._cache:
            setting = self._cache[slug]
            # Essayer d'obtenir la traduction
            if hasattr(setting, 'get_translated'):
                translated = setting.get_translated('value')
                if translated:
                    return translated
            return setting.get_raw_value()

        if name in self._cache:
            setting = self._cache[name]
            if hasattr(setting, 'get_translated'):
                translated = setting.get_translated('value')
                if translated:
                    return translated
            return setting.get_raw_value()

        return ''

    def get(self, slug, default=''):
        """Acces explicite a un setting par slug."""
        self._load_settings()
        if slug in self._cache:
            return self._cache[slug].get_raw_value() or default
        return default

    def get_formatted(self, slug, default=''):
        """Acces a la valeur formatee d'un setting."""
        self._load_settings()
        if slug in self._cache:
            return self._cache[slug].get_value() or default
        return default

    def get_image_url(self, slug):
        """Acces a l'URL de l'image d'un setting."""
        self._load_settings()
        if slug in self._cache:
            return self._cache[slug].get_image_url()
        return None

    def get_by_category(self, category):
        """Retourne tous les settings d'une categorie."""
        self._load_settings()
        return [s for s in self._cache.values()
                if hasattr(s, 'category') and s.category == category]


def _translate_articles_with_categories(articles, language_code=None):
    """
    Traduit les articles ET leurs catégories liées.
    """
    if not articles:
        return articles

    # Traduire les articles
    prefetch_translations(articles, language_code=language_code)

    # Collecter et traduire les catégories uniques
    categories = [a.category for a in articles if a.category]
    if categories:
        # Dédupliquer
        unique_categories = list({c.pk: c for c in categories}.values())
        prefetch_translations(unique_categories, language_code=language_code)

        # Mapper les catégories traduites aux articles
        cat_map = {c.pk: c for c in unique_categories}
        for article in articles:
            if article.category and article.category.pk in cat_map:
                article.category = cat_map[article.category.pk]

    return articles


def _translate_events_with_types(events, language_code=None):
    """
    Traduit les événements ET leurs types liés.
    """
    if not events:
        return events

    # Traduire les événements
    prefetch_translations(events, language_code=language_code)

    # Collecter et traduire les types uniques
    event_types = [e.event_type for e in events if e.event_type]
    if event_types:
        # Dédupliquer
        unique_types = list({t.pk: t for t in event_types}.values())
        prefetch_translations(unique_types, language_code=language_code)

        # Mapper les types traduits aux événements
        type_map = {t.pk: t for t in unique_types}
        for event in events:
            if event.event_type and event.event_type.pk in type_map:
                event.event_type = type_map[event.event_type.pk]

    return events


def _translate_single_object(obj, language_code=None):
    """
    Traduit un seul objet.
    """
    if obj:
        prefetch_translations([obj], language_code=language_code)
    return obj


def _translate_persons_with_universities(persons, language_code=None):
    """
    Traduit les personnes ET leurs universités liées.
    """
    if not persons:
        return persons

    # Traduire les personnes
    prefetch_translations(persons, language_code=language_code)

    # Collecter et traduire les universités uniques
    universities = [p.university for p in persons if p.university]
    if universities:
        unique_universities = list({u.pk: u for u in universities}.values())
        prefetch_translations(unique_universities, language_code=language_code)

        # Mapper les universités traduites aux personnes
        uni_map = {u.pk: u for u in unique_universities}
        for person in persons:
            if person.university and person.university.pk in uni_map:
                person.university = uni_map[person.university.pk]

    return persons


def site_config(request):
    """Context processor pour rendre la config du site disponible partout"""
    now = timezone.now()

    # Recuperer le code de langue courant
    language_code = getattr(request, 'current_language_code', None)

    # Proxy vers les nouveaux Settings (compatible avec les anciens attributs)
    settings_proxy = SettingsProxy(language_code=language_code)

    return {
        # Configuration du site (ancien systeme - garde pour compatibilite)
        'site_config': SiteConfiguration.get_config(),

        # Nouveau systeme de settings (utilise settings.site_name, etc.)
        'settings': settings_proxy,

        # Partenaires (avec traductions)
        'main_partner': _translate_single_object(
            Partner.objects.filter(is_main_partner=True, is_active=True).first(),
            language_code
        ),
        'partners': prefetch_translations(
            list(Partner.objects.filter(is_active=True).order_by('order')),
            language_code=language_code
        ),

        # Reseaux sociaux
        'social_links': SocialMediaLink.objects.filter(is_active=True),

        # Carousel et Stats (avec traductions)
        'carousel_slides': prefetch_translations(
            list(CarouselSlide.objects.filter(is_active=True).order_by('order')),
            language_code=language_code
        ),
        'program_stats': prefetch_translations(
            list(ProgramStatistic.objects.filter(is_active=True).order_by('order')),
            language_code=language_code
        ),

        # Universites (avec traductions)
        'universities': prefetch_translations(
            list(University.objects.filter(is_active=True).select_related('country').order_by('order')),
            language_code=language_code
        ),

        # News - Articles (avec traductions)
        'news_categories': prefetch_translations(
            list(NewsCategory.objects.filter(is_active=True).order_by('order')),
            language_code=language_code
        ),
        'latest_news': _translate_articles_with_categories(
            list(NewsArticle.objects.filter(is_published=True).select_related('category', 'author')[:6]),
            language_code=language_code
        ),
        'featured_news': _translate_articles_with_categories(
            list(NewsArticle.objects.filter(is_published=True, is_featured=True).select_related('category')[:3]),
            language_code=language_code
        ),

        # News - Evenements (avec traductions)
        'upcoming_events': _translate_events_with_types(
            list(Event.objects.filter(
                is_active=True,
                event_date__gte=now
            ).select_related('event_type', 'host_university').order_by('event_date')[:6]),
            language_code=language_code
        ),
        'featured_events': _translate_events_with_types(
            list(Event.objects.filter(
                is_active=True,
                is_featured=True,
                event_date__gte=now
            ).select_related('event_type')[:3]),
            language_code=language_code
        ),

        # Team - Direction (coordinateurs et directeurs) avec traductions
        'directors': _translate_persons_with_universities(
            list(Person.objects.filter(
                is_active=True,
                is_director=True
            ).select_related('university').order_by('order')[:6]),
            language_code=language_code
        ),
        'coordinators': _translate_persons_with_universities(
            list(Person.objects.filter(
                is_active=True,
                is_coordinator=True
            ).select_related('university').order_by('order')),
            language_code=language_code
        ),

        # Team - Professeurs avec traductions
        'professors': _translate_persons_with_universities(
            list(Person.objects.filter(
                is_active=True,
                person_type='professor'
            ).select_related('university', 'professor').order_by('order')[:8]),
            language_code=language_code
        ),

        # Team - Doctorants avec traductions
        'phd_students': _translate_persons_with_universities(
            list(Person.objects.filter(
                is_active=True,
                person_type='phd'
            ).select_related('university', 'phd_student').order_by('order')[:8]),
            language_code=language_code
        ),

        # Team - Etudiants Master avec traductions
        'master_students': _translate_persons_with_universities(
            list(Person.objects.filter(
                is_active=True,
                person_type='master'
            ).select_related('university', 'master_student').order_by('order')[:8]),
            language_code=language_code
        ),

        # Team - Featured avec traductions
        'featured_team': _translate_persons_with_universities(
            list(Person.objects.filter(
                is_active=True,
                is_featured=True
            ).select_related('university').order_by('order')[:6]),
            language_code=language_code
        ),

        # Research avec traductions
        'research_areas': prefetch_translations(
            list(ResearchArea.objects.filter(is_active=True).order_by('order')),
            language_code=language_code
        ),
        'featured_projects': prefetch_translations(
            list(ResearchProject.objects.filter(
                is_active=True,
                is_featured=True
            ).select_related('research_area', 'university')[:6]),
            language_code=language_code
        ),
        'active_projects': prefetch_translations(
            list(ResearchProject.objects.filter(
                is_active=True,
                status='active'
            ).select_related('research_area', 'university').order_by('order')[:6]),
            language_code=language_code
        ),

        # =====================================================================
        # Programme et Candidature (disponible globalement)
        # =====================================================================

        # Programme principal
        'program': _translate_single_object(
            Program.objects.first(),
            language_code
        ),

        # Appel a candidature courant
        'current_call': _translate_single_object(
            ApplicationCall.get_current(),
            language_code
        ),
        'all_calls': prefetch_translations(
            list(ApplicationCall.objects.filter(is_active=True).order_by('-academic_year')),
            language_code=language_code
        ),

        # Bourses
        'scholarships': prefetch_translations(
            list(Scholarship.objects.filter(is_active=True).order_by('order')),
            language_code=language_code
        ),

        # Conditions d'admission
        'requirements': prefetch_translations(
            list(AdmissionRequirement.objects.filter(is_active=True).order_by('order')),
            language_code=language_code
        ),

        # Timeline de candidature
        'timeline': prefetch_translations(
            list(ApplicationTimeline.objects.all().order_by('order')[:10]),
            language_code=language_code
        ),

        # FAQs par categorie
        'faqs': prefetch_translations(
            list(FAQItem.objects.filter(is_active=True).order_by('category', 'order')),
            language_code=language_code
        ),
        'faqs_admission': prefetch_translations(
            list(FAQItem.objects.filter(is_active=True, category='admission').order_by('order')),
            language_code=language_code
        ),
        'faqs_financial': prefetch_translations(
            list(FAQItem.objects.filter(is_active=True, category='financial').order_by('order')),
            language_code=language_code
        ),
        'faqs_academic': prefetch_translations(
            list(FAQItem.objects.filter(is_active=True, category='academic').order_by('order')),
            language_code=language_code
        ),
    }
