import enum
import uuid
from datetime import datetime, date
from typing import Optional
from sqlmodel import SQLModel, Field, Relationship, Column, JSON

class Role(str, enum.Enum):
    owner = "Owner/Admin"
    compliance_manager = "Compliance Manager"
    it_manager = "IT Manager"
    employee = "Employee"
    auditor = "Auditor/Read-only"

class Answer(str, enum.Enum):
    yes = "Yes"
    no = "No"
    partial = "Partial"
    na = "Not Applicable"

class Status(str, enum.Enum):
    open = "Open"
    in_progress = "In Progress"
    completed = "Completed"
    accepted = "Accepted"
    deferred = "Deferred"

class Severity(str, enum.Enum):
    low = "Low"
    medium = "Medium"
    high = "High"
    critical = "Critical"

class Tenant(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    industry: str = "Manufacturing"
    created_at: datetime = Field(default_factory=datetime.utcnow)

class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tenant_id: int = Field(foreign_key="tenant.id", index=True)
    email: str = Field(index=True, unique=True)
    full_name: str
    role: Role = Field(default=Role.employee)
    password_hash: str
    is_active: bool = True
    created_at: datetime = Field(default_factory=datetime.utcnow)

class Control(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    code: str = Field(index=True, unique=True)
    family: str
    title: str
    requirement: str
    nist_800_171: str
    cmmc_level: str
    insurance_control: bool = False

class Assessment(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tenant_id: int = Field(index=True)
    control_id: int = Field(foreign_key="control.id")
    answer: Answer = Field(default=Answer.no)
    notes: str = ""
    owner_id: Optional[int] = Field(default=None, foreign_key="user.id")
    due_date: Optional[date] = None
    risk_level: Severity = Field(default=Severity.medium)
    remediation_status: Status = Field(default=Status.open)
    updated_at: datetime = Field(default_factory=datetime.utcnow)

class Evidence(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tenant_id: int = Field(index=True)
    title: str
    description: str = ""
    filename: str
    content_type: str
    storage_path: str
    sha256: str
    version: int = 1
    tags: list[str] = Field(default_factory=list, sa_column=Column(JSON))
    control_id: Optional[int] = Field(default=None, foreign_key="control.id")
    owner_id: Optional[int] = Field(default=None, foreign_key="user.id")
    review_date: Optional[date] = None
    created_at: datetime = Field(default_factory=datetime.utcnow)

class Risk(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tenant_id: int = Field(index=True)
    title: str
    description: str
    control_id: Optional[int] = Field(default=None, foreign_key="control.id")
    severity: Severity = Field(default=Severity.medium)
    likelihood: int = Field(default=3, ge=1, le=5)
    owner_id: Optional[int] = Field(default=None, foreign_key="user.id")
    due_date: Optional[date] = None
    status: Status = Field(default=Status.open)
    remediation_plan: str = ""
    evidence_id: Optional[int] = Field(default=None, foreign_key="evidence.id")
    created_at: datetime = Field(default_factory=datetime.utcnow)
    @property
    def risk_score(self) -> int:
        severity_map = {Severity.low:1, Severity.medium:2, Severity.high:3, Severity.critical:4}
        return severity_map[self.severity] * self.likelihood

class Policy(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tenant_id: int = Field(index=True)
    title: str
    category: str
    content: str
    version: int = 1
    owner_id: Optional[int] = Field(default=None, foreign_key="user.id")
    next_review_date: Optional[date] = None
    created_at: datetime = Field(default_factory=datetime.utcnow)

class PolicyAcknowledgement(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tenant_id: int = Field(index=True)
    policy_id: int = Field(foreign_key="policy.id")
    user_id: int = Field(foreign_key="user.id")
    acknowledged_at: datetime = Field(default_factory=datetime.utcnow)

class Supplier(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tenant_id: int = Field(index=True)
    name: str
    criticality: Severity = Field(default=Severity.medium)
    contact_email: str = ""
    risk_score: int = 0
    review_date: Optional[date] = None
    notes: str = ""

class Questionnaire(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tenant_id: int = Field(index=True)
    customer_name: str
    title: str
    status: str = "Draft"
    questions: list[dict] = Field(default_factory=list, sa_column=Column(JSON))
    created_at: datetime = Field(default_factory=datetime.utcnow)

class AILog(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tenant_id: int = Field(index=True)
    user_id: int = Field(foreign_key="user.id")
    prompt: str
    response: str
    source_records: list[dict] = Field(default_factory=list, sa_column=Column(JSON))
    created_at: datetime = Field(default_factory=datetime.utcnow)

class AuditLog(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    tenant_id: int = Field(index=True)
    user_id: Optional[int] = Field(default=None, foreign_key="user.id")
    action: str
    entity_type: str
    entity_id: Optional[int] = None
    details: dict = Field(default_factory=dict, sa_column=Column(JSON))
    created_at: datetime = Field(default_factory=datetime.utcnow)
