"""
ERP / 그룹웨어 연동 커넥터

기능:
  - 그룹웨어 전자결재 연동 (결재 요청 → GUARDiA SR 생성)
  - ERP HR 데이터 동기화 (사용자 조직 정보)
  - 범용 REST API 커넥터 (설정 기반)

엔드포인트:
  POST /api/erp/config               — ERP 연동 설정
  GET  /api/erp/config               — 설정 조회
  POST /api/erp/test                 — 연결 테스트
  POST /api/erp/webhook              — ERP 웹훅 수신 (결재 알림)
  POST /api/erp/sync-users           — HR 사용자 동기화
  GET  /api/erp/org-chart            — 조직도 조회
"""
from __future__ import annotations

import logging
from datetime import datetime
from typing import Optional

import httpx
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Request
from pydantic import BaseModel, Field
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from core.auth import get_current_user, require_admin_role
from database import get_db
from models import User, UserRole, SRRequest, SRStatus, ERPConfig  # 신규

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/erp", tags=["ERP 연동"])


class ERPConfigCreate(BaseModel):
    name: str = Field(..., max_length=100, description="시스템명 (예: 나라장터, 그룹웨어)")
    base_url: str
    api_key: Optional[str] = None
    username: Optional[str] = None
    password: Optional[str] = None
    erp_type: str = Field("generic", description="groupware | nara | hr | generic")


@router.post("/config")
async def save_erp_config(
    req: ERPConfigCreate, db: AsyncSession = Depends(get_db),
    user: User = Depends(require_admin_role),
):
    cfg = ERPConfig(
        tenant_id=user.tenant_id, name=req.name, base_url=req.base_url,
        api_key_enc=req.api_key, username=req.username, password_enc=req.password,
        erp_type=req.erp_type, is_active=True, created_at=datetime.utcnow()
    )
    db.add(cfg)
    await db.commit()
    await db.refresh(cfg)
    return {"ok": True, "id": cfg.id}


@router.get("/config")
async def list_erp_configs(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
    rows = await db.execute(select(ERPConfig).where(ERPConfig.tenant_id == user.tenant_id, ERPConfig.is_active == True))
    cfgs = rows.scalars().all()
    return [{"id": c.id, "name": c.name, "erp_type": c.erp_type, "base_url": c.base_url[:30] + "..."} for c in cfgs]


@router.post("/test/{config_id}")
async def test_erp(config_id: int, db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
    row = await db.execute(select(ERPConfig).where(ERPConfig.id == config_id, ERPConfig.tenant_id == user.tenant_id))
    cfg = row.scalar_one_or_none()
    if not cfg: raise HTTPException(404, "설정 없음")
    try:
        headers = {"Authorization": f"Bearer {cfg.api_key_enc}"} if cfg.api_key_enc else {}
        async with httpx.AsyncClient(timeout=10, verify=False) as c:
            r = await c.get(cfg.base_url, headers=headers)
            return {"ok": r.status_code < 400, "status_code": r.status_code}
    except Exception as e:
        return {"ok": False, "error": str(e)}


@router.post("/webhook")
async def erp_webhook(request: Request, background_tasks: BackgroundTasks,
                       db: AsyncSession = Depends(get_db)):
    """ERP 웹훅 수신 — 결재 요청 → SR 자동 생성."""
    body = await request.json()
    event_type = body.get("event_type", "")
    title = body.get("title") or body.get("subject") or "ERP 연동 요청"
    description = body.get("description") or body.get("content") or json_to_str(body)

    if event_type in ("APPROVAL_REQUEST", "WORK_ORDER", "MAINTENANCE_REQUEST"):
        sr = SRRequest(
            title=f"[ERP] {title[:100]}",
            description=description[:1000],
            category="ERP", priority="MEDIUM",
            status=SRStatus.OPEN, created_at=datetime.utcnow(),
        )
        db.add(sr)
        await db.commit()
        return {"ok": True, "sr_id": sr.id}

    return {"ok": True, "skipped": True}


@router.post("/sync-users/{config_id}")
async def sync_hr_users(
    config_id: int, db: AsyncSession = Depends(get_db),
    user: User = Depends(require_admin_role),
):
    """ERP HR → GUARDiA 사용자 동기화."""
    row = await db.execute(select(ERPConfig).where(ERPConfig.id == config_id, ERPConfig.tenant_id == user.tenant_id))
    cfg = row.scalar_one_or_none()
    if not cfg: raise HTTPException(404, "설정 없음")

    try:
        headers = {"Authorization": f"Bearer {cfg.api_key_enc}"} if cfg.api_key_enc else {}
        async with httpx.AsyncClient(timeout=15, verify=False) as c:
            r = await c.get(f"{cfg.base_url}/users", headers=headers)
            if r.status_code != 200:
                raise HTTPException(400, "HR API 응답 오류")
            hr_users = r.json().get("users", r.json() if isinstance(r.json(), list) else [])
    except Exception as e:
        raise HTTPException(500, f"HR 연결 실패: {e}")

    synced = 0
    for hr_user in hr_users:
        email = hr_user.get("email") or hr_user.get("mail")
        name = hr_user.get("name") or hr_user.get("displayName")
        if not email: continue
        existing = await db.execute(select(User).where(User.email == email))
        u = existing.scalar_one_or_none()
        if u:
            if name: u.name = name
            synced += 1

    await db.commit()
    return {"ok": True, "synced": synced, "total_hr": len(hr_users)}


@router.get("/org-chart/{config_id}")
async def get_org_chart(
    config_id: int, db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user),
):
    row = await db.execute(select(ERPConfig).where(ERPConfig.id == config_id, ERPConfig.tenant_id == user.tenant_id))
    cfg = row.scalar_one_or_none()
    if not cfg: raise HTTPException(404, "설정 없음")
    try:
        headers = {"Authorization": f"Bearer {cfg.api_key_enc}"} if cfg.api_key_enc else {}
        async with httpx.AsyncClient(timeout=15, verify=False) as c:
            r = await c.get(f"{cfg.base_url}/org-chart", headers=headers)
            return r.json() if r.status_code == 200 else {"departments": []}
    except Exception:
        return {"departments": []}


def json_to_str(data: dict) -> str:
    import json
    return json.dumps(data, ensure_ascii=False)[:500]
