from __future__ import annotations
from fastapi import APIRouter, Request, Form
from fastapi.responses import HTMLResponse, RedirectResponse
from starlette import status
from supabase import create_client
from app.web.deps import templates
from app.services import supabase_service as sps

router = APIRouter(prefix="/auth")


def _tmp_client():
    # Create a short-lived client to avoid mutating the shared client's auth state
    return create_client(sps.SUPABASE_URL, sps.SUPABASE_KEY)


def _client():
    """Default client; use site settings (anon/service)."""
    return sps.get_client()


# 허용 기관 및 이메일 도메인 매핑
ALLOWED_ORGS = {
    "공무원": "korea.kr",
    "한국전력공사": "kepco.co.kr",
    "한국남동발전": "koenergy.kr",
    "한국중부발전": "komipo.co.kr",
    "한국서부발전": "iwest.co.kr",
    "한국남부발전": "kospo.co.kr",
    "한국동서발전": "ewp.co.kr",
    "한국수력원자력": "khnp.co.kr",
    "한전KPS": "kps.co.kr",
    "한전KDN": "kdn.com",
    "한국전력기술": "kepco-enc.com",
    "한전원자력연료": "knfc.co.kr",
    "전력거래소": "kpx.or.kr",
}

from app.services.supabase_service import get_admin_emails


@router.get("/login", response_class=HTMLResponse)
async def login_page(request: Request, m: str | None = None):
    return templates.TemplateResponse(
        "auth/login.html",
        {"request": request, "message": m, "allowed_orgs": ALLOWED_ORGS},
    )


@router.get("/reset", response_class=HTMLResponse)
async def reset_page(request: Request, m: str | None = None, e: str | None = None):
    return templates.TemplateResponse(
        "auth/reset.html",
        {"request": request, "message": m, "error": e, "allowed_orgs": ALLOWED_ORGS},
    )


@router.post("/reset")
async def reset_action(request: Request, email: str = Form(...)):
    client = _client()
    try:
        # Use project Site URL redirect unless overridden in Supabase
        client.auth.reset_password_for_email(email)
        return RedirectResponse(url="/auth/reset?m=sent", status_code=status.HTTP_303_SEE_OTHER)
    except Exception:
        return RedirectResponse(url="/auth/reset?e=failed", status_code=status.HTTP_303_SEE_OTHER)


@router.post("/login")
async def login_action(request: Request, email: str = Form(...), password: str = Form(...)):
    client = _tmp_client()
    try:
        res = client.auth.sign_in_with_password({"email": email, "password": password})
        user = res.user
        if not user:
            raise RuntimeError("로그인 실패")
        meta = user.user_metadata or {}
        is_admin = (user.email or "").lower() in get_admin_emails()
        request.session["user"] = {
            "id": user.id,
            "email": user.email,
            "name": meta.get("name"),
            "org": meta.get("org"),
            "department": meta.get("department"),
            "office_phone": meta.get("office_phone"),
            "responsibility": meta.get("responsibility"),
            "role": "admin" if is_admin else "user",
        }
        # Optional: Do not persist tokens in session cookie
        return RedirectResponse(url="/", status_code=status.HTTP_303_SEE_OTHER)
    except Exception as e:
        msg = str(e) if e else ""
        err_text = "이메일 또는 비밀번호를 확인하세요."
        if "confirm" in msg.lower() or "not confirmed" in msg.lower():
            err_text = "이메일 인증 후 로그인 가능합니다. 메일함을 확인해 주세요."
        return templates.TemplateResponse(
            "auth/login.html",
            {
                "request": request,
                "error": err_text,
                "email": email,
                "allowed_orgs": ALLOWED_ORGS,
            },
            status_code=400,
        )


@router.get("/signup", response_class=HTMLResponse)
async def signup_page(request: Request, m: str | None = None):
    return templates.TemplateResponse(
        "auth/signup.html",
        {
            "request": request,
            "message": m,
            "allowed_orgs": ALLOWED_ORGS,
        },
    )


@router.post("/signup")
async def signup_action(
    request: Request,
    email: str = Form(...),
    password: str = Form(...),
    name: str = Form(...),
    department: str | None = Form(None),
    office_phone: str | None = Form(None),
    responsibility: str | None = Form(None),
    agree: str | None = Form(None),
):
    client = _tmp_client()
    # --- Validation: 허용 도메인 체크 및 기관 자동 매핑, 동의 확인 ---
    try:
        domain = email.split("@")[-1].lower().strip()
        if not agree:
            raise ValueError("안내에 동의가 필요합니다.")
        # map domain -> organization label
        org = None
        for label, allowed_domain in ALLOWED_ORGS.items():
            if domain == allowed_domain:
                org = label
                break
        if org is None:
            raise ValueError("허용된 도메인의 이메일로만 가입할 수 있습니다.")
    except Exception as e:
        return templates.TemplateResponse(
            "auth/signup.html",
            {
                "request": request,
                "error": str(e) if str(e) else "가입 정보가 올바르지 않습니다.",
                "email": email,
                "name": name,
                "department": department or "",
                "office_phone": office_phone or "",
                "responsibility": responsibility or "",
                "allowed_orgs": ALLOWED_ORGS,
            },
            status_code=400,
        )

    # --- Sign up with user metadata ---
    try:
        payload = {
            "email": email,
            "password": password,
            "options": {
                "data": {
                    "name": name,
                    "org": org,
                    "department": department or "",
                    "office_phone": office_phone or "",
                    "responsibility": responsibility or "",
                }
            },
        }
        _ = client.auth.sign_up(payload)
        return RedirectResponse(url="/auth/login?m=signup_ok", status_code=status.HTTP_303_SEE_OTHER)
    except Exception:
        return templates.TemplateResponse(
            "auth/signup.html",
            {
                "request": request,
                "error": "가입 중 오류가 발생했습니다. 이메일을 확인하거나 다른 주소를 사용해 보세요.",
                "email": email,
                "name": name,
                "department": department or "",
                "office_phone": office_phone or "",
                "responsibility": responsibility or "",
                "allowed_orgs": ALLOWED_ORGS,
            },
            status_code=400,
        )


@router.get("/logout")
async def logout(request: Request):
    request.session.pop("user", None)
    return RedirectResponse(url="/", status_code=status.HTTP_303_SEE_OTHER)
