"""Jira/Confluence 연동 — SR ↔ Jira 이슈 양방향 동기화.

환경변수:
  JIRA_BASE_URL:        Jira 인스턴스 URL (ex: http://jira.internal:8080)
  JIRA_TOKEN:           Jira API 토큰
  JIRA_PROJECT_KEY:     프로젝트 키 (ex: GUARDIA)
  CONFLUENCE_BASE_URL:  Confluence URL (ex: http://confluence.internal:8090)
  CONFLUENCE_TOKEN:     Confluence API 토큰
  CONFLUENCE_SPACE_KEY: Confluence 스페이스 키 (기본: GUARDIA)
"""
from __future__ import annotations

import logging
import os
from typing import Optional

import httpx

logger = logging.getLogger(__name__)

JIRA_BASE_URL       = os.getenv("JIRA_BASE_URL", "")
JIRA_TOKEN          = os.getenv("JIRA_TOKEN", "")
JIRA_PROJECT_KEY    = os.getenv("JIRA_PROJECT_KEY", "GUARDIA")
CONFLUENCE_BASE_URL = os.getenv("CONFLUENCE_BASE_URL", "")
CONFLUENCE_TOKEN    = os.getenv("CONFLUENCE_TOKEN", "")
CONFLUENCE_SPACE    = os.getenv("CONFLUENCE_SPACE_KEY", "GUARDIA")

_PRIORITY_MAP = {
    "CRITICAL": "Highest",
    "HIGH":     "High",
    "MEDIUM":   "Medium",
    "LOW":      "Low",
}

_STATUS_TRANSITION_MAP = {
    "IN_PROGRESS":          "In Progress",
    "COMPLETED":            "Done",
    "REJECTED":             "Closed",
    "FAILED_ROLLBACK":      "Closed",
    "PENDING_APPROVAL":     "In Review",
    "APPROVED":             "To Do",
}


def _jira_headers() -> dict:
    return {
        "Authorization": f"Bearer {JIRA_TOKEN}",
        "Content-Type": "application/json",
        "Accept": "application/json",
    }


def _confluence_headers() -> dict:
    return {
        "Authorization": f"Bearer {CONFLUENCE_TOKEN}",
        "Content-Type": "application/json",
        "Accept": "application/json",
    }


async def create_jira_issue(
    sr_id: str,
    title: str,
    description: str,
    priority: str,
) -> Optional[str]:
    """SR → Jira 이슈 생성. 성공 시 Jira 이슈 키 반환 (ex: GUARDIA-42)."""
    if not JIRA_BASE_URL or not JIRA_TOKEN:
        logger.debug("JIRA_BASE_URL/JIRA_TOKEN 미설정 — Jira 연동 스킵")
        return None

    payload = {
        "fields": {
            "project":     {"key": JIRA_PROJECT_KEY},
            "summary":     f"[{sr_id}] {title}",
            "description": description or "",
            "issuetype":   {"name": "Task"},
            "priority":    {"name": _PRIORITY_MAP.get(priority, "Medium")},
            "labels":      ["GUARDiA", "auto-sync"],
        }
    }

    try:
        async with httpx.AsyncClient(timeout=10.0) as client:
            resp = await client.post(
                f"{JIRA_BASE_URL}/rest/api/2/issue",
                headers=_jira_headers(),
                json=payload,
            )
            if resp.status_code == 201:
                key = resp.json().get("key")
                logger.info("Jira 이슈 생성: sr_id=%s jira_key=%s", sr_id, key)
                return key
            else:
                logger.warning("Jira 이슈 생성 실패: status=%d body=%s",
                               resp.status_code, resp.text[:200])
    except Exception as e:
        logger.error("Jira 연동 오류: %s", str(e)[:100])
    return None


