# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
"""Trustee models: TrusteeOrganisation, TrusteeRole, TrusteeAccess, TrusteeContract, TrusteeDocument, TrusteePosition, TrusteePositionDocument."""

from typing import Optional
from pydantic import BaseModel, Field
from modules.shared.attributeUtils import registerModelLabels
import uuid


class TrusteeOrganisation(BaseModel):
    """Represents trustee organisations (companies) within the Trustee feature."""
    id: str = Field(  # Unique string label (PK), not UUID
        description="Unique organisation identifier (label)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": False,  # Editable at creation, then readonly
            "frontend_required": True
        }
    )
    label: str = Field(
        description="Company name",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": False,
            "frontend_required": True
        }
    )
    enabled: bool = Field(
        default=True,
        description="Whether the organisation is enabled",
        json_schema_extra={
            "frontend_type": "checkbox",
            "frontend_readonly": False,
            "frontend_required": False
        }
    )
    mandateId: Optional[str] = Field(
        default=None,
        description="Mandate ID (system-level organisation)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    featureInstanceId: Optional[str] = Field(
        default=None,
        description="Feature Instance ID for instance-level isolation",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    # System attributes are automatically set by DatabaseConnector:
    # _createdAt, _modifiedAt, _createdBy, _modifiedBy


registerModelLabels(
    "TrusteeOrganisation",
    {"en": "Organisation", "fr": "Organisation", "de": "Organisation"},
    {
        "id": {"en": "ID", "fr": "ID", "de": "ID"},
        "label": {"en": "Label", "fr": "Libellé", "de": "Bezeichnung"},
        "enabled": {"en": "Enabled", "fr": "Activé", "de": "Aktiviert"},
        "mandateId": {"en": "Mandate", "fr": "Mandat", "de": "Mandat"},
        "featureInstanceId": {"en": "Feature Instance", "fr": "Instance de fonctionnalité", "de": "Feature-Instanz"},
    },
)


class TrusteeRole(BaseModel):
    """Defines roles within the Trustee feature."""
    id: str = Field(  # Unique string label (PK), not UUID
        description="Unique role identifier (label)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": False,
            "frontend_required": True
        }
    )
    desc: str = Field(
        description="Role description",
        json_schema_extra={
            "frontend_type": "textarea",
            "frontend_readonly": False,
            "frontend_required": True
        }
    )
    mandateId: Optional[str] = Field(
        default=None,
        description="Mandate ID",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    featureInstanceId: Optional[str] = Field(
        default=None,
        description="Feature Instance ID for instance-level isolation",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    # System attributes are automatically set by DatabaseConnector


registerModelLabels(
    "TrusteeRole",
    {"en": "Role", "fr": "Rôle", "de": "Rolle"},
    {
        "id": {"en": "ID", "fr": "ID", "de": "ID"},
        "desc": {"en": "Description", "fr": "Description", "de": "Beschreibung"},
        "mandateId": {"en": "Mandate", "fr": "Mandat", "de": "Mandat"},
        "featureInstanceId": {"en": "Feature Instance", "fr": "Instance de fonctionnalité", "de": "Feature-Instanz"},
    },
)


class TrusteeAccess(BaseModel):
    """Defines user access to organisations with specific roles."""
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="Unique access ID",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    organisationId: str = Field(
        description="Reference to TrusteeOrganisation.id",
        json_schema_extra={
            "frontend_type": "select",
            "frontend_readonly": False,
            "frontend_required": True,
            "frontend_options": "/api/trustee/{instanceId}/organisations/options"
        }
    )
    roleId: str = Field(
        description="Reference to TrusteeRole.id",
        json_schema_extra={
            "frontend_type": "select",
            "frontend_readonly": False,
            "frontend_required": True,
            "frontend_options": "/api/trustee/{instanceId}/roles/options"
        }
    )
    userId: str = Field(
        description="User ID assigned to this role",
        json_schema_extra={
            "frontend_type": "select",
            "frontend_readonly": False,
            "frontend_required": True,
            "frontend_options": "/api/users/options"
        }
    )
    contractId: Optional[str] = Field(
        default=None,
        description="Optional reference to TrusteeContract.id. If None, access is for full organisation. If set, access is limited to this specific contract.",
        json_schema_extra={
            "frontend_type": "select",
            "frontend_readonly": False,
            "frontend_required": False,
            "frontend_options": "/api/trustee/{instanceId}/contracts/options",
            "frontend_depends_on": "organisationId"
        }
    )
    mandateId: Optional[str] = Field(
        default=None,
        description="Mandate ID",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    featureInstanceId: Optional[str] = Field(
        default=None,
        description="Feature Instance ID for instance-level isolation",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    # System attributes are automatically set by DatabaseConnector


registerModelLabels(
    "TrusteeAccess",
    {"en": "Access", "fr": "Accès", "de": "Zugriff"},
    {
        "id": {"en": "ID", "fr": "ID", "de": "ID"},
        "organisationId": {"en": "Organisation", "fr": "Organisation", "de": "Organisation"},
        "roleId": {"en": "Role", "fr": "Rôle", "de": "Rolle"},
        "userId": {"en": "User", "fr": "Utilisateur", "de": "Benutzer"},
        "contractId": {"en": "Contract (optional)", "fr": "Contrat (optionnel)", "de": "Vertrag (optional)"},
        "mandateId": {"en": "Mandate", "fr": "Mandat", "de": "Mandat"},
        "featureInstanceId": {"en": "Feature Instance", "fr": "Instance de fonctionnalité", "de": "Feature-Instanz"},
    },
)


class TrusteeContract(BaseModel):
    """Defines customer contracts within organisations."""
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="Unique contract ID",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    organisationId: str = Field(
        description="Reference to TrusteeOrganisation.id (immutable after creation)",
        json_schema_extra={
            "frontend_type": "select",
            "frontend_readonly": False,  # Editable at creation, then readonly
            "frontend_required": True,
            "frontend_options": "/api/trustee/{instanceId}/organisations/options"
        }
    )
    label: str = Field(
        description="Label for the customer contract (e.g., 'Muster AG 2026')",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": False,
            "frontend_required": True
        }
    )
    enabled: bool = Field(
        default=True,
        description="Whether the contract is enabled",
        json_schema_extra={
            "frontend_type": "checkbox",
            "frontend_readonly": False,
            "frontend_required": False
        }
    )
    mandateId: Optional[str] = Field(
        default=None,
        description="Mandate ID",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    featureInstanceId: Optional[str] = Field(
        default=None,
        description="Feature Instance ID for instance-level isolation",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    # System attributes are automatically set by DatabaseConnector


registerModelLabels(
    "TrusteeContract",
    {"en": "Contract", "fr": "Contrat", "de": "Vertrag"},
    {
        "id": {"en": "ID", "fr": "ID", "de": "ID"},
        "organisationId": {"en": "Organisation", "fr": "Organisation", "de": "Organisation"},
        "label": {"en": "Label", "fr": "Libellé", "de": "Bezeichnung"},
        "enabled": {"en": "Enabled", "fr": "Activé", "de": "Aktiviert"},
        "mandateId": {"en": "Mandate", "fr": "Mandat", "de": "Mandat"},
        "featureInstanceId": {"en": "Feature Instance", "fr": "Instance de fonctionnalité", "de": "Feature-Instanz"},
    },
)


class TrusteeDocument(BaseModel):
    """Contains document references for bookings.
    
    Documents reference files in the central Files table via fileId.
    This allows file content to be stored once and referenced by multiple features.
    
    Note: organisationId and contractId removed as per architecture decision:
    - The feature instance IS the organisation
    - Contracts are eliminated from the model
    """
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="Unique document ID",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    fileId: Optional[str] = Field(
        default=None,
        description="Reference to central Files table (Files.id)",
        json_schema_extra={
            "frontend_type": "file_reference",
            "frontend_readonly": False,
            "frontend_required": False
        }
    )
    documentName: str = Field(
        description="File name (e.g., 'Beleg.pdf')",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": False,
            "frontend_required": True
        }
    )
    documentMimeType: str = Field(
        default="application/octet-stream",
        description="MIME type of the document",
        json_schema_extra={
            "frontend_type": "select",
            "frontend_readonly": False,
            "frontend_required": True,
            "frontend_options": "/api/trustee/mime-types/options"
        }
    )
    sourceType: Optional[str] = Field(
        default=None,
        description="Source type (e.g., 'sharepoint', 'upload', 'email')",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    sourceLocation: Optional[str] = Field(
        default=None,
        description="Original source location (e.g., SharePoint path)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    mandateId: Optional[str] = Field(
        default=None,
        description="Mandate ID (auto-set from context)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False,
            "frontend_hidden": True
        }
    )
    featureInstanceId: Optional[str] = Field(
        default=None,
        description="Feature Instance ID for instance-level isolation (auto-set from context)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False,
            "frontend_hidden": True
        }
    )
    # System attributes are automatically set by DatabaseConnector


registerModelLabels(
    "TrusteeDocument",
    {"en": "Document", "fr": "Document", "de": "Dokument"},
    {
        "id": {"en": "ID", "fr": "ID", "de": "ID"},
        "fileId": {"en": "File Reference", "fr": "Référence du fichier", "de": "Datei-Referenz"},
        "documentName": {"en": "Document Name", "fr": "Nom du document", "de": "Dokumentname"},
        "documentMimeType": {"en": "MIME Type", "fr": "Type MIME", "de": "MIME-Typ"},
        "sourceType": {"en": "Source Type", "fr": "Type de source", "de": "Quelltyp"},
        "sourceLocation": {"en": "Source Location", "fr": "Emplacement source", "de": "Quellort"},
        "mandateId": {"en": "Mandate", "fr": "Mandat", "de": "Mandat"},
        "featureInstanceId": {"en": "Feature Instance", "fr": "Instance de fonctionnalité", "de": "Feature-Instanz"},
    },
)


class TrusteePosition(BaseModel):
    """Contains booking positions (expense entries).
    
    Note: organisationId and contractId removed as per architecture decision:
    - The feature instance IS the organisation
    - Contracts are eliminated from the model
    """
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="Unique position ID",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    valuta: Optional[str] = Field(
        default=None,
        description="Value date (ISO format: YYYY-MM-DD)",
        json_schema_extra={
            "frontend_type": "date",
            "frontend_readonly": False,
            "frontend_required": True
        }
    )
    transactionDateTime: Optional[float] = Field(
        default=None,
        description="Transaction timestamp (UTC timestamp in seconds)",
        json_schema_extra={
            "frontend_type": "timestamp",
            "frontend_readonly": False,
            "frontend_required": True
        }
    )
    company: str = Field(
        default="",
        description="Company name",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": False,
            "frontend_required": False
        }
    )
    desc: str = Field(
        default="",
        description="Description",
        json_schema_extra={
            "frontend_type": "textarea",
            "frontend_readonly": False,
            "frontend_required": False
        }
    )
    tags: str = Field(
        default="",
        description="Tags (comma-separated)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": False,
            "frontend_required": False
        }
    )
    bookingCurrency: str = Field(
        default="CHF",
        description="Booking currency code",
        json_schema_extra={
            "frontend_type": "select",
            "frontend_readonly": False,
            "frontend_required": True,
            "frontend_options": [
                {"value": "CHF", "label": {"en": "CHF", "fr": "CHF", "de": "CHF"}},
                {"value": "EUR", "label": {"en": "EUR", "fr": "EUR", "de": "EUR"}},
                {"value": "USD", "label": {"en": "USD", "fr": "USD", "de": "USD"}},
                {"value": "GBP", "label": {"en": "GBP", "fr": "GBP", "de": "GBP"}},
            ]
        }
    )
    bookingAmount: float = Field(
        default=0.0,
        description="Booking amount",
        json_schema_extra={
            "frontend_type": "number",
            "frontend_readonly": False,
            "frontend_required": True
        }
    )
    originalCurrency: str = Field(
        default="CHF",
        description="Original currency code",
        json_schema_extra={
            "frontend_type": "select",
            "frontend_readonly": False,
            "frontend_required": True,
            "frontend_options": [
                {"value": "CHF", "label": {"en": "CHF", "fr": "CHF", "de": "CHF"}},
                {"value": "EUR", "label": {"en": "EUR", "fr": "EUR", "de": "EUR"}},
                {"value": "USD", "label": {"en": "USD", "fr": "USD", "de": "USD"}},
                {"value": "GBP", "label": {"en": "GBP", "fr": "GBP", "de": "GBP"}},
            ]
        }
    )
    originalAmount: float = Field(
        default=0.0,
        description="Original amount (manual input, no automatic currency conversion)",
        json_schema_extra={
            "frontend_type": "number",
            "frontend_readonly": False,
            "frontend_required": True
        }
    )
    vatPercentage: float = Field(
        default=0.0,
        description="VAT percentage",
        json_schema_extra={
            "frontend_type": "number",
            "frontend_readonly": False,
            "frontend_required": False
        }
    )
    vatAmount: float = Field(
        default=0.0,
        description="VAT amount (calculated: bookingAmount * vatPercentage / 100, can be manually overridden)",
        json_schema_extra={
            "frontend_type": "number",
            "frontend_readonly": False,
            "frontend_required": False
        }
    )
    mandateId: Optional[str] = Field(
        default=None,
        description="Mandate ID (auto-set from context)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False,
            "frontend_hidden": True
        }
    )
    featureInstanceId: Optional[str] = Field(
        default=None,
        description="Feature Instance ID for instance-level isolation (auto-set from context)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False,
            "frontend_hidden": True
        }
    )
    
    # Allow extra fields like _createdAt from database
    model_config = {"extra": "allow"}


