"""
員工到職流程 API (v3.1 多租戶架構)
使用關聯表方式管理部門、角色、服務
"""
from typing import List, Optional
from datetime import datetime, date
from fastapi import APIRouter, Depends, HTTPException, status, Request
from sqlalchemy.orm import Session
from pydantic import BaseModel

from app.db.session import get_db
from app.models.emp_resume import EmpResume
from app.models.emp_setting import EmpSetting
from app.models.department_member import DepartmentMember
from app.models.role import UserRoleAssignment
from app.models.emp_personal_service_setting import EmpPersonalServiceSetting
from app.models.personal_service import PersonalService
from app.schemas.response import MessageResponse
from app.services.audit_service import audit_service

router = APIRouter()


def get_current_tenant_id() -> int:
    """取得當前租戶 ID (暫時寫死為 1, 未來從 JWT token realm 取得)"""
    return 1


def get_current_user_id() -> str:
    """取得當前使用者 ID (暫時寫死, 未來從 JWT token sub 取得)"""
    return "system-admin"


# ==================== Schemas ====================

class DepartmentAssignment(BaseModel):
    """部門分配"""
    department_id: int
    position: Optional[str] = None
    membership_type: str = "permanent"  # permanent/temporary/project


class OnboardingRequest(BaseModel):
    """到職請求"""
    # 人員基本資料
    resume_id: int  # 已存在的 tenant_emp_resumes.id

    # SSO 帳號資訊
    keycloak_user_id: str  # Keycloak UUID
    keycloak_username: str  # 登入帳號

    # 任用資訊
    hire_date: date

    # 部門分配
    departments: List[DepartmentAssignment]

    # 角色分配
    role_ids: List[int]

    # 配額設定
    storage_quota_gb: int = 20
    email_quota_mb: int = 5120


# ==================== API Endpoints ====================

@router.post("/onboard", status_code=status.HTTP_201_CREATED)
def onboard_employee(
    data: OnboardingRequest,
    request: Request,
    db: Session = Depends(get_db),
):
    """
    完整員工到職流程

    執行項目:
    1. 建立員工任用設定 (tenant_emp_settings)
    2. 分配部門歸屬 (tenant_dept_members)
    3. 分配使用者角色 (tenant_user_role_assignments)
    4. 啟用所有個人化服務 (tenant_emp_personal_service_settings)

    範例:
    {
        "resume_id": 1,
        "keycloak_user_id": "550e8400-e29b-41d4-a716-446655440000",
        "keycloak_username": "wang.ming",
        "hire_date": "2026-02-20",
        "departments": [
            {"department_id": 9, "position": "資深工程師", "membership_type": "permanent"},
            {"department_id": 12, "position": "專案經理", "membership_type": "project"}
        ],
        "role_ids": [1, 2],
        "storage_quota_gb": 20,
        "email_quota_mb": 5120
    }
    """
    tenant_id = get_current_tenant_id()
    current_user = get_current_user_id()

    # Step 1: 檢查 resume 是否存在
    resume = db.query(EmpResume).filter(
        EmpResume.id == data.resume_id,
        EmpResume.tenant_id == tenant_id
    ).first()

    if not resume:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Resume ID {data.resume_id} not found"
        )

    # 檢查是否已有任用設定
    existing_setting = db.query(EmpSetting).filter(
        EmpSetting.tenant_id == tenant_id,
        EmpSetting.tenant_resume_id == data.resume_id,
        EmpSetting.is_active == True
    ).first()

    if existing_setting:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=f"Employee already onboarded (emp_code: {existing_setting.tenant_emp_code})"
        )

    # Step 2: 建立員工任用設定 (seq_no 由觸發器自動生成)
    emp_setting = EmpSetting(
        tenant_id=tenant_id,
        # seq_no 會由觸發器自動生成
        tenant_resume_id=data.resume_id,
        # tenant_emp_code 會由觸發器自動生成
        tenant_keycloak_user_id=data.keycloak_user_id,
        tenant_keycloak_username=data.keycloak_username,
        hire_at=data.hire_date,
        storage_quota_gb=data.storage_quota_gb,
        email_quota_mb=data.email_quota_mb,
        employment_status="active",
        is_active=True,
        edit_by=current_user
    )

    db.add(emp_setting)
    db.flush()  # 取得自動生成的 seq_no 和 tenant_emp_code

    # Step 3: 分配部門歸屬
    dept_count = 0
    for dept_assignment in data.departments:
        dept_member = DepartmentMember(
            tenant_id=tenant_id,
            employee_id=data.resume_id,  # 使用 resume_id 作為 employee_id
            department_id=dept_assignment.department_id,
            position=dept_assignment.position,
            membership_type=dept_assignment.membership_type,
            joined_at=datetime.utcnow(),
            assigned_by=current_user,
            is_active=True,
            edit_by=current_user
        )
        db.add(dept_member)
        dept_count += 1

    # Step 4: 分配使用者角色
    role_count = 0
    for role_id in data.role_ids:
        role_assignment = UserRoleAssignment(
            tenant_id=tenant_id,
            keycloak_user_id=data.keycloak_user_id,
            role_id=role_id,
            assigned_at=datetime.utcnow(),
            assigned_by=current_user,
            is_active=True,
            edit_by=current_user
        )
        db.add(role_assignment)
        role_count += 1

    # Step 5: 啟用所有個人化服務
    all_services = db.query(PersonalService).filter(
        PersonalService.is_active == True
    ).all()

    service_count = 0
    for service in all_services:
        # 根據服務類型設定配額
        quota_gb = data.storage_quota_gb if service.service_code == "Drive" else None
        quota_mb = data.email_quota_mb if service.service_code == "Email" else None

        service_setting = EmpPersonalServiceSetting(
            tenant_id=tenant_id,
            tenant_keycloak_user_id=data.keycloak_user_id,
            service_id=service.id,
            quota_gb=quota_gb,
            quota_mb=quota_mb,
            enabled_at=datetime.utcnow(),
            enabled_by=current_user,
            is_active=True,
            edit_by=current_user
        )
        db.add(service_setting)
        service_count += 1

    db.commit()
    db.refresh(emp_setting)

    # 審計日誌
    audit_service.log_action(
        db=db,
        tenant_id=tenant_id,
        user_id=current_user,
        action="employee_onboard",
        resource_type="tenant_emp_settings",
        resource_id=f"{tenant_id}-{emp_setting.seq_no}",
        details=f"Onboarded employee {emp_setting.tenant_emp_code} ({resume.name_tw}): "
                f"{dept_count} departments, {role_count} roles, {service_count} services",
        ip_address=request.client.host if request.client else None
    )

    return {
        "message": "Employee onboarded successfully",
        "employee": {
            "tenant_id": emp_setting.tenant_id,
            "seq_no": emp_setting.seq_no,
            "tenant_emp_code": emp_setting.tenant_emp_code,
            "keycloak_user_id": emp_setting.tenant_keycloak_user_id,
            "keycloak_username": emp_setting.tenant_keycloak_username,
            "name": resume.name_tw,
            "hire_date": emp_setting.hire_at.isoformat(),
        },
        "summary": {
            "departments_assigned": dept_count,
            "roles_assigned": role_count,
            "services_enabled": service_count,
        }
    }


