"""Canonical PEZAJOB job category taxonomy - shared across jobs, seekers, CV library, and alerts."""

from django.utils.text import slugify

CATEGORY_HELP_TEXT = 'Select the category that best describes the type of work or profession.'

# (name, slug, icon, sort_order)
PEZAJOB_JOB_CATEGORIES = [
    ('Accounting & Finance', 'accounting-finance', 'fa-calculator', 10),
    ('Administration & Office Support', 'administration-office-support', 'fa-clipboard', 20),
    ('Agriculture & Agribusiness', 'agriculture-agribusiness', 'fa-seedling', 30),
    ('Architecture, Construction & Built Environment', 'architecture-construction-built-environment', 'fa-hard-hat', 40),
    ('Arts, Design & Creative', 'arts-design-creative', 'fa-palette', 50),
    ('Aviation & Airport Services', 'aviation-airport-services', 'fa-plane', 60),
    ('Banking, Insurance & Financial Services', 'banking-insurance-financial-services', 'fa-university', 70),
    ('Business & Management', 'business-management', 'fa-briefcase', 80),
    ('Customer Service', 'customer-service', 'fa-headset', 90),
    ('Education & Training', 'education-training', 'fa-graduation-cap', 100),
    ('Engineering', 'engineering', 'fa-cogs', 110),
    ('Environment & Natural Resources', 'environment-natural-resources', 'fa-leaf', 120),
    ('Government & Public Sector', 'government-public-sector', 'fa-landmark', 130),
    ('Healthcare & Medical', 'healthcare-medical', 'fa-heartbeat', 140),
    ('Human Resources & People', 'human-resources-people', 'fa-users', 150),
    ('Information Technology & Software', 'information-technology-software', 'fa-laptop-code', 160),
    ('Legal & Compliance', 'legal-compliance', 'fa-gavel', 170),
    ('Logistics, Transport & Supply Chain', 'logistics-transport-supply-chain', 'fa-truck', 180),
    ('Manufacturing & Production', 'manufacturing-production', 'fa-industry', 190),
    ('Marketing, Communications & Public Relations', 'marketing-communications-public-relations', 'fa-bullhorn', 200),
    ('Media, Journalism & Publishing', 'media-journalism-publishing', 'fa-newspaper', 210),
    ('Mining, Minerals & Geology', 'mining-minerals-geology', 'fa-gem', 220),
    ('NGO, Development & Humanitarian', 'ngo-development-humanitarian', 'fa-hands-helping', 230),
    ('Pharmaceutical & Life Sciences', 'pharmaceutical-life-sciences', 'fa-flask', 240),
    ('Project & Programme Management', 'project-programme-management', 'fa-tasks', 250),
    ('Sales & Business Development', 'sales-business-development', 'fa-chart-line', 260),
    ('Science, Research & Laboratory', 'science-research-laboratory', 'fa-microscope', 270),
    ('Security, Safety & Emergency Services', 'security-safety-emergency-services', 'fa-shield-alt', 280),
    ('Skilled Trades & Technical', 'skilled-trades-technical', 'fa-tools', 290),
    ('Social Services & Community Work', 'social-services-community-work', 'fa-hands', 300),
    ('Sports, Fitness & Recreation', 'sports-fitness-recreation', 'fa-running', 310),
    ('Hospitality, Tourism & Travel', 'hospitality-tourism-travel', 'fa-hotel', 320),
    ('Retail & Consumer Services', 'retail-consumer-services', 'fa-store', 330),
    ('Telecommunications', 'telecommunications', 'fa-broadcast-tower', 340),
    ('Energy, Utilities & Power', 'energy-utilities-power', 'fa-bolt', 350),
    ('International Affairs & Diplomacy', 'international-affairs-diplomacy', 'fa-globe', 360),
    ('Consulting & Professional Services', 'consulting-professional-services', 'fa-user-tie', 370),
    ('Property, Facilities & Estate Management', 'property-facilities-estate-management', 'fa-building', 380),
    ('Research, Monitoring & Evaluation', 'research-monitoring-evaluation', 'fa-chart-bar', 390),
    ('Other / General', 'other-general', 'fa-ellipsis-h', 400),
]

PEZAJOB_CATEGORY_SLUGS = {slug for _name, slug, _icon, _order in PEZAJOB_JOB_CATEGORIES}

# Map legacy category slugs (seed data, imports, free-text) to canonical slugs.
LEGACY_SLUG_MAP = {
    'technology': 'information-technology-software',
    'technology-it': 'information-technology-software',
    'information-technology': 'information-technology-software',
    'it': 'information-technology-software',
    'finance': 'banking-insurance-financial-services',
    'finance-banking': 'banking-insurance-financial-services',
    'finance-accounting': 'accounting-finance',
    'healthcare': 'healthcare-medical',
    'mining': 'mining-minerals-geology',
    'mining-energy': 'energy-utilities-power',
    'agriculture': 'agriculture-agribusiness',
    'retail': 'retail-consumer-services',
    'retail-fmcg': 'retail-consumer-services',
    'general': 'other-general',
    'human-resources': 'human-resources-people',
    'legal': 'legal-compliance',
    'marketing': 'marketing-communications-public-relations',
    'sales': 'sales-business-development',
    'education': 'education-training',
}


