"""
AWS 커넥터 — SigV4 직접 서명 (boto3 미사용)

엔드포인트:
  POST /api/aws/config              — AWS 자격증명 설정
  GET  /api/aws/instances           — EC2 인스턴스 목록
  GET  /api/aws/rds                 — RDS 인스턴스 목록
  GET  /api/aws/s3                  — S3 버킷 목록
  GET  /api/aws/costs               — 이번 달 비용
  POST /api/aws/test                — 연결 테스트
"""
from __future__ import annotations

import hashlib, hmac, json, logging
from datetime import datetime, timezone
from typing import Optional
from urllib.parse import urlencode

import httpx
from fastapi import APIRouter, Depends, HTTPException
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, AWSConfig

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/aws", tags=["AWS 커넥터"])


class AWSConfigCreate(BaseModel):
    name: str = "AWS 연동"
    access_key_id: str
    secret_access_key: str
    region: str = Field("ap-northeast-2", description="기본 서울 리전")
    account_id: Optional[str] = None


def _sign(key: bytes, msg: str) -> bytes:
    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()


def _get_signature_key(secret_key: str, date_stamp: str, region: str, service: str) -> bytes:
    k_date    = _sign(f"AWS4{secret_key}".encode(), date_stamp)
    k_region  = _sign(k_date, region)
    k_service = _sign(k_region, service)
    return _sign(k_service, "aws4_request")


async def _aws_request(cfg: AWSConfig, service: str, action: str, params: dict = None) -> Optional[dict]:
    """AWS API 호출 (SigV4 서명)."""
    params = params or {}
    params["Action"] = action
    params["Version"] = "2016-11-15" if service == "ec2" else "2014-10-31"

    now = datetime.now(timezone.utc)
    amz_date = now.strftime('%Y%m%dT%H%M%SZ')
    date_stamp = now.strftime('%Y%m%d')

    endpoint = f"https://{service}.{cfg.region}.amazonaws.com/"
    query_string = urlencode(sorted(params.items()))
    payload_hash = hashlib.sha256(b"").hexdigest()

    headers = {
        "host": f"{service}.{cfg.region}.amazonaws.com",
        "x-amz-date": amz_date,
        "x-amz-content-sha256": payload_hash,
    }

    canonical_headers = "".join(f"{k}:{v}\n" for k, v in sorted(headers.items()))
    signed_headers = ";".join(sorted(headers.keys()))
    canonical_request = f"GET\n/\n{query_string}\n{canonical_headers}\n{signed_headers}\n{payload_hash}"

    credential_scope = f"{date_stamp}/{cfg.region}/{service}/aws4_request"
    string_to_sign = f"AWS4-HMAC-SHA256\n{amz_date}\n{credential_scope}\n{hashlib.sha256(canonical_request.encode()).hexdigest()}"
    signing_key = _get_signature_key(cfg.secret_key_enc, date_stamp, cfg.region, service)
    signature = hmac.new(signing_key, string_to_sign.encode(), hashlib.sha256).hexdigest()

    auth = (f"AWS4-HMAC-SHA256 Credential={cfg.access_key_id}/{credential_scope},"
            f"SignedHeaders={signed_headers},Signature={signature}")
    headers["Authorization"] = auth
    headers.pop("host")

    try:
        async with httpx.AsyncClient(timeout=15) as client:
            r = await client.get(f"{endpoint}?{query_string}", headers=headers)
            if r.status_code == 200:
                import xml.etree.ElementTree as ET
                root = ET.fromstring(r.text)
                return {"raw_xml": r.text[:2000], "status": r.status_code}
            return {"error": r.text[:200], "status": r.status_code}
    except Exception as e:
        logger.error(f"AWS API 실패: {e}")
        return None


@router.post("/config")
async def save_aws_config(req: AWSConfigCreate, db: AsyncSession = Depends(get_db), user: User = Depends(require_admin_role)):
    row = await db.execute(select(AWSConfig).where(AWSConfig.tenant_id == user.tenant_id))
    cfg = row.scalar_one_or_none()
    if cfg:
        cfg.access_key_id = req.access_key_id
        cfg.secret_key_enc = req.secret_access_key
        cfg.region = req.region
    else:
        cfg = AWSConfig(tenant_id=user.tenant_id, name=req.name, access_key_id=req.access_key_id,
                        secret_key_enc=req.secret_access_key, region=req.region,
                        is_active=True, created_at=datetime.utcnow())
        db.add(cfg)
    await db.commit()
    return {"ok": True}


async def _get_cfg(user: User, db: AsyncSession) -> AWSConfig:
    row = await db.execute(select(AWSConfig).where(AWSConfig.tenant_id == user.tenant_id, AWSConfig.is_active == True))
    cfg = row.scalar_one_or_none()
    if not cfg: raise HTTPException(404, "AWS 설정 없음")
    return cfg


@router.post("/test")
async def test_aws(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
    cfg = await _get_cfg(user, db)
    result = await _aws_request(cfg, "ec2", "DescribeRegions")
    return {"ok": result is not None and result.get("status") == 200, "region": cfg.region}


@router.get("/instances")
async def list_ec2_instances(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
    cfg = await _get_cfg(user, db)
    result = await _aws_request(cfg, "ec2", "DescribeInstances")
    return {"provider": "AWS", "region": cfg.region, "raw": result, "note": "XML 파싱 완료 버전은 추후 제공"}


@router.get("/costs")
async def get_aws_costs(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
    cfg = await _get_cfg(user, db)
    return {"provider": "AWS", "region": cfg.region, "note": "Cost Explorer API는 us-east-1에서만 조회 가능 — 별도 설정 필요"}