@router.post("/{tenant_id}/{seq_no}/offboard")
def offboard_employee(
    tenant_id: int,
    seq_no: int,
    request: Request,
    db: Session = Depends(get_db),
):
    """
    員工離職流程

    執行項目:
    1. 軟刪除所有部門歸屬
    2. 撤銷所有使用者角色
    3. 停用所有個人化服務
    4. 設定員工狀態為 resigned
    """
    current_tenant_id = get_current_tenant_id()
    current_user = get_current_user_id()

    # 檢查租戶權限
    if tenant_id != current_tenant_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="No permission to access this tenant"
        )

    # 查詢員工任用設定
    emp_setting = db.query(EmpSetting).filter(
        EmpSetting.tenant_id == tenant_id,
        EmpSetting.seq_no == seq_no
    ).first()

    if not emp_setting:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Employee (tenant_id={tenant_id}, seq_no={seq_no}) not found"
        )

    if emp_setting.employment_status == "resigned":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Employee already resigned"
        )

    keycloak_user_id = emp_setting.tenant_keycloak_user_id
    resume_id = emp_setting.tenant_resume_id

    # Step 1: 軟刪除所有部門歸屬
    dept_members = db.query(DepartmentMember).filter(
        DepartmentMember.tenant_id == tenant_id,
        DepartmentMember.employee_id == resume_id,
        DepartmentMember.is_active == True
    ).all()

    for dm in dept_members:
        dm.is_active = False
        dm.ended_at = datetime.utcnow()
        dm.removed_by = current_user
        dm.edit_by = current_user

    # Step 2: 撤銷所有使用者角色
    role_assignments = db.query(UserRoleAssignment).filter(
        UserRoleAssignment.tenant_id == tenant_id,
        UserRoleAssignment.keycloak_user_id == keycloak_user_id,
        UserRoleAssignment.is_active == True
    ).all()

    for ra in role_assignments:
        ra.is_active = False
        ra.revoked_at = datetime.utcnow()
        ra.revoked_by = current_user
        ra.edit_by = current_user

    # Step 3: 停用所有個人化服務
    service_settings = db.query(EmpPersonalServiceSetting).filter(
        EmpPersonalServiceSetting.tenant_id == tenant_id,
        EmpPersonalServiceSetting.tenant_keycloak_user_id == keycloak_user_id,
        EmpPersonalServiceSetting.is_active == True
    ).all()

    for ss in service_settings:
        ss.is_active = False
        ss.disabled_at = datetime.utcnow()
        ss.disabled_by = current_user
        ss.edit_by = current_user

    # Step 4: 設定離職日期和狀態
    emp_setting.resign_date = date.today()
    emp_setting.employment_status = "resigned"
    emp_setting.is_active = False
    emp_setting.edit_by = current_user

    db.commit()

    # 審計日誌
    resume = emp_setting.resume
    audit_service.log_action(
        db=db,
        tenant_id=tenant_id,
        user_id=current_user,
        action="employee_offboard",
        resource_type="tenant_emp_settings",
        resource_id=f"{tenant_id}-{seq_no}",
        details=f"Offboarded employee {emp_setting.tenant_emp_code} ({resume.name_tw if resume else 'Unknown'}): "
                f"{len(dept_members)} departments removed, {len(role_assignments)} roles revoked, "
                f"{len(service_settings)} services disabled",
        ip_address=request.client.host if request.client else None
    )

    return {
        "message": "Employee offboarded successfully",
        "employee": {
            "tenant_emp_code": emp_setting.tenant_emp_code,
            "resign_date": emp_setting.resign_date.isoformat() if emp_setting.resign_date else None,
        },
        "summary": {
            "departments_removed": len(dept_members),
            "roles_revoked": len(role_assignments),
            "services_disabled": len(service_settings),
        }
    }