def resolve_category_slug(slug_or_name):
    """Return a canonical category slug from a slug or display name."""
    raw = (slug_or_name or '').strip()
    if not raw:
        return 'other-general'
    slug = slugify(raw)
    if slug in PEZAJOB_CATEGORY_SLUGS:
        return slug
    if slug in LEGACY_SLUG_MAP:
        return LEGACY_SLUG_MAP[slug]
    for name, canonical_slug, _icon, _order in PEZAJOB_JOB_CATEGORIES:
        if slugify(name) == slug or name.lower() == raw.lower():
            return canonical_slug
    return slug


def numbered_category_label(category):
    """Return e.g. '15. Human Resources & People' for dropdowns and filters."""
    if hasattr(category, 'numbered_name'):
        return category.numbered_name
    number = getattr(category, 'number', 0)
    name = getattr(category, 'name', str(category))
    return f'{number}. {name}' if number else name


def category_form_choices(queryset=None):
    """Return (slug, numbered label) pairs for filter and form choice fields."""
    qs = queryset if queryset is not None else active_job_categories()
    return [(cat.slug, numbered_category_label(cat)) for cat in qs]


def active_job_categories():
    from .models import JobCategory

    return JobCategory.active()


def _model_has_number_field(model):
    return any(field.name == 'number' for field in model._meta.local_fields)


def sync_pezajob_categories(*, deactivate_unknown=True, job_category_model=None, job_model=None):
    """
    Upsert all PEZAJOB job categories and mirror them to SeekerCategory for CV library.
    Remap jobs and seeker profiles that reference legacy slugs.
    Returns counts: (job_created, job_updated, seeker_synced).

    Pass ``job_category_model`` / ``job_model`` from ``apps.get_model`` inside migrations.
    """
    from seekers.models import SeekerCategory, SeekerProfile

    if job_category_model is None or job_model is None:
        from .models import Job, JobCategory

        job_category_model = job_category_model or JobCategory
        job_model = job_model or Job
    else:
        JobCategory = job_category_model
        Job = job_model

    supports_number = _model_has_number_field(job_category_model)

    canonical_slugs = set()
    job_created = 0
    job_updated = 0

    for category_number, (name, slug, icon, sort_order) in enumerate(PEZAJOB_JOB_CATEGORIES, start=1):
        canonical_slugs.add(slug)
        defaults = {
            'name': name,
            'icon': icon,
            'sort_order': sort_order,
            'is_active': True,
        }
        if supports_number:
            defaults['number'] = category_number
        category = job_category_model.objects.filter(slug=slug).first()
        if category:
            for field, value in defaults.items():
                setattr(category, field, value)
            category.save()
            job_updated += 1
        else:
            legacy = job_category_model.objects.filter(name=name).first()
            if legacy:
                for field, value in defaults.items():
                    setattr(legacy, field, value)
                legacy.slug = slug
                legacy.save()
                category = legacy
                job_updated += 1
            else:
                category = job_category_model.objects.create(slug=slug, **defaults)
                job_created += 1

        seeker_cat = SeekerCategory.objects.filter(slug=slug).first()
        seeker_defaults = {
            'name': name,
            'icon': icon,
            'sort_order': sort_order,
            'is_active': True,
        }
        if seeker_cat:
            for field, value in seeker_defaults.items():
                setattr(seeker_cat, field, value)
            seeker_cat.save()
        else:
            legacy_seeker = SeekerCategory.objects.filter(name=name).first()
            if legacy_seeker:
                for field, value in seeker_defaults.items():
                    setattr(legacy_seeker, field, value)
                legacy_seeker.slug = slug
                legacy_seeker.save()
            else:
                SeekerCategory.objects.create(slug=slug, **seeker_defaults)

    if deactivate_unknown:
        job_category_model.objects.exclude(slug__in=canonical_slugs).update(is_active=False)
        SeekerCategory.objects.exclude(slug__in=canonical_slugs).update(is_active=False)

    category_by_slug = {
        c.slug: c for c in job_category_model.objects.filter(slug__in=canonical_slugs)
    }

    for old_slug, new_slug in LEGACY_SLUG_MAP.items():
        target = category_by_slug.get(new_slug)
        if not target:
            continue
        old_cat = job_category_model.objects.filter(slug=old_slug).first()
        if old_cat and old_cat.pk != target.pk:
            job_model.objects.filter(category=old_cat).update(category=target)
            old_cat.is_active = False
            old_cat.save(update_fields=['is_active'])

    for profile in SeekerProfile.objects.only('id', 'category', 'category_slug', 'job_category').iterator():
        canonical = resolve_category_slug(profile.category_slug or profile.category)
        cat = category_by_slug.get(canonical)
        if not cat:
            continue
        updates = {}
        if profile.job_category_id != cat.pk:
            updates['job_category'] = cat
        if profile.category != cat.name:
            updates['category'] = cat.name
        if profile.category_slug != cat.slug:
            updates['category_slug'] = cat.slug
        if updates:
            SeekerProfile.objects.filter(pk=profile.pk).update(**updates)

    return job_created, job_updated, len(canonical_slugs)
