from __future__ import annotations

import json
import os
import time
from pathlib import Path

from app.config import LOCK_FILE


class WorkerLock:
    def __init__(self, path: Path = LOCK_FILE, stale_seconds: int = 600):
        self.path = path
        self.stale_seconds = stale_seconds
        self.acquired = False

    def _is_stale(self) -> bool:
        try:
            age = time.time() - self.path.stat().st_mtime
            data = json.loads(self.path.read_text(encoding='utf-8'))
            pid = int(data.get('pid', 0))
            if pid > 0:
                try:
                    os.kill(pid, 0)
                    return False
                except ProcessLookupError:
                    return True
                except PermissionError:
                    return False
            return age > self.stale_seconds
        except Exception:
            try:
                return (time.time() - self.path.stat().st_mtime) > self.stale_seconds
            except OSError:
                return True

    def acquire(self) -> bool:
        self.path.parent.mkdir(parents=True, exist_ok=True)
        if self.path.exists() and self._is_stale():
            try:
                self.path.unlink()
            except OSError:
                return False
        try:
            fd = os.open(self.path, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o600)
            with os.fdopen(fd, 'w', encoding='utf-8') as handle:
                json.dump({'pid': os.getpid(), 'created_at': time.time()}, handle)
            self.acquired = True
            return True
        except FileExistsError:
            return False

    def release(self) -> None:
        if self.acquired:
            try:
                self.path.unlink(missing_ok=True)
            finally:
                self.acquired = False

    def __enter__(self):
        if not self.acquire():
            return None
        return self

    def __exit__(self, exc_type, exc, tb):
        self.release()
