from __future__ import annotations

from sqlalchemy import select
from sqlalchemy.orm import Session

from app.core.logging import get_logger
from app.models.employee import Employee
from app.repositories.employee import EmployeeRepository
from app.services.employee_seed import LEGACY_ORGANIZATION_UNIT_CODE_MAP

logger = get_logger("app.services.employee_directory_maintenance")


class EmployeeDirectoryMaintenance:
    """维护可能在目录初始化完成后出现的历史组织数据。"""

    def __init__(self, db: Session, repository: EmployeeRepository) -> None:
        self.db = db
        self.repository = repository
        self.tenant_id = repository.tenant_id

    def normalize_after_cache_hit(self) -> None:
        """建表与种子可缓存，外部同步产生的旧部门编码仍需持续归一化。"""
        try:
            if self.normalize_legacy_departments():
                self.db.commit()
        except Exception:
            self.db.rollback()
            logger.exception("Failed to normalize cached employee departments")
            raise

    def normalize_legacy_departments(self) -> bool:
        if not LEGACY_ORGANIZATION_UNIT_CODE_MAP:
            return False

        organizations_by_code = {
            unit.unit_code: unit for unit in self.repository.list_organization_units()
        }
        legacy_target_by_id = {
            organization.id: organizations_by_code.get(target_code)
            for legacy_code, target_code in LEGACY_ORGANIZATION_UNIT_CODE_MAP.items()
            if (organization := organizations_by_code.get(legacy_code)) is not None
        }
        if not legacy_target_by_id:
            return False

        employees = list(
            self.db.scalars(
                select(Employee).where(
                    Employee.tenant_id == self.tenant_id,
                    Employee.organization_unit_id.in_(legacy_target_by_id),
                )
            ).all()
        )
        changed = False
        for employee in employees:
            organization = legacy_target_by_id.get(employee.organization_unit_id)
            if organization is None or employee.organization_unit_id == organization.id:
                continue
            employee.organization_unit_id = organization.id
            changed = True

        self.db.flush()
        return changed
