"""
Management command to assign managers (report_to) to staff members.

This command assigns department heads as managers for staff in their department.
For staff without a department head, it assigns the first available manager.
"""
from django.core.management.base import BaseCommand
from django.db import transaction
from apps.organizations.models import Staff, Department


class Command(BaseCommand):
    help = 'Assign managers (report_to) to staff members who do not have one assigned'

    def add_arguments(self, parser):
        parser.add_argument(
            '--dry-run',
            action='store_true',
            dest='dry_run',
            default=False,
            help='Show what would be done without making changes',
        )
        parser.add_argument(
            '--hospital-id',
            dest='hospital_id',
            default=None,
            help='Only process staff for a specific hospital ID',
        )

    def handle(self, *args, **options):
        dry_run = options['dry_run']
        hospital_id = options['hospital_id']
        
        # Get staff without managers
        staff_queryset = Staff.objects.filter(report_to__isnull=True, status='active')
        
        if hospital_id:
            staff_queryset = staff_queryset.filter(hospital_id=hospital_id)
        
        staff_without_managers = staff_queryset.select_related('department', 'hospital')
        
        if not staff_without_managers.exists():
            self.stdout.write(self.style.SUCCESS('All staff members already have managers assigned.'))
            return
        
        self.stdout.write(f'Found {staff_without_managers.count()} staff members without managers.')
        
        assigned_count = 0
        skipped_count = 0
        
        for staff in staff_without_managers:
            manager = self._find_manager_for_staff(staff)
            
            if manager:
                if dry_run:
                    self.stdout.write(f'  [DRY RUN] Would assign: {staff} -> manager: {manager}')
                else:
                    staff.report_to = manager
                    staff.save(update_fields=['report_to'])
                    self.stdout.write(self.style.SUCCESS(f'  Assigned: {staff} -> manager: {manager}'))
                assigned_count += 1
            else:
                self.stdout.write(self.style.WARNING(f'  No manager found for: {staff} (Dept: {staff.department})'))
                skipped_count += 1
        
        if dry_run:
            self.stdout.write(self.style.WARNING(f'\n[DRY RUN] Would assign {assigned_count} managers, skip {skipped_count}'))
        else:
            self.stdout.write(self.style.SUCCESS(f'\nAssigned managers to {assigned_count} staff members.'))
            if skipped_count > 0:
                self.stdout.write(self.style.WARNING(f'Could not find managers for {skipped_count} staff members.'))

    def _find_manager_for_staff(self, staff):
        """Find an appropriate manager for a staff member."""
        
        # Strategy 1: Find another staff member in the same department who has people reporting to them
        if staff.department:
            dept_managers = Staff.objects.filter(
                department=staff.department,
                status='active',
                direct_reports__isnull=False
            ).exclude(id=staff.id).distinct()
            
            if dept_managers.exists():
                return dept_managers.first()
            
            # Strategy 2: Find any staff member with a higher job title in the same department
            # Look for staff with "Manager", "Director", "Head", "Chief", "Supervisor" in job title
            manager_titles = ['manager', 'director', 'head', 'chief', 'supervisor', 'lead', 'senior']
            for title in manager_titles:
                potential_managers = Staff.objects.filter(
                    department=staff.department,
                    status='active',
                    job_title__icontains=title
                ).exclude(id=staff.id)
                
                if potential_managers.exists():
                    return potential_managers.first()
        
        # Strategy 3: Find any manager in the same hospital
        hospital_managers = Staff.objects.filter(
            hospital=staff.hospital,
            status='active',
            direct_reports__isnull=False
        ).exclude(id=staff.id).distinct()
        
        if hospital_managers.exists():
            return hospital_managers.first()
        
        # Strategy 4: Find any senior staff in the same hospital
        manager_titles = ['manager', 'director', 'head', 'chief', 'supervisor', 'lead']
        for title in manager_titles:
            potential_managers = Staff.objects.filter(
                hospital=staff.hospital,
                status='active',
                job_title__icontains=title
            ).exclude(id=staff.id)
            
            if potential_managers.exists():
                return potential_managers.first()
        
        return None