registerModelLabels(
    "TrusteePosition",
    {"en": "Position", "fr": "Position", "de": "Position"},
    {
        "id": {"en": "ID", "fr": "ID", "de": "ID"},
        "valuta": {"en": "Value Date", "fr": "Date de valeur", "de": "Valutadatum"},
        "transactionDateTime": {"en": "Transaction Date/Time", "fr": "Date/Heure de transaction", "de": "Transaktionszeitpunkt"},
        "company": {"en": "Company", "fr": "Entreprise", "de": "Firma"},
        "desc": {"en": "Description", "fr": "Description", "de": "Beschreibung"},
        "tags": {"en": "Tags", "fr": "Tags", "de": "Tags"},
        "bookingCurrency": {"en": "Booking Currency", "fr": "Devise de comptabilisation", "de": "Buchungswährung"},
        "bookingAmount": {"en": "Booking Amount", "fr": "Montant de comptabilisation", "de": "Buchungsbetrag"},
        "originalCurrency": {"en": "Original Currency", "fr": "Devise d'origine", "de": "Originalwährung"},
        "originalAmount": {"en": "Original Amount", "fr": "Montant d'origine", "de": "Originalbetrag"},
        "vatPercentage": {"en": "VAT Percentage", "fr": "Pourcentage TVA", "de": "MwSt-Prozentsatz"},
        "vatAmount": {"en": "VAT Amount", "fr": "Montant TVA", "de": "MwSt-Betrag"},
        "mandateId": {"en": "Mandate", "fr": "Mandat", "de": "Mandat"},
        "featureInstanceId": {"en": "Feature Instance", "fr": "Instance de fonctionnalité", "de": "Feature-Instanz"},
    },
)


