from datetime import datetime, timezone
from typing import Any, Literal

from pydantic import BaseModel, ConfigDict, Field


def utc_now() -> datetime:
    return datetime.now(timezone.utc)


class WazuhIngestRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "source": "wazuh",
                "rule_id": "100335",
                "alert_id": "1737301024.88912",
                "severity": 12,
                "title": "VPN success outside Thailand",
                "payload": {"full_log": "soc_mvp_test=true usecase_id=A3-05"},
            }
        }
    )

    source: str = Field(default="wazuh", description="Alert source name.", examples=["wazuh"])
    rule_id: str | None = Field(default=None, description="Wazuh rule ID.", examples=["100335"])
    alert_id: str | None = Field(default=None, description="Original alert identifier.", examples=["1737301024.88912"])
    severity: int | None = Field(default=None, description="Numeric alert severity.", examples=[12])
    title: str | None = Field(default=None, description="Human-readable alert title.", examples=["VPN success outside Thailand"])
    payload: dict[str, Any] = Field(
        default_factory=dict,
        description="Raw alert payload from source.",
        examples=[{"full_log": "soc_mvp_test=true usecase_id=A3-05"}],
    )


class ActionCreateIncidentRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "title": "Suspicious admin login",
                "severity": "high",
                "source": "soc-integrator",
                "dedupe_key": "vpn-user1-2026-03-03",
                "payload": {"description": "Detected from C1-01", "case_customer": 1},
            }
        }
    )

    title: str = Field(description="Incident title for escalation target.", examples=["Suspicious admin login"])
    severity: str = Field(default="medium", description="Incident severity level.", examples=["high"])
    source: str = Field(default="soc-integrator", description="Producer of the incident.", examples=["soc-integrator"])
    dedupe_key: str | None = Field(default=None, description="Stable key to deduplicate incidents.", examples=["vpn-user1-2026-03-03"])
    payload: dict[str, Any] = Field(
        default_factory=dict,
        description="Additional incident context.",
        examples=[{"description": "Detected from C1-01", "case_customer": 1}],
    )


class IrisTicketCreateRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "title": "C1-01 impossible travel",
                "description": "Auto-created from SOC workflow",
                "case_customer": 1,
                "case_soc_id": "soc-prod",
                "payload": {"case_tags": ["appendix_c", "c1-01"]},
            }
        }
    )

    title: str = Field(description="IRIS case name.", examples=["C1-01 impossible travel"])
    description: str = Field(default="Created by soc-integrator", description="IRIS case description.", examples=["Auto-created from SOC workflow"])
    case_customer: int | None = Field(default=None, description="IRIS customer ID.", examples=[1])
    case_soc_id: str | None = Field(default=None, description="IRIS SOC ID.", examples=["soc-prod"])
    payload: dict[str, Any] = Field(
        default_factory=dict,
        description="Optional IRIS API fields merged into request body.",
        examples=[{"case_tags": ["appendix_c", "c1-01"]}],
    )


class IocEnrichRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "ioc_type": "ip",
                "ioc_value": "8.8.8.8",
                "providers": ["virustotal", "abuseipdb"],
            }
        }
    )

    ioc_type: Literal["domain", "ip", "hash", "url"] = Field(description="Type of IOC.", examples=["ip"])
    ioc_value: str = Field(description="IOC value to enrich.", examples=["8.8.8.8"])
    providers: list[str] = Field(
        default_factory=lambda: ["virustotal"],
        description="Enrichment providers to query.",
        examples=[["virustotal", "abuseipdb"]],
    )


class IocEvaluateRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "ioc_type": "domain",
                "ioc_value": "example.com",
                "providers": ["virustotal"],
                "malicious_threshold": 1,
                "suspicious_threshold": 3,
            }
        }
    )

    ioc_type: Literal["domain", "ip", "hash", "url"] = Field(description="Type of IOC.", examples=["domain"])
    ioc_value: str = Field(description="IOC value to evaluate.", examples=["example.com"])
    providers: list[str] = Field(default_factory=lambda: ["virustotal"], description="Evaluation providers.", examples=[["virustotal"]])
    malicious_threshold: int = Field(default=1, description="Minimum malicious engines to mark matched.", examples=[1])
    suspicious_threshold: int = Field(default=3, description="Minimum suspicious engines to mark matched.", examples=[3])


class TriggerShuffleRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "workflow_id": "07ecad05-ff68-41cb-888d-96d1a8e8db4b",
                "execution_argument": {"ioc_type": "ip", "ioc_value": "8.8.8.8"},
            }
        }
    )

    workflow_id: str = Field(description="Shuffle workflow UUID.", examples=["07ecad05-ff68-41cb-888d-96d1a8e8db4b"])
    execution_argument: dict[str, Any] = Field(
        default_factory=dict,
        description="Execution argument payload passed to workflow.",
        examples=[{"ioc_type": "ip", "ioc_value": "8.8.8.8"}],
    )


class ShuffleProxyRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "method": "POST",
                "path": "/api/v1/workflows",
                "params": {"limit": 50},
                "payload": {"name": "test"},
            }
        }
    )

    method: str = Field(default="GET", description="HTTP method for proxied request.", examples=["POST"])
    path: str = Field(description="Shuffle API path (with or without /api prefix).", examples=["/api/v1/workflows"])
    params: dict[str, Any] = Field(default_factory=dict, description="Query parameters.", examples=[{"limit": 50}])
    payload: dict[str, Any] = Field(default_factory=dict, description="JSON body for POST/PUT/PATCH.", examples=[{"name": "test"}])


class ShuffleLoginRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={"example": {"username": "admin@example.com", "password": "change-me"}}
    )

    username: str = Field(description="Shuffle username.", examples=["admin@example.com"])
    password: str = Field(description="Shuffle password.", examples=["change-me"])


class LogLossStreamCheck(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "name": "log_monitor",
                "query": "full_log:log_monitor OR rule.id:100411",
                "min_count": 1,
            }
        }
    )

    name: str = Field(description="Logical stream name.", examples=["fortigate"])
    query: str = Field(description="OpenSearch query to count matching logs.", examples=["full_log:*source=fortigate*"])
    min_count: int = Field(default=1, description="Minimum events expected in time window.", examples=[1])


class LogLossCheckRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "minutes": 5,
                "streams": [
                    {"name": "log_monitor", "query": "full_log:log_monitor OR rule.id:100411", "min_count": 1},
                    {
                        "name": "fortigate",
                        "query": "full_log:fortigate OR full_log:FGT80F OR full_log:FGT60F OR full_log:FGT40F OR full_log:FGT501E",
                        "min_count": 1,
                    },
                    {"name": "windows_agent", "query": "full_log:windows_agent OR full_log:windows", "min_count": 1},
                ],
            }
        }
    )

    minutes: int = Field(default=5, description="Lookback window in minutes.", examples=[5])
    streams: list[LogLossStreamCheck] = Field(
        default_factory=list,
        description="Streams to validate. Empty uses default streams.",
    )


class MvpIncidentIngestRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "source": "wazuh",
                "event_type": "vpn_geo_anomaly",
                "event_id": "evt-1737301024",
                "timestamp": "2026-03-03T06:00:00Z",
                "severity": "high",
                "title": "VPN login anomaly",
                "description": "User logged in from unexpected country",
                "asset": {"user": "alice", "hostname": "win-dc01"},
                "network": {"src_ip": "8.8.8.8", "country": "US"},
                "tags": ["vpn", "geo-anomaly"],
                "risk_context": {"admin_account": True},
                "raw": {"full_log": "..."},
                "payload": {"case_customer": 1},
            }
        }
    )

    source: Literal["wazuh", "shuffle", "manual"] = Field(default="wazuh", description="Source system for the event.", examples=["wazuh"])
    event_type: Literal[
        "ioc_dns",
        "ioc_ips",
        "vpn_geo_anomaly",
        "auth_anomaly",
        "c1_impossible_travel",
        "c2_credential_abuse",
        "c3_lateral_movement",
        "generic",
    ] = Field(default="generic", description="Normalized event category.", examples=["vpn_geo_anomaly"])
    event_id: str = Field(description="Unique event identifier from source.", examples=["evt-1737301024"])
    timestamp: datetime = Field(description="Event timestamp in ISO-8601 format.", examples=["2026-03-03T06:00:00Z"])
    severity: Literal["low", "medium", "high", "critical"] = Field(default="medium", description="Normalized severity.", examples=["high"])
    title: str = Field(description="Short event title.", examples=["VPN login anomaly"])
    description: str = Field(description="Detailed event description.", examples=["User logged in from unexpected country"])
    asset: dict[str, Any] = Field(default_factory=dict, description="Asset and identity context.", examples=[{"user": "alice", "hostname": "win-dc01"}])
    network: dict[str, Any] = Field(default_factory=dict, description="Network context.", examples=[{"src_ip": "8.8.8.8", "country": "US"}])
    tags: list[str] = Field(default_factory=list, description="Search/filter tags.", examples=[["vpn", "geo-anomaly"]])
    risk_context: dict[str, Any] = Field(default_factory=dict, description="Risk indicators used in scoring.", examples=[{"admin_account": True}])
    raw: dict[str, Any] = Field(default_factory=dict, description="Original raw event object.", examples=[{"full_log": "..." }])
    payload: dict[str, Any] = Field(default_factory=dict, description="Additional pipeline payload.", examples=[{"case_customer": 1}])


class MvpIocEvaluateRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "ioc_type": "ip",
                "ioc_value": "1.1.1.1",
                "source_event": {"event_id": "evt-1", "asset": {"hostname": "fw01"}},
            }
        }
    )

    ioc_type: Literal["domain", "ip"] = Field(description="IOC type for MVP workflow.", examples=["ip"])
    ioc_value: str = Field(description="IOC value to evaluate.", examples=["1.1.1.1"])
    source_event: dict[str, Any] = Field(
        default_factory=dict,
        description="Source event context used for incident linking.",
        examples=[{"event_id": "evt-1", "asset": {"hostname": "fw01"}}],
    )


class MvpVpnEvaluateRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "user": "alice",
                "src_ip": "8.8.8.8",
                "country_code": "US",
                "success": True,
                "event_time": "2026-03-03T06:00:00Z",
                "is_admin": False,
                "off_hours": True,
                "first_seen_country": True,
                "event_id": "vpn-1737301024",
            }
        }
    )

    user: str = Field(description="Authenticated username.", examples=["alice"])
    src_ip: str = Field(description="Source public IP address.", examples=["8.8.8.8"])
    country_code: str = Field(description="ISO country code of source IP.", examples=["US"])
    success: bool = Field(description="Whether VPN login succeeded.", examples=[True])
    event_time: datetime = Field(description="Authentication timestamp.", examples=["2026-03-03T06:00:00Z"])
    is_admin: bool = Field(default=False, description="User is privileged/admin account.", examples=[False])
    off_hours: bool = Field(default=False, description="Event happened outside business hours.", examples=[True])
    first_seen_country: bool = Field(default=False, description="First observed country for user.", examples=[True])
    event_id: str | None = Field(default=None, description="Optional event ID from upstream.", examples=["vpn-1737301024"])


class CDetectionEvaluateRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "minutes": 30,
                "query": "soc_mvp_test=true",
                "selectors": ["c1", "c3"],
                "dry_run": True,
                "limit": 200,
            }
        }
    )

    minutes: int = Field(default=30, description="Lookback window in minutes.", examples=[30])
    query: str = Field(default="soc_mvp_test=true", description="OpenSearch query for candidate events.", examples=["soc_mvp_test=true"])
    selectors: list[str] = Field(
        default_factory=list,
        description="Optional use-case filters (c1/c2/c3 or Cx-yy).",
        examples=[["c1", "c3"]],
    )
    dry_run: bool = Field(default=False, description="If true, evaluate only and do not create incidents/tickets.", examples=[True])
    limit: int = Field(default=200, description="Maximum events fetched from Wazuh indexer.", examples=[200])


class SimLogRunRequest(BaseModel):
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "script": "fortigate",
                "target": "all",
                "scenario": "all",
                "count": 1,
                "delay_seconds": 0.3,
                "forever": False,
            }
        }
    )

    script: Literal[
        "fortigate",
        "endpoint",
        "cisco",
        "proposal_required",
        "proposal_appendix_b",
        "proposal_appendix_c",
        "wazuh_test",
    ] = Field(description="Whitelisted simulator script key.", examples=["fortigate"])
    target: str = Field(default="all", description="Primary selector/model/platform for the script.", examples=["all"])
    scenario: str = Field(default="all", description="Secondary selector used by endpoint simulator.", examples=["process"])
    count: int = Field(default=1, description="Number of iterations for non-forever mode.", examples=[1])
    delay_seconds: float = Field(default=0.3, description="Delay between iterations.", examples=[0.3])
    forever: bool = Field(default=False, description="Run continuously until stopped.", examples=[False])


class ApiResponse(BaseModel):
    ok: bool = True
    message: str = "ok"
    timestamp: datetime = Field(default_factory=utc_now)
    data: dict[str, Any] = Field(default_factory=dict)
