"""Auto-generated by delta-registry-website/lib/schema-generator — do not hand-edit.
Source: Apify actor 'singapore-acra-registry-monitor' (live Apify API), generated 2026-09-18.
Regenerate with: node generate-all.js
"""
import os
from typing import Optional, Type

import requests
from crewai.tools import BaseTool
from pydantic import BaseModel, Field

APIFY_ACTOR_ID = 'ht22I1rCH3Ah9QGnM'  # stefano_seggio/singapore-acra-registry-monitor
APIFY_RUN_SYNC_URL = f"https://api.apify.com/v2/acts/{APIFY_ACTOR_ID}/run-sync-get-dataset-items"


class SingaporeAcraRegistryMonitorInput(BaseModel):
    """Mirrors singapore-acra-registry-monitor's real .actor/input_schema.json field-for-field."""

    shardSelection: Optional[list[str]] = Field(default=["A"], description='ACRA\'s data.gov.sg register is split into 27 files by the entity name\'s first letter (A-Z, plus \'Others\' for names starting with a digit/symbol). Select a subset to bound run time/cost, or leave all selected to monitor the full ~2.1M-entity register.')
    onlyNew: Optional[bool] = Field(default=True, description='When true (recommended, and the only free-of-charge default), only NEW_LISTING, STATUS_CHANGE, and UPDATED events are delivered - never a snapshot of unchanged or first-run-baseline entities. When false, every entity is delivered every run, including BASELINE_SNAPSHOT (first-run) and SNAPSHOT_NO_DIFF (unchanged) rows - useful for a full audit/export, but on a first run against all 27 shards this delivers roughly 2.1 million uncharged rows to your dataset.')
    eventTypes: Optional[list[str]] = Field(default=None, description='Restricts which of the three charged event types are delivered. Leave empty to deliver all three. Has no effect on BASELINE_SNAPSHOT/SNAPSHOT_NO_DIFF, which are controlled solely by \'onlyNew\'.')
    ssicCodeFilter: Optional[list[str]] = Field(default=[], description='Deliver only entities whose primary or secondary SSIC code starts with one of these prefixes - e.g. ["62"] for the whole Computer Programming/IT division (62011, 62020, 62090, ...), or ["62011"] for an exact code. Matching happens at delivery time only: every entity is still tracked internally regardless of this filter, so an entity that changes INTO your filtered SSIC range is correctly reported as UPDATED/STATUS_CHANGE the moment it does, not missed because it didn\'t match previously. Leave empty to deliver all industries.')
    entityStatusFilter: Optional[list[str]] = Field(default=[], description='Deliver only entities whose CURRENT status exactly matches one of these (case-insensitive) - e.g. ["Struck Off", "In Liquidation - Compulsory Winding Up (Insolvency)"] to watch only distressed/exited entities. Real status strings observed in the live register (2026-09-11): "Live", "Live Company", "Struck Off", "Terminated", "Cancelled", "Cancelled (Non-Renewal)", "Ceased Registration", "Amalgamated", "Dissolved - Members Voluntary Winding Up", "Dissolved - Creditors Voluntary Winding Up", "Dissolved - Compulsory Winding Up (Insolvency)", "In Liquidation - Members voluntary winding up", "In Liquidation - Compulsory Winding Up (Insolvency)". This list is not guaranteed exhaustive - ACRA\'s own register may use additional status strings not yet observed. As with the SSIC filter, matching is delivery-time only; internal tracking always covers every status. Leave empty to deliver all statuses.')
    maxItems: Optional[int] = Field(default=25, ge=1, description='Stops the run once this many records have been pushed (and charged, where applicable). Entities not yet reached when the limit is hit are simply re-evaluated fresh next run - nothing is lost or double-counted. Leave unset for no limit (a full-register run can deliver a large number of BASELINE_SNAPSHOT rows on its very first execution if onlyNew=false).')
    deltaStateName: Optional[str] = Field(default="default", description='Names the persistent Key-Value Store this run\'s delta memory lives in. Use a distinct name per independent schedule/configuration if you run this Actor more than one way (e.g. one schedule per shard subset) so they don\'t share baseline progress. Leave as \'default\' for a single schedule.')
    resetState: Optional[bool] = Field(default=False, description='When true, ignores all previously-remembered entities for the selected shards and re-baselines from scratch (every entity becomes a fresh, uncharged BASELINE_SNAPSHOT again). Use only to deliberately restart monitoring - this will suppress NEW_LISTING/STATUS_CHANGE/UPDATED detection for one run per affected shard.')
    watchlistUens: Optional[list[str]] = Field(default=[], description='A bounded list of specific UENs to re-check via ACRA\'s own real-time Business Profile API (see \'ACRA Business Profile API key\' below) in addition to the monthly bulk extract - use this for a small number of high-priority counterparties where a fresher-than-monthly check matters. Requires \'ACRA Business Profile API key\' to be set.')
    acraBusinessProfileApiKey: Optional[str] = Field(default=None, description='Required only when \'Watchlist UENs\' is non-empty. Bring-your-own-key: obtain a paid subscription key from ACRA\'s own API Marketplace (Entity Information Query / EIQ product, launched 18 Nov 2025) - this Actor never attempts to create that subscription on your behalf. Never logged or persisted beyond this run. Note: the exact response schema for this API was not independently verified during this Actor\'s build (it sits behind the same subscriber wall as the key itself) - see AGENTS.md before relying on BYOK enrichment in production.')
    webhookUrl: Optional[str] = Field(default=None, description='A Slack Incoming Webhook URL, or any HTTPS endpoint that accepts a JSON POST (e.g. a Make/n8n/Zapier catch-hook), to receive a formatted alert the moment a STATUS_CHANGE event is detected (the event type a compliance team actually escalates on). This is independent of, and does not replace, Apify\'s own platform-level webhook system, which you can configure separately in the Apify Console for the other event types.')


