from pydantic import BaseModel, Field, EmailStr
from typing import Optional, List, Dict, Any
from datetime import datetime
from enum import Enum

class UserRole(str, Enum):
    SUPER_ADMIN = "super_admin"
    ADMIN = "admin"
    ENGINEER = "engineer"
    VIEWER = "viewer"

class DeviceStatus(str, Enum):
    ONLINE = "online"
    OFFLINE = "offline"
    UNKNOWN = "unknown"

class User(BaseModel):
    id: str
    email: EmailStr
    username: str
    hashed_password: str
    role: UserRole = UserRole.VIEWER
    created_at: datetime = Field(default_factory=datetime.utcnow)
    is_active: bool = True

class UserCreate(BaseModel):
    email: EmailStr
    username: str
    password: str
    role: Optional[UserRole] = UserRole.VIEWER

class UserLogin(BaseModel):
    email: EmailStr
    password: str

class Token(BaseModel):
    access_token: str
    token_type: str
    user: Dict[str, Any]

class Device(BaseModel):
    id: str
    ip: str
    mac: Optional[str] = None
    hostname: Optional[str] = None
    vendor: Optional[str] = None
    device_type: Optional[str] = None
    model: Optional[str] = None
    status: DeviceStatus = DeviceStatus.UNKNOWN
    last_seen: datetime = Field(default_factory=datetime.utcnow)
    first_discovered: datetime = Field(default_factory=datetime.utcnow)
    open_ports: List[int] = []
    snmp_enabled: bool = False
    snmp_community: Optional[str] = None
    snmp_version: Optional[str] = None
    sys_descr: Optional[str] = None
    sys_object_id: Optional[str] = None
    location: Optional[str] = None
    notes: Optional[str] = None
    created_by: Optional[str] = None

class DeviceUpdate(BaseModel):
    hostname: Optional[str] = None
    location: Optional[str] = None
    notes: Optional[str] = None
    snmp_community: Optional[str] = None

class ScanTarget(BaseModel):
    """Individual scan target - supports IP, CIDR, IP range, or hostname with optional port"""
    target: str
    port: Optional[int] = None
    port_range: Optional[str] = None

class ScanRequest(BaseModel):
    subnet: str
    scan_ports: bool = True
    check_snmp: bool = True
    snmp_community: str = "public"
    snmp_version: str = "v2c"
    timeout: int = 2
    custom_ports: Optional[List[int]] = None
    scan_type: str = "discovery"
    targets: Optional[List[ScanTarget]] = None
    credential_set: Optional[str] = None

class ScanResult(BaseModel):
    id: str
    subnet: str
    started_at: datetime
    completed_at: Optional[datetime] = None
    devices_found: int = 0
    status: str = "running"
    created_by: str
    scan_type: str = "discovery"
    custom_ports: Optional[List[int]] = None

class SNMPData(BaseModel):
    sys_descr: Optional[str] = None
    sys_object_id: Optional[str] = None
    sys_uptime: Optional[str] = None
    sys_name: Optional[str] = None
    sys_location: Optional[str] = None
    sys_contact: Optional[str] = None
    interfaces: List[Dict[str, Any]] = []

class DashboardStats(BaseModel):
    total_devices: int
    online_devices: int
    offline_devices: int
    recent_scans: int
    devices_by_vendor: Dict[str, int]
    devices_by_type: Dict[str, int]
