from __future__ import annotations

import hmac
import os
import subprocess
import sys
from datetime import datetime
from pathlib import Path
from typing import Any

from flask import Flask, jsonify, request


APP = Flask(__name__)

PROJECT_DIR = Path(r"D:\honghee\blog_api")
PYTHON_EXE = Path(r"C:\Users\owner\AppData\Local\Programs\Python\Python313\python.exe")
LOG_DIR = PROJECT_DIR / "storage" / "logs"
ADMIN_TOKEN = '7oINdW6WTcFHN3WNsIEs7RZ9y3cD0aQufPLyhcxJA74'

ALLOWED_ACTIONS = {
    "generate_map",
    "refresh_session",
}


def json_error(message: str, status: int = 400, **extra: Any):
    payload = {"ok": False, "message": message}
    payload.update(extra)
    return jsonify(payload), status


def log_tail(log_file: Path, line_count: int = 20) -> str:
    try:
        lines = log_file.read_text(
            encoding="utf-8",
            errors="replace",
        ).splitlines()
        return "\n".join(lines[-line_count:])
    except Exception:
        return ""


def validate_request() -> tuple[str, int] | tuple[None, None]:
    supplied_token = request.headers.get("X-Admin-Token", "")
    if not supplied_token or not hmac.compare_digest(supplied_token, ADMIN_TOKEN):
        return None, None

    data = request.get_json(silent=True) or {}
    action = str(data.get("action") or "").strip()
    realtor_id = int(data.get("realtor_id") or 0)

    if action not in ALLOWED_ACTIONS:
        raise ValueError("허용되지 않은 작업입니다.")

    if realtor_id <= 0:
        raise ValueError("realtor_id 값이 올바르지 않습니다.")

    return action, realtor_id


def build_command(action: str, realtor_id: int) -> tuple[list[str], dict[str, str], Path]:
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    env = os.environ.copy()

    if action == "generate_map":
        script = PROJECT_DIR / "tools" / "generate_realtor_naver_map.py"
        log_file = LOG_DIR / f"realtor_map_manual_{realtor_id}_{timestamp}.log"
        env["KAKAO_REST_API_KEY"] = "017c0f4899486c08e0275d7122ae54d7"
        command = [
            str(PYTHON_EXE),
            str(script),
            "--realtor-id",
            str(realtor_id),
        ]
        return command, env, log_file

    script = PROJECT_DIR / "workers" / "naver_session_check_worker.py"
    log_file = LOG_DIR / f"naver_session_manual_{realtor_id}_{timestamp}.log"
    command = [
        str(PYTHON_EXE),
        str(script),
        "--realtor-id",
        str(realtor_id),
        "--auto-relogin",
        "--headful",
    ]
    return command, env, log_file


@APP.get("/health")
def health():
    return jsonify({
        "ok": True,
        "service": "MaemulHOME Admin Task API",
        "python": str(PYTHON_EXE),
        "project_dir": str(PROJECT_DIR),
    })


@APP.post("/api/admin/realtor-task")
def run_realtor_task():
    try:
        validated = validate_request()
    except (TypeError, ValueError) as exc:
        return json_error(str(exc), 400)

    if validated == (None, None):
        return json_error("인증 토큰이 올바르지 않습니다.", 403)

    action, realtor_id = validated

    if not PYTHON_EXE.is_file():
        return json_error(
            f"Python 실행파일을 찾을 수 없습니다: {PYTHON_EXE}",
            500,
        )

    LOG_DIR.mkdir(parents=True, exist_ok=True)

    command, env, log_file = build_command(action, realtor_id)
    script_path = Path(command[1])

    if not script_path.is_file():
        return json_error(
            f"실행 스크립트를 찾을 수 없습니다: {script_path}",
            500,
        )

    try:
        with log_file.open("w", encoding="utf-8") as log_handle:
            completed = subprocess.run(
                command,
                cwd=str(PROJECT_DIR),
                env=env,
                stdout=log_handle,
                stderr=subprocess.STDOUT,
                text=True,
                timeout=900,
                check=False,
                creationflags=(
                    subprocess.CREATE_NEW_CONSOLE
                    if action == "refresh_session" and sys.platform == "win32"
                    else 0
                ),
            )
    except subprocess.TimeoutExpired:
        return json_error(
            "Python 작업이 15분 제한시간을 초과했습니다.",
            504,
            log_file=str(log_file),
            log_tail=log_tail(log_file),
        )
    except Exception as exc:
        return json_error(
            f"Python 작업 실행 중 오류: {exc}",
            500,
            log_file=str(log_file),
        )

    if completed.returncode != 0:
        return json_error(
            "지도 이미지 생성 실패"
            if action == "generate_map"
            else "네이버 세션 자동갱신 실패",
            500,
            exit_code=completed.returncode,
            log_file=str(log_file),
            log_tail=log_tail(log_file),
        )

    # 각 Python 스크립트가 기존 운영 로직대로 DB를 저장합니다.
    # PHP 목록은 성공 응답 후 다시 로드되어 최신 DB 값을 표시합니다.
    message = (
        "지도 이미지 생성 및 DB 저장이 완료되었습니다."
        if action == "generate_map"
        else "네이버 세션 JSON 저장 및 DB 상태 반영이 완료되었습니다."
    )

    return jsonify({
        "ok": True,
        "message": message,
        "action": action,
        "realtor_id": realtor_id,
        "log_file": str(log_file),
        "log_tail": log_tail(log_file, 8),
    })


if __name__ == "__main__":
    APP.run(
        host="0.0.0.0",
        port=9110,
        debug=False,
        threaded=True,
        use_reloader=False,
    )
