"""Thread-safe state shared between the worker thread and the menu bar UI."""

from __future__ import annotations

import threading
from dataclasses import dataclass, field
from datetime import UTC, datetime
from enum import StrEnum


class WorkerState(StrEnum):
    STARTING = "Starting..."
    IDLE = "Idle"
    WORKING = "Working"
    PAUSED = "Paused"
    STOPPED = "Stopped"
    ERROR = "Error"


@dataclass
class AppState:
    _lock: threading.Lock = field(default_factory=threading.Lock, repr=False)

    _state: WorkerState = WorkerState.STARTING
    _shards_completed: int = 0
    _earnings_cents: int = 0  # stored as integer cents; used for the held/pending payout amount
    _current_job: str | None = None
    _error_message: str | None = None
    _last_payout_sync_at: str | None = None
    _last_payout_sync_error: str | None = None

    @property
    def worker_state(self) -> WorkerState:
        with self._lock:
            return self._state

    @worker_state.setter
    def worker_state(self, value: WorkerState) -> None:
        with self._lock:
            self._state = value

    @property
    def shards_completed(self) -> int:
        with self._lock:
            return self._shards_completed

    def record_shard_completed(self) -> None:
        with self._lock:
            self._shards_completed += 1

    def set_earnings(self, dollars: float) -> None:
        """Update the currently pending payout amount from the coordinator API."""
        with self._lock:
            self._earnings_cents = round(dollars * 100)

    @property
    def earnings_dollars(self) -> float:
        with self._lock:
            return self._earnings_cents / 100.0

    @property
    def current_job(self) -> str | None:
        with self._lock:
            return self._current_job

    @current_job.setter
    def current_job(self, value: str | None) -> None:
        with self._lock:
            self._current_job = value

    @property
    def error_message(self) -> str | None:
        with self._lock:
            return self._error_message

    @error_message.setter
    def error_message(self, value: str | None) -> None:
        with self._lock:
            self._error_message = value

    def mark_payout_sync_success(self) -> None:
        with self._lock:
            self._last_payout_sync_at = datetime.now(UTC).isoformat()
            self._last_payout_sync_error = None

    def mark_payout_sync_failure(self, error: str) -> None:
        with self._lock:
            self._last_payout_sync_at = datetime.now(UTC).isoformat()
            self._last_payout_sync_error = error

    @property
    def last_payout_sync_at(self) -> str | None:
        with self._lock:
            return self._last_payout_sync_at

    @property
    def last_payout_sync_error(self) -> str | None:
        with self._lock:
            return self._last_payout_sync_error

    def payout_sync_status_line(self) -> str:
        with self._lock:
            synced_at = self._last_payout_sync_at
            error = self._last_payout_sync_error
        if error:
            return f"Sync: degraded — {error}"
        if synced_at:
            return "Sync: healthy"
        return "Sync: waiting…"

    def status_line(self) -> str:
        """Produce a single status string atomically."""
        with self._lock:
            state = self._state
            job = self._current_job
            err = self._error_message
        if state == WorkerState.WORKING:
            return f"Working{f' — {job}' if job else ''}"
        if state == WorkerState.ERROR:
            return f"Error: {err or 'unknown'}"
        return state.value
