from datetime import timedelta
from typing import Dict, Any
from fastapi import APIRouter, HTTPException
from app.core.config import settings
from app.core.security import create_token, decode_token

router = APIRouter(prefix="/auth", tags=["auth"])

@router.post("/login")
def login(payload: Dict[str, Any]):
    """
    payload:
    {
      "org_id": "<uuid>",
      "login": "<username or email>",
      "password": "<plain>"
    }
    """
    from app.db.session import get_conn

    conn = get_conn()
    try:
        cur = conn.cursor()
        cur.execute("BEGIN;")

        org_id = (payload.get("org_id") or "").strip()
        login_id = (payload.get("login") or "").strip()
        password = payload.get("password") or ""

        if not org_id or not login_id or not password:
            raise HTTPException(status_code=400, detail="org_id, login, password required")

        # RLS miatt kötelező: org kontextus beállítás
        cur.execute("SELECT set_config('app.tenant_org_id', %s, false);", (org_id,))

        # account + credential
        cur.execute(
            """
            SELECT
              a.account_id::text,
              a.org_id::text,
              a.username::text,
              a.email::text,
              c.password_hash,
              c.is_active
            FROM app.account a
            JOIN app.account_credential c ON c.account_id = a.account_id
            WHERE a.org_id = %s::uuid
              AND (a.username = %s::citext OR a.email = %s::citext)
              AND c.is_active = true
            LIMIT 1;
            """,
            (org_id, login_id, login_id),
        )

        row = cur.fetchone()
        if not row:
            raise HTTPException(status_code=401, detail="Invalid credentials")

        account_id, org_id_db, username, email, password_hash, cred_active = row

        # Jelszó ellenőrzés pgcrypto-val: crypt(plain, stored_hash) = stored_hash
        cur.execute("SELECT crypt(%s, %s) = %s;", (password, password_hash, password_hash))
        ok = cur.fetchone()[0]
        if not ok:
            raise HTTPException(status_code=401, detail="Invalid credentials")

        # MVP: role később membershipből; most fixen tenant_admin
        role_code = "tenant_admin"
        is_platform_admin = False

        access = create_token(
            {
                "sub": account_id,
                "org_id": org_id_db,
                "role": role_code,
                "is_platform_admin": is_platform_admin,
                "type": "access",
            },
            settings.JWT_SECRET,
            timedelta(minutes=settings.JWT_ACCESS_MINUTES),
        )

        refresh = create_token(
            {
                "sub": account_id,
                "org_id": org_id_db,
                "role": role_code,
                "is_platform_admin": is_platform_admin,
                "type": "refresh",
            },
            settings.JWT_SECRET,
            timedelta(days=settings.JWT_REFRESH_DAYS),
        )

        conn.commit()
        return {"access_token": access, "refresh_token": refresh, "token_type": "bearer"}
    except HTTPException:
        conn.rollback()
        raise
    except Exception as e:
        conn.rollback()
        raise HTTPException(status_code=500, detail=str(e))
    finally:
        conn.close()


@router.post("/refresh")
def refresh_token(payload: Dict[str, Any]):
    token = payload.get("refresh_token") or ""
    if not token:
        raise HTTPException(status_code=400, detail="refresh_token required")

    try:
        claims = decode_token(token, settings.JWT_SECRET)
        if claims.get("type") != "refresh":
            raise HTTPException(status_code=401, detail="Invalid refresh token type")

        access = create_token(
            {
                "sub": claims.get("sub"),
                "org_id": claims.get("org_id"),
                "role": claims.get("role"),
                "is_platform_admin": claims.get("is_platform_admin", False),
                "type": "access",
            },
            settings.JWT_SECRET,
            timedelta(minutes=settings.JWT_ACCESS_MINUTES),
        )
        return {"access_token": access, "token_type": "bearer"}
    except Exception:
        raise HTTPException(status_code=401, detail="Invalid or expired refresh token")