async def get_jira_issue_status(jira_key: str) -> Optional[dict]:
    """Jira 이슈 상태 조회."""
    if not JIRA_BASE_URL or not JIRA_TOKEN:
        return None
    try:
        async with httpx.AsyncClient(timeout=10.0) as client:
            resp = await client.get(
                f"{JIRA_BASE_URL}/rest/api/2/issue/{jira_key}",
                headers=_jira_headers(),
            )
            if resp.status_code == 200:
                data = resp.json()
                fields = data.get("fields", {})
                return {
                    "jira_key":   jira_key,
                    "summary":    fields.get("summary", ""),
                    "status":     fields.get("status", {}).get("name", ""),
                    "priority":   fields.get("priority", {}).get("name", ""),
                    "assignee":   (fields.get("assignee") or {}).get("displayName", ""),
                    "updated":    fields.get("updated", ""),
                }
    except Exception as e:
        logger.error("Jira 상태 조회 오류: %s", str(e)[:100])
    return None


async def sync_jira_status(jira_key: str, guardia_status: str) -> bool:
    """GUARDiA 상태를 Jira 트랜지션으로 반영."""
    if not JIRA_BASE_URL or not JIRA_TOKEN:
        return False
    target = _STATUS_TRANSITION_MAP.get(guardia_status)
    if not target:
        return False
    try:
        async with httpx.AsyncClient(timeout=10.0) as client:
            # 트랜지션 목록 조회
            r = await client.get(
                f"{JIRA_BASE_URL}/rest/api/2/issue/{jira_key}/transitions",
                headers=_jira_headers(),
            )
            if r.status_code != 200:
                return False
            transitions = r.json().get("transitions", [])
            tid = next(
                (t["id"] for t in transitions if t["name"] == target),
                None,
            )
            if not tid:
                return False
            await client.post(
                f"{JIRA_BASE_URL}/rest/api/2/issue/{jira_key}/transitions",
                headers=_jira_headers(),
                json={"transition": {"id": tid}},
            )
        logger.info("Jira 상태 동기화: key=%s status=%s", jira_key, target)
        return True
    except Exception as e:
        logger.error("Jira 상태 동기화 오류: %s", str(e)[:100])
        return False


async def list_jira_projects() -> list:
    """연결된 Jira 프로젝트 목록 조회."""
    if not JIRA_BASE_URL or not JIRA_TOKEN:
        return []
    try:
        async with httpx.AsyncClient(timeout=10.0) as client:
            r = await client.get(
                f"{JIRA_BASE_URL}/rest/api/2/project",
                headers=_jira_headers(),
            )
            if r.status_code == 200:
                return [
                    {"key": p["key"], "name": p["name"], "id": p["id"]}
                    for p in r.json()
                ]
    except Exception as e:
        logger.error("Jira 프로젝트 목록 오류: %s", str(e)[:100])
    return []


async def create_confluence_page(
    title: str,
    content: str,
    space_key: Optional[str] = None,
) -> Optional[str]:
    """KB 문서를 Confluence 페이지로 발행. 성공 시 페이지 URL 반환."""
    if not CONFLUENCE_BASE_URL or not CONFLUENCE_TOKEN:
        logger.debug("Confluence 미설정 — 스킵")
        return None

    space = space_key or CONFLUENCE_SPACE
    storage_content = f"<p>{content.replace(chr(10), '</p><p>')}</p>"

    payload = {
        "type":  "page",
        "title": title,
        "space": {"key": space},
        "body": {
            "storage": {
                "value":          storage_content,
                "representation": "storage",
            }
        },
    }

    try:
        async with httpx.AsyncClient(timeout=15.0) as client:
            resp = await client.post(
                f"{CONFLUENCE_BASE_URL}/rest/api/content",
                headers=_confluence_headers(),
                json=payload,
            )
            if resp.status_code == 200:
                data = resp.json()
                page_id = data.get("id")
                url = f"{CONFLUENCE_BASE_URL}/pages/viewpage.action?pageId={page_id}"
                logger.info("Confluence 페이지 생성: title=%s url=%s", title, url)
                return url
            else:
                logger.warning("Confluence 페이지 생성 실패: status=%d", resp.status_code)
    except Exception as e:
        logger.error("Confluence 연동 오류: %s", str(e)[:100])
    return None
