from __future__ import annotations

from sqlalchemy import or_
from sqlalchemy.orm import Session, joinedload

from ..database.orm import DepartmentORM, PositionORM


class OrganizationRepository:
    """组织架构仓库：封装部门和岗位表的读写。"""

    def __init__(self, session: Session):
        self.session = session

    def list_departments(self, *, active_only: bool = False, keyword: str | None = None) -> list[DepartmentORM]:
        query = self.session.query(DepartmentORM)
        if active_only:
            query = query.filter(DepartmentORM.is_active.is_(True))
        if keyword:
            like_keyword = f"%{keyword}%"
            query = query.filter(
                or_(
                    DepartmentORM.department_code.like(like_keyword),
                    DepartmentORM.name.like(like_keyword),
                )
            )
        return query.order_by(DepartmentORM.sort_order.asc(), DepartmentORM.id.asc()).all()

    def create_department(
        self,
        *,
        parent_id: int | None,
        department_code: str,
        name: str,
        sort_order: int,
        is_active: bool,
        remark: str,
    ) -> DepartmentORM:
        department = DepartmentORM(
            parent_id=parent_id,
            department_code=department_code,
            name=name,
            sort_order=sort_order,
            is_active=is_active,
            remark=remark,
        )
        self.session.add(department)
        self.session.commit()
        self.session.refresh(department)
        return department

    def update_department(
        self,
        department_id: int,
        *,
        parent_id: int | None,
        department_code: str,
        name: str,
        sort_order: int,
        is_active: bool,
        remark: str,
    ) -> DepartmentORM:
        department = self.require_department(department_id)
        department.parent_id = parent_id
        department.department_code = department_code
        department.name = name
        department.sort_order = sort_order
        department.is_active = is_active
        department.remark = remark
        self.session.commit()
        self.session.refresh(department)
        return department

    def require_department(self, department_id: int) -> DepartmentORM:
        department = self.session.query(DepartmentORM).filter(DepartmentORM.id == department_id).one_or_none()
        if department is None:
            raise ValueError("部门不存在")
        return department

    def get_department_by_name(self, name: str) -> DepartmentORM | None:
        return self.session.query(DepartmentORM).filter(DepartmentORM.name == name).one_or_none()

    def get_department_by_code(self, department_code: str) -> DepartmentORM | None:
        return (
            self.session.query(DepartmentORM)
            .filter(DepartmentORM.department_code == department_code)
            .one_or_none()
        )

    def list_positions(
        self,
        *,
        department_id: int | None = None,
        active_only: bool = False,
        keyword: str | None = None,
    ) -> list[PositionORM]:
        query = self.session.query(PositionORM).join(PositionORM.department).options(joinedload(PositionORM.department))
        if department_id:
            query = query.filter(PositionORM.department_id == department_id)
        if active_only:
            query = query.filter(PositionORM.is_active.is_(True))
        if keyword:
            like_keyword = f"%{keyword}%"
            query = query.filter(
                or_(
                    PositionORM.position_code.like(like_keyword),
                    PositionORM.name.like(like_keyword),
                )
            )
        return query.order_by(
            DepartmentORM.sort_order.asc(),
            PositionORM.sort_order.asc(),
            PositionORM.id.asc(),
        ).all()

    def create_position(
        self,
        *,
        department_id: int,
        position_code: str,
        name: str,
        sort_order: int,
        is_active: bool,
        remark: str,
    ) -> PositionORM:
        position = PositionORM(
            department_id=department_id,
            position_code=position_code,
            name=name,
            sort_order=sort_order,
            is_active=is_active,
            remark=remark,
        )
        self.session.add(position)
        self.session.commit()
        return self.require_position(position.id)

    def update_position(
        self,
        position_id: int,
        *,
        department_id: int,
        position_code: str,
        name: str,
        sort_order: int,
        is_active: bool,
        remark: str,
    ) -> PositionORM:
        position = self.require_position(position_id)
        position.department_id = department_id
        position.position_code = position_code
        position.name = name
        position.sort_order = sort_order
        position.is_active = is_active
        position.remark = remark
        self.session.commit()
        return self.require_position(position_id)

    def require_position(self, position_id: int) -> PositionORM:
        position = (
            self.session.query(PositionORM)
            .options(joinedload(PositionORM.department))
            .filter(PositionORM.id == position_id)
            .one_or_none()
        )
        if position is None:
            raise ValueError("岗位不存在")
        return position

    def get_position_by_code(self, position_code: str) -> PositionORM | None:
        return (
            self.session.query(PositionORM)
            .options(joinedload(PositionORM.department))
            .filter(PositionORM.position_code == position_code)
            .one_or_none()
        )

    def get_position_by_department_and_name(self, department_id: int, name: str) -> PositionORM | None:
        """按部门和岗位名称查询，用于避免同一部门下重复维护同名岗位。"""
        return (
            self.session.query(PositionORM)
            .options(joinedload(PositionORM.department))
            .filter(PositionORM.department_id == department_id, PositionORM.name == name)
            .one_or_none()
        )
