"""HIT (Human Intelligence Task) management tools."""

import json
from datetime import datetime, timezone
from mcp.types import TextContent

from ..client import get_mturk_client, format_error, wrap_html_question


def register_tools(register):
    """Register HIT-related tools."""

    async def create_hit(args: dict) -> list[TextContent]:
        """Create a new Human Intelligence Task on MTurk."""
        try:
            client = get_mturk_client()
            params = {
                "Title": args["title"],
                "Description": args["description"],
                "Question": wrap_html_question(args["question_html"]),
                "Reward": args["reward"],
                "MaxAssignments": args.get("max_assignments", 1),
                "LifetimeInSeconds": args.get("lifetime_seconds", 86400),
                "AssignmentDurationInSeconds": args.get("assignment_duration_seconds", 3600),
                "AutoApprovalDelayInSeconds": args.get("auto_approval_delay", 259200),
            }
            if args.get("keywords"):
                params["Keywords"] = args["keywords"]

            response = client.create_hit(**params)
            hit = response["HIT"]
            result = {
                "hit_id": hit["HITId"],
                "hit_type_id": hit["HITTypeId"],
                "hit_group_id": hit.get("HITGroupId"),
                "title": hit["Title"],
                "status": hit["HITStatus"],
                "max_assignments": hit["MaxAssignments"],
                "reward": hit["Reward"],
                "creation_time": str(hit["CreationTime"]),
                "expiration": str(hit["Expiration"]),
            }
            return [TextContent(type="text", text=json.dumps(result, indent=2))]
        except Exception as e:
            return [TextContent(type="text", text=format_error(e))]

    register(
        "create_hit",
        """Creates a new Human Intelligence Task (HIT) on Amazon Mechanical Turk that workers can complete for payment.

CRITICAL: ALWAYS GET USER CONFIRMATION BEFORE CALLING THIS TOOL. Before creating any HIT, you MUST present the following details to the user and wait for explicit approval:

1. **Survey/Task Title**: What workers will see
2. **Question/Task**: The exact wording and form fields
3. **Number of workers**: How many people will respond (max_assignments)
4. **Payment per worker**: The reward amount
5. **Total cost estimate**: (reward × max_assignments) + ~20-40% MTurk fees
6. **Duration**: How long the HIT will be available

Example confirmation message:
"Before I create this HIT, here's what will happen:
- **Title**: 'Quick Survey: Pepsi or Coke?'
- **Question**: Radio buttons asking preference + optional text field for reason
- **Workers**: 1 person will answer
- **Payment**: $0.15 per response
- **Estimated total cost**: ~$0.18-0.21 (including MTurk fees)
- **Available for**: 1 hour

Should I proceed?"

Only call this tool AFTER the user confirms. This prevents accidental charges.

---

Use this tool when you need human input for tasks like surveys, data labeling, content moderation, transcription, or any task requiring human judgment. Each HIT represents a single task that one or more workers will complete.

IMPORTANT: Creating a HIT costs real money in production mode. The total cost is: reward × max_assignments + MTurk fees (20-40% depending on settings). Always verify your account balance first with get_account_balance.

The question_html parameter should contain your task's HTML form. Include form fields for worker input - the HTML will be automatically wrapped in MTurk's template with a submit button. Example:
```html
<h2>Survey Question</h2>
<p>What is your favorite color?</p>
<input type="text" name="answer" required>
```

Workers see this in the MTurk marketplace and can accept and complete it. Once submitted, use list_assignments to see responses.

Returns the hit_id which you'll need for all subsequent operations (checking status, reviewing assignments, deleting the HIT).""",
        {
            "type": "object",
            "properties": {
                "title": {
                    "type": "string",
                    "description": "Title displayed to workers in the MTurk marketplace (max 128 characters). Make it clear and descriptive so workers understand the task at a glance. Example: 'Answer a 5-question survey about shopping habits'"
                },
                "description": {
                    "type": "string",
                    "description": "Detailed description shown to workers before they accept the HIT. Explain what the task involves, approximately how long it takes, and any requirements. This helps workers decide if they want to do your task."
                },
                "question_html": {
                    "type": "string",
                    "description": "The HTML content for your task form. Include form inputs (text fields, radio buttons, checkboxes, etc.) with name attributes. Do NOT include <form> tags, <html>, <head>, or submit buttons - these are added automatically. Just provide the task content and input fields."
                },
                "reward": {
                    "type": "string",
                    "description": "Payment amount per assignment in USD as a string, e.g., '0.10' for 10 cents, '1.50' for $1.50. This is what each worker receives for completing the task. Fair pay improves response quality and speed. MTurk minimum is $0.01."
                },
                "max_assignments": {
                    "type": "integer",
                    "description": "Number of different workers who should complete this HIT. Use 1 for tasks needing one response, higher numbers (e.g., 100) for surveys or when you want multiple opinions. Each assignment is paid separately.",
                    "default": 1
                },
                "lifetime_seconds": {
                    "type": "integer",
                    "description": "How long the HIT stays in the marketplace for workers to accept (in seconds). Default is 86400 (24 hours). After this time, no new workers can accept it. Existing accepted assignments can still be completed.",
                    "default": 86400
                },
                "assignment_duration_seconds": {
                    "type": "integer",
                    "description": "Maximum time a worker has to complete the task after accepting it (in seconds). Default is 3600 (1 hour). If they don't submit in time, the assignment is released for another worker. Set based on task complexity.",
                    "default": 3600
                },
                "keywords": {
                    "type": "string",
                    "description": "Comma-separated keywords to help workers find your HIT in searches. Example: 'survey, research, quick, easy'. Good keywords increase visibility to relevant workers."
                },
                "auto_approval_delay": {
                    "type": "integer",
                    "description": "Seconds to wait before automatically approving submissions you haven't manually reviewed. Default is 259200 (3 days). After this time, pending assignments are auto-approved and workers are paid. Set longer if you need more review time.",
                    "default": 259200
                },
            },
            "required": ["title", "description", "question_html", "reward"],
        },
        create_hit,
    )

    async def get_hit(args: dict) -> list[TextContent]:
        """Get details of a specific HIT."""
        try:
            client = get_mturk_client()
            response = client.get_hit(HITId=args["hit_id"])
            hit = response["HIT"]
            result = {
                "hit_id": hit["HITId"],
                "hit_type_id": hit["HITTypeId"],
                "title": hit["Title"],
                "description": hit["Description"],
                "status": hit["HITStatus"],
                "max_assignments": hit["MaxAssignments"],
                "number_of_assignments_pending": hit.get("NumberOfAssignmentsPending", 0),
                "number_of_assignments_available": hit.get("NumberOfAssignmentsAvailable", 0),
                "number_of_assignments_completed": hit.get("NumberOfAssignmentsCompleted", 0),
                "reward": hit["Reward"],
                "creation_time": str(hit["CreationTime"]),
                "expiration": str(hit["Expiration"]),
            }
            return [TextContent(type="text", text=json.dumps(result, indent=2))]
        except Exception as e:
            return [TextContent(type="text", text=format_error(e))]

    register(
        "get_hit",
        """Retrieves detailed information about a specific HIT including its current status and assignment progress.

Use this tool to check on a HIT you've created - see how many workers have completed it, how many assignments are still available, and whether it's expired. This is useful for monitoring progress on your tasks.

The response includes assignment counts:
- pending: Workers have accepted but not yet submitted
- available: Open slots waiting for workers to accept
- completed: Submitted assignments (may be approved, rejected, or awaiting review)

Status values:
- 'Assignable': HIT is active and workers can accept new assignments
- 'Unassignable': All assignments taken or HIT expired, but some work pending
- 'Reviewable': Has submitted assignments ready for your review
- 'Reviewing': You've marked it as being reviewed
- 'Disposed': HIT has been deleted

Does NOT return the actual worker submissions - use list_assignments for that.""",
        {
            "type": "object",
            "properties": {
                "hit_id": {
                    "type": "string",
                    "description": "The unique HIT ID returned when you created the HIT (starts with a letter followed by alphanumeric characters). You can also get HIT IDs from list_hits."
                },
            },
            "required": ["hit_id"],
        },
        get_hit,
    )

    async def list_hits(args: dict) -> list[TextContent]:
        """List all HITs for the requester account."""
        try:
            client = get_mturk_client()
            response = client.list_hits(MaxResults=min(args.get("max_results", 100), 100))
            hits = response.get("HITs", [])
            result = {
                "count": len(hits),
                "hits": [
                    {
                        "hit_id": hit["HITId"],
                        "title": hit["Title"],
                        "status": hit["HITStatus"],
                        "max_assignments": hit["MaxAssignments"],
                        "pending": hit.get("NumberOfAssignmentsPending", 0),
                        "available": hit.get("NumberOfAssignmentsAvailable", 0),
                        "completed": hit.get("NumberOfAssignmentsCompleted", 0),
                        "reward": hit["Reward"],
                        "creation_time": str(hit["CreationTime"]),
                    }
                    for hit in hits
                ],
            }
            return [TextContent(type="text", text=json.dumps(result, indent=2))]
        except Exception as e:
            return [TextContent(type="text", text=format_error(e))]

    register(
        "list_hits",
        """Lists all HITs you've created on your MTurk requester account, sorted by creation date (most recent first).

Use this tool to get an overview of all your tasks, find HIT IDs you need for other operations, or check the status of multiple HITs at once. Returns summary information for each HIT including assignment progress.

For each HIT, shows:
- hit_id: Unique identifier needed for other operations
- title: The task title workers see
- status: Current state (Assignable, Reviewable, etc.)
- Assignment counts: pending/available/completed
- reward: Payment per assignment
- creation_time: When you created it

This returns HITs in all states. To find only HITs with work ready to review, use list_reviewable_hits instead.

Note: Only returns up to 100 HITs. If you have more, you may not see older ones.""",
        {
            "type": "object",
            "properties": {
                "max_results": {
                    "type": "integer",
                    "description": "Maximum number of HITs to return, between 1 and 100. Defaults to 100. Returns most recent HITs first.",
                    "default": 100,
                    "minimum": 1,
                    "maximum": 100
                },
            },
            "required": [],
        },
        list_hits,
    )

    async def delete_hit(args: dict) -> list[TextContent]:
        """Delete a HIT. The HIT must have no pending or available assignments."""
        try:
            client = get_mturk_client()
            hit_id = args["hit_id"]
            # First, try to update the HIT to expire it (required before deletion)
            try:
                client.update_expiration_for_hit(
                    HITId=hit_id,
                    ExpireAt=datetime.now(timezone.utc)
                )
            except Exception:
                pass  # May already be expired

            client.delete_hit(HITId=hit_id)
            return [TextContent(type="text", text=json.dumps({"success": True, "hit_id": hit_id, "message": "HIT deleted successfully"}, indent=2))]
        except Exception as e:
            return [TextContent(type="text", text=format_error(e))]

    register(
        "delete_hit",
        """Permanently deletes a HIT from MTurk. This cannot be undone.

Use this tool to clean up HITs you no longer need - either completed HITs after you've saved the results, or HITs created by mistake. Deleting removes the HIT from your dashboard and worker visibility.

IMPORTANT RESTRICTIONS:
- Cannot delete a HIT with pending assignments (workers currently working on it)
- Cannot delete a HIT with available assignments still open
- Must first review (approve/reject) all submitted assignments OR let them auto-approve

This tool automatically expires the HIT before deletion (required by MTurk). If the HIT can't be deleted due to pending work, you'll get an error - in that case, either wait for workers to finish or use update_hit_expiration to expire it, then try again after assignments complete.

Workflow for deleting an active HIT:
1. Use update_hit_expiration with 'now' to stop new workers accepting
2. Wait for pending workers to submit or timeout
3. Approve/reject all submissions with list_assignments and approve_assignment/reject_assignment
4. Then delete_hit will succeed""",
        {
            "type": "object",
            "properties": {
                "hit_id": {
                    "type": "string",
                    "description": "The unique HIT ID to delete. Get this from create_hit response or list_hits. The HIT must have no pending or available assignments."
                },
            },
            "required": ["hit_id"],
        },
        delete_hit,
    )

    async def update_hit_expiration(args: dict) -> list[TextContent]:
        """Update the expiration time of a HIT."""
        try:
            client = get_mturk_client()
            hit_id = args["hit_id"]
            expire_at = args["expire_at"]

            if expire_at.lower() == "now":
                expiration = datetime.now(timezone.utc)
            else:
                expiration = datetime.fromisoformat(expire_at.replace("Z", "+00:00"))

            client.update_expiration_for_hit(HITId=hit_id, ExpireAt=expiration)
            return [TextContent(type="text", text=json.dumps({
                "success": True,
                "hit_id": hit_id,
                "new_expiration": str(expiration),
            }, indent=2))]
        except Exception as e:
            return [TextContent(type="text", text=format_error(e))]

    register(
        "update_hit_expiration",
        """Changes when a HIT expires (stops accepting new workers).

Use this tool to:
- EXTEND a HIT: Give more time for workers to find and accept your task
- EXPIRE IMMEDIATELY: Stop accepting new workers right now (use 'now' as the value)

When a HIT expires:
- No NEW workers can accept the task
- Workers who already accepted can still complete and submit
- The HIT remains until all work is reviewed and you delete it

Common use cases:
- Your HIT isn't getting enough responses - extend the deadline
- You made a mistake and want to stop the HIT - expire it immediately
- Preparing to delete a HIT - must expire first before deletion

This does NOT affect workers currently doing the task or submitted work awaiting review. To cancel everything including pending work, you'd need to expire it, wait for timeouts, then reject/approve submissions.""",
        {
            "type": "object",
            "properties": {
                "hit_id": {
                    "type": "string",
                    "description": "The unique HIT ID to update. Get this from create_hit response or list_hits."
                },
                "expire_at": {
                    "type": "string",
                    "description": "New expiration time. Use 'now' to expire immediately, or an ISO 8601 datetime string like '2024-12-31T23:59:59Z' for a specific time. The time must be in the future (unless using 'now')."
                },
            },
            "required": ["hit_id", "expire_at"],
        },
        update_hit_expiration,
    )

    async def create_additional_assignments(args: dict) -> list[TextContent]:
        """Add more assignments to an existing HIT."""
        try:
            client = get_mturk_client()
            client.create_additional_assignments_for_hit(
                HITId=args["hit_id"],
                NumberOfAdditionalAssignments=args["additional_assignments"],
            )
            return [TextContent(type="text", text=json.dumps({
                "success": True,
                "hit_id": args["hit_id"],
                "additional_assignments": args["additional_assignments"],
            }, indent=2))]
        except Exception as e:
            return [TextContent(type="text", text=format_error(e))]

    register(
        "create_additional_assignments",
        """Adds more worker slots to an existing HIT, allowing more workers to complete it.

Use this tool when you need more responses than originally planned - for example, if you created a survey for 50 people but now want 100 total responses. This is cheaper than creating a new HIT because you reuse the existing task setup.

IMPORTANT: This costs additional money - each new assignment will be paid at the HIT's reward rate plus MTurk fees. Verify your balance with get_account_balance first.

The new assignments are added to the existing count. For example, if a HIT had max_assignments=50 and you add 25 more, it now has 75 total slots.

Requirements:
- The HIT must still be active (not expired or disposed)
- The HIT must be extendable (not all assignment types support this)

This does NOT extend the HIT's lifetime - if the HIT is about to expire, also use update_hit_expiration to give workers time to complete the new assignments.""",
        {
            "type": "object",
            "properties": {
                "hit_id": {
                    "type": "string",
                    "description": "The unique HIT ID to add assignments to. Get this from create_hit response or list_hits."
                },
                "additional_assignments": {
                    "type": "integer",
                    "description": "Number of new assignment slots to add. Each slot allows one additional worker to complete the HIT. Must be at least 1.",
                    "minimum": 1
                },
            },
            "required": ["hit_id", "additional_assignments"],
        },
        create_additional_assignments,
    )