class SingaporeAcraRegistryMonitorTool(BaseTool):
    name: str = 'singapore-acra-registry-monitor'
    description: str = 'ACRA Singapore UEN delta monitor: tracks the corporate register (Pte Ltd, sole props, LLPs) via data.gov.sg for new incorporations, status changes (Struck Off, In Liquidation, Dissolved), SSIC/address updates. Filter by UEN, SSIC code, or status. Pay-per-event: billed only for what changed.'
    args_schema: Type[BaseModel] = SingaporeAcraRegistryMonitorInput

    def _run(self, shardSelection: Optional[list[str]] = None, onlyNew: Optional[bool] = None, eventTypes: Optional[list[str]] = None, ssicCodeFilter: Optional[list[str]] = None, entityStatusFilter: Optional[list[str]] = None, maxItems: Optional[int] = None, deltaStateName: Optional[str] = None, resetState: Optional[bool] = None, watchlistUens: Optional[list[str]] = None, acraBusinessProfileApiKey: Optional[str] = None, webhookUrl: Optional[str] = None) -> str:
        token = os.environ["APIFY_TOKEN"]
        payload = {
            **({"shardSelection": shardSelection} if shardSelection is not None else {}),
            **({"onlyNew": onlyNew} if onlyNew is not None else {}),
            **({"eventTypes": eventTypes} if eventTypes is not None else {}),
            **({"ssicCodeFilter": ssicCodeFilter} if ssicCodeFilter is not None else {}),
            **({"entityStatusFilter": entityStatusFilter} if entityStatusFilter is not None else {}),
            **({"maxItems": maxItems} if maxItems is not None else {}),
            **({"deltaStateName": deltaStateName} if deltaStateName is not None else {}),
            **({"resetState": resetState} if resetState is not None else {}),
            **({"watchlistUens": watchlistUens} if watchlistUens is not None else {}),
            **({"acraBusinessProfileApiKey": acraBusinessProfileApiKey} if acraBusinessProfileApiKey is not None else {}),
            **({"webhookUrl": webhookUrl} if webhookUrl is not None else {}),
        }
        resp = requests.post(
            APIFY_RUN_SYNC_URL,
            params={"token": token},
            json=payload,
            timeout=320,  # Apify's real run-sync-get-dataset-items cap is 300s
        )
        resp.raise_for_status()
        return resp.text  # dataset items as a JSON array string