class TrusteePositionDocument(BaseModel):
    """Cross-reference table linking positions to documents (many-to-many).
    
    Note: organisationId and contractId removed as per architecture decision:
    - The feature instance IS the organisation
    - Contracts are eliminated from the model
    """
    id: str = Field(
        default_factory=lambda: str(uuid.uuid4()),
        description="Unique link ID",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False
        }
    )
    documentId: str = Field(
        description="Reference to TrusteeDocument.id",
        json_schema_extra={
            "frontend_type": "select",
            "frontend_readonly": False,
            "frontend_required": True,
            "frontend_options": "/api/trustee/{instanceId}/documents/options"
        }
    )
    positionId: str = Field(
        description="Reference to TrusteePosition.id",
        json_schema_extra={
            "frontend_type": "select",
            "frontend_readonly": False,
            "frontend_required": True,
            "frontend_options": "/api/trustee/{instanceId}/positions/options"
        }
    )
    mandateId: Optional[str] = Field(
        default=None,
        description="Mandate ID (auto-set from context)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False,
            "frontend_hidden": True
        }
    )
    featureInstanceId: Optional[str] = Field(
        default=None,
        description="Feature Instance ID for instance-level isolation (auto-set from context)",
        json_schema_extra={
            "frontend_type": "text",
            "frontend_readonly": True,
            "frontend_required": False,
            "frontend_hidden": True
        }
    )
    # System attributes are automatically set by DatabaseConnector


registerModelLabels(
    "TrusteePositionDocument",
    {"en": "Position-Document Link", "fr": "Lien Position-Document", "de": "Position-Dokument-Verknüpfung"},
    {
        "id": {"en": "ID", "fr": "ID", "de": "ID"},
        "documentId": {"en": "Document", "fr": "Document", "de": "Dokument"},
        "positionId": {"en": "Position", "fr": "Position", "de": "Position"},
        "mandateId": {"en": "Mandate", "fr": "Mandat", "de": "Mandat"},
        "featureInstanceId": {"en": "Feature Instance", "fr": "Instance de fonctionnalité", "de": "Feature-Instanz"},
    },
)