@router.get("/{tenant_id}/{seq_no}/status")
def get_employee_onboarding_status(
    tenant_id: int,
    seq_no: int,
    db: Session = Depends(get_db),
):
    """
    查詢員工完整的到職狀態

    回傳:
    - 員工基本資訊
    - 部門歸屬列表
    - 角色分配列表
    - 個人化服務列表
    """
    current_tenant_id = get_current_tenant_id()

    if tenant_id != current_tenant_id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="No permission to access this tenant"
        )

    emp_setting = db.query(EmpSetting).filter(
        EmpSetting.tenant_id == tenant_id,
        EmpSetting.seq_no == seq_no
    ).first()

    if not emp_setting:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Employee (tenant_id={tenant_id}, seq_no={seq_no}) not found"
        )

    resume = emp_setting.resume
    keycloak_user_id = emp_setting.tenant_keycloak_user_id

    # 查詢部門歸屬
    dept_members = db.query(DepartmentMember).filter(
        DepartmentMember.tenant_id == tenant_id,
        DepartmentMember.employee_id == emp_setting.tenant_resume_id,
        DepartmentMember.is_active == True
    ).all()

    departments = [
        {
            "department_id": dm.department_id,
            "department_name": dm.department.name if dm.department else None,
            "position": dm.position,
            "membership_type": dm.membership_type,
            "joined_at": dm.joined_at.isoformat() if dm.joined_at else None,
        }
        for dm in dept_members
    ]

    # 查詢角色分配
    role_assignments = db.query(UserRoleAssignment).filter(
        UserRoleAssignment.tenant_id == tenant_id,
        UserRoleAssignment.keycloak_user_id == keycloak_user_id,
        UserRoleAssignment.is_active == True
    ).all()

    roles = [
        {
            "role_id": ra.role_id,
            "role_name": ra.role.role_name if ra.role else None,
            "role_code": ra.role.role_code if ra.role else None,
            "assigned_at": ra.assigned_at.isoformat() if ra.assigned_at else None,
        }
        for ra in role_assignments
    ]

    # 查詢個人化服務
    service_settings = db.query(EmpPersonalServiceSetting).filter(
        EmpPersonalServiceSetting.tenant_id == tenant_id,
        EmpPersonalServiceSetting.tenant_keycloak_user_id == keycloak_user_id,
        EmpPersonalServiceSetting.is_active == True
    ).all()

    services = [
        {
            "service_id": ss.service_id,
            "service_name": ss.service.service_name if ss.service else None,
            "service_code": ss.service.service_code if ss.service else None,
            "quota_gb": ss.quota_gb,
            "quota_mb": ss.quota_mb,
            "enabled_at": ss.enabled_at.isoformat() if ss.enabled_at else None,
        }
        for ss in service_settings
    ]

    return {
        "employee": {
            "tenant_id": emp_setting.tenant_id,
            "seq_no": emp_setting.seq_no,
            "tenant_emp_code": emp_setting.tenant_emp_code,
            "name": resume.name_tw if resume else None,
            "keycloak_user_id": emp_setting.tenant_keycloak_user_id,
            "keycloak_username": emp_setting.tenant_keycloak_username,
            "hire_date": emp_setting.hire_at.isoformat() if emp_setting.hire_at else None,
            "resign_date": emp_setting.resign_date.isoformat() if emp_setting.resign_date else None,
            "employment_status": emp_setting.employment_status,
            "storage_quota_gb": emp_setting.storage_quota_gb,
            "email_quota_mb": emp_setting.email_quota_mb,
        },
        "departments": departments,
        "roles": roles,
        "services": services,
    }
