"""Local-execution policy. Core decides; desktop never overrides these gates."""
from __future__ import annotations
from typing import Optional
from uuid import UUID

from src.core.exceptions import ForbiddenError, ValidationError
from src.domain.devices.models import Device, DeviceStatus
from src.domain.devices.repository import DeviceRepository
from src.domain.workspaces.repository import MembershipRepository, WorkspaceSettingsRepository


class LocalExecutionPolicy:
    """Fail-closed checks for workspace opt-in + ``codegen.run.desktop`` + an eligible device."""

    def __init__(
        self,
        *,
        devices: DeviceRepository,
        memberships: MembershipRepository,
        settings: WorkspaceSettingsRepository,
    ) -> None:
        self._devices = devices
        self._memberships = memberships
        self._settings = settings

    async def is_workspace_enabled(self, workspace_id: UUID) -> bool:
        row = await self._settings.get_or_create(workspace_id)
        return bool(row.local_execution_enabled)

    async def assert_user_may_run_local(self, workspace_id: UUID, user_id: UUID) -> None:
        if not await self.is_workspace_enabled(workspace_id):
            raise ForbiddenError("Local execution is not enabled for this workspace")
        if not await self._memberships.has_permission(workspace_id, user_id, "codegen.run.desktop"):
            raise ForbiddenError("You do not have permission to run codegen on a desktop device")

    async def resolve_device(
        self,
        *,
        workspace_id: UUID,
        user_id: UUID,
        preferred_device_id: Optional[UUID] = None,
    ) -> Device:
        await self.assert_user_may_run_local(workspace_id, user_id)
        device: Optional[Device] = None
        if preferred_device_id:
            device = await self._devices.get_by_id(preferred_device_id)
        if device is None:
            device = await self._devices.get_most_recent_active_for_user(user_id)
        if device is None or device.status != DeviceStatus.active.value:
            raise ValidationError("No active paired device is available for local execution")
        if device.user_id != user_id:
            raise ForbiddenError("Device is not owned by this user")
        membership = await self._memberships.get(workspace_id, user_id)
        if not membership:
            raise ForbiddenError("Device owner is not a member of this workspace")
        return device
