from __future__ import annotations

import json
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

from prompt_auto_lab.core.store_dir import get_store_dir


@dataclass
class UserRecord:
    id: str
    created_at: datetime
    last_login: datetime


def _get_users_file() -> Path:
    return get_store_dir() / "users.json"


def _normalize_datetime(value: Any, *, fallback: datetime) -> datetime:
    if isinstance(value, datetime):
        return value
    if isinstance(value, str):
        raw = value.strip()
        if raw.endswith("Z"):
            raw = raw[:-1] + "+00:00"
        try:
            return datetime.fromisoformat(raw)
        except ValueError:
            return fallback
    return fallback


def _record_from_payload(payload: Any) -> UserRecord | None:
    if not isinstance(payload, dict):
        return None
    user_id = payload.get("id")
    if not isinstance(user_id, str) or not user_id.strip():
        return None

    now = datetime.now(timezone.utc)
    created_at = _normalize_datetime(payload.get("created_at"), fallback=now)
    last_login = _normalize_datetime(payload.get("last_login"), fallback=created_at)
    return UserRecord(
        id=user_id.strip(),
        created_at=created_at,
        last_login=last_login,
    )


def _record_to_payload(record: UserRecord) -> dict[str, str]:
    return {
        "id": record.id,
        "created_at": record.created_at.isoformat(),
        "last_login": record.last_login.isoformat(),
    }


def _load_users() -> dict[str, dict[str, Any]]:
    users_file = _get_users_file()
    if not users_file.exists():
        return {}
    try:
        payload = json.loads(users_file.read_text(encoding="utf-8"))
        return payload if isinstance(payload, dict) else {}
    except Exception:
        return {}


def _save_users(users: dict[str, dict[str, Any]]) -> None:
    users_file = _get_users_file()
    users_file.write_text(json.dumps(users, indent=2, default=str), encoding="utf-8")


def get_user_record(user_id: str) -> UserRecord | None:
    users = _load_users()
    return _record_from_payload(users.get(user_id))


def create_user_record(user_id: str) -> UserRecord:
    users = _load_users()
    if user_id in users:
        raise ValueError(f"User '{user_id}' already exists")

    now = datetime.now(timezone.utc)
    record = UserRecord(
        id=user_id,
        created_at=now,
        last_login=now,
    )
    users[user_id] = _record_to_payload(record)
    _save_users(users)

    user_dir = get_user_dir(user_id)
    user_dir.mkdir(parents=True, exist_ok=True)
    (user_dir / "sessions").mkdir(parents=True, exist_ok=True)
    return record


def login_user_record(user_id: str) -> UserRecord:
    users = _load_users()
    now = datetime.now(timezone.utc)
    existing = _record_from_payload(users.get(user_id))
    if existing is None:
        return create_user_record(user_id)

    updated = UserRecord(
        id=existing.id,
        created_at=existing.created_at,
        last_login=now,
    )
    users[user_id] = _record_to_payload(updated)
    _save_users(users)
    return updated


def ensure_user_record(user_id: str) -> UserRecord:
    record = get_user_record(user_id)
    if record is not None:
        return record
    return create_user_record(user_id)


def get_user_dir(user_id: str) -> Path:
    return get_store_dir() / "users" / user_id


def get_user_sessions_file(user_id: str) -> Path:
    user_dir = get_user_dir(user_id)
    user_dir.mkdir(parents=True, exist_ok=True)
    return user_dir / "sessions.json"


def get_user_session_dir(user_id: str, session_id: str) -> Path:
    return get_user_dir(user_id) / "sessions" / session_id

