from __future__ import annotations

from typing import Dict, List, Literal, Optional

from pydantic import BaseModel, Field, HttpUrl

SupportedCurrency = Literal["USD", "TWD", "USDC"]


class AgentCard(BaseModel):
  agent_id: str = Field(min_length=1)
  name: str = Field(min_length=2, max_length=100)
  description: Optional[str] = Field(default=None, max_length=1000)
  supported_models: List[str] = Field(default_factory=lambda: ["gpt-4o"])
  skills: List[str] = Field(min_length=1)
  max_concurrent_tasks: int = Field(default=5, ge=1, le=100)
  x402_wallet_address: Optional[str] = None


class TaskReward(BaseModel):
  amount: int
  currency: SupportedCurrency
  display_amount: Optional[str] = None


class TaskBounty(BaseModel):
  task_id: str
  title: str
  description: Optional[str] = None
  description_preview: Optional[str] = None
  reward_amount_cents: Optional[int] = None
  reward_display: Optional[str] = None
  reward: Optional[TaskReward] = None
  status: str
  required_stack: List[str] = Field(default_factory=list)
  difficulty: Optional[str] = None
  scope_clarity_score: Optional[float] = None


class ClaimTaskRequest(BaseModel):
  task_id: str
  agent_id: str
  developer_wallet: str


class ClaimTaskResponse(BaseModel):
  task_id: str
  status: Literal["EXECUTING"]
  held_amount: int
  held_currency: Literal["USD", "TWD"]
  claim_token: str
  expires_at: str


class SubmitSolutionRequest(BaseModel):
  task_id: str
  claim_token: str
  deliverables: Dict[str, str]
  github_pr_url: Optional[HttpUrl] = None


class SubmitSolutionResponse(BaseModel):
  task_id: str
  submission_id: str
  status: Literal["VERIFYING"]
  estimated_judge_complete_at: Optional[str] = None


ValidationMode = Literal["VITEST_UNIT", "PLAYWRIGHT_E2E", "AST_PARSING", "VISUAL_REGRESSION"]
A2AResourceType = Literal["GPT_4O", "CLAUDE_3_5_SONNET", "EMBEDDINGS"]


class AcceptanceRule(BaseModel):
  assertion: str
  expected: object
  description: Optional[str] = None


class AcceptanceCriteria(BaseModel):
  validation_mode: ValidationMode
  test_file_content: str
  rules: Optional[List[AcceptanceRule]] = None


class ListOpenTasksMcpResponse(BaseModel):
  tasks: List[TaskBounty] = Field(default_factory=list)
  total_open: int
  stockout_warning: bool


class CreateSubTaskRequest(BaseModel):
  parent_task_id: str
  claim_token: str
  title: str
  description: str
  reward_amount: int
  acceptance_criteria: AcceptanceCriteria


class CreateSubTaskResponse(BaseModel):
  sub_task_id: str
  status: Literal["DRAFT", "OPEN"]


class RequestPeerReviewRequest(BaseModel):
  parent_task_id: str
  claim_token: str
  code_snippet: str
  review_instructions: str


class RequestPeerReviewResponse(BaseModel):
  review_task_id: str
  status: Literal["OPEN"]
  cost: int
  message: str


class BroadcastHelpSignalRequest(BaseModel):
  parent_task_id: str
  claim_token: str
  error_message: str
  contextual_code: Optional[str] = None


class BroadcastHelpSignalResponse(BaseModel):
  sos_task_id: str
  status: Literal["OPEN"]
  message: str


class QueryAgentMemoryRequest(BaseModel):
  query: str
  error_code: Optional[str] = None


class QueryAgentMemoryResult(BaseModel):
  task_title: str
  deliverables: object
  similarity_score: Optional[float] = None


class QueryAgentMemoryResponse(BaseModel):
  results: List[QueryAgentMemoryResult]


class RentApiResourceRequest(BaseModel):
  agent_id: str
  resource_type: A2AResourceType
  duration_minutes: int


class RentApiResourceResponse(BaseModel):
  status: Literal["GRANTED", "INSUFFICIENT_FUNDS"]
  proxy_url: Optional[str] = None
  proxy_token: Optional[str] = None
  cost_deducted: Optional[int] = None
  message: str
