"""
Driver Model
Driver profiles, verification, documents, and location tracking
"""
import enum
from datetime import datetime, date
from typing import Optional, List
from sqlalchemy import (
    String, Boolean, Enum, Text, DateTime, Date,
    ForeignKey, Float, Index, JSON
)
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.models.base import BaseModel


class DriverStatus(str, enum.Enum):
    """Driver verification and availability status"""
    PENDING = "pending"
    UNDER_REVIEW = "under_review"
    APPROVED = "approved"
    REJECTED = "rejected"
    SUSPENDED = "suspended"


class DocumentType(str, enum.Enum):
    """Driver document types"""
    DRIVERS_LICENSE = "drivers_license"
    VEHICLE_REGISTRATION = "vehicle_registration"
    INSURANCE = "insurance"
    PROFILE_PHOTO = "profile_photo"
    NATIONAL_ID = "national_id"
    BACKGROUND_CHECK = "background_check"
    OTHER = "other"


class Driver(BaseModel):
    """
    Driver profile with verification and location.
    Uses MySQL POINT type for geospatial location storage.
    """
    __tablename__ = "drivers"
    
    # User reference
    user_id: Mapped[int] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"),
        unique=True,
        nullable=False,
        index=True
    )
    
    # License Information
    license_number: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    license_expiry: Mapped[Optional[date]] = mapped_column(Date, nullable=True)
    license_state: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    
    # Verification Status
    status: Mapped[DriverStatus] = mapped_column(
        Enum(DriverStatus),
        default=DriverStatus.PENDING,
        nullable=False,
        index=True
    )
    rejection_reason: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    verified_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    verified_by: Mapped[Optional[int]] = mapped_column(
        ForeignKey("users.id", ondelete="SET NULL"),
        nullable=True
    )
    
    # Availability
    is_online: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    is_on_ride: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    last_online_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    
    # Current Location (stored as lat/lng for simplicity, can use MySQL POINT)
    current_latitude: Mapped[Optional[float]] = mapped_column(Float(precision=10), nullable=True)
    current_longitude: Mapped[Optional[float]] = mapped_column(Float(precision=10), nullable=True)
    location_updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    heading: Mapped[Optional[float]] = mapped_column(Float, nullable=True)  # Direction in degrees
    
    # Rating
    average_rating: Mapped[float] = mapped_column(Float, default=5.0, nullable=False)
    total_ratings: Mapped[int] = mapped_column(default=0, nullable=False)
    total_rides: Mapped[int] = mapped_column(default=0, nullable=False)
    completed_rides: Mapped[int] = mapped_column(default=0, nullable=False)
    cancelled_rides: Mapped[int] = mapped_column(default=0, nullable=False)
    
    # Earnings
    total_earnings: Mapped[int] = mapped_column(default=0, nullable=False)  # In cents
    current_balance: Mapped[int] = mapped_column(default=0, nullable=False)  # In cents
    
    # Vehicle (current active vehicle)
    current_vehicle_id: Mapped[Optional[int]] = mapped_column(
        ForeignKey("vehicles.id", ondelete="SET NULL"),
        nullable=True
    )
    
    # Bank Details for Payouts (encrypted in production)
    bank_name: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    bank_account_number: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    bank_routing_number: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
    bank_account_holder: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    
    # Metadata
    notes: Mapped[Optional[str]] = mapped_column(Text, nullable=True)  # Admin notes
    
    # Relationships
    user: Mapped["User"] = relationship(
        "User",
        back_populates="driver_profile",
        foreign_keys=[user_id]
    )
    documents: Mapped[List["DriverDocument"]] = relationship(
        "DriverDocument",
        back_populates="driver",
        lazy="dynamic"
    )
    vehicles: Mapped[List["Vehicle"]] = relationship(
        "Vehicle",
        back_populates="driver",
        foreign_keys="Vehicle.driver_id",
        lazy="dynamic"
    )
    current_vehicle: Mapped[Optional["Vehicle"]] = relationship(
        "Vehicle",
        foreign_keys=[current_vehicle_id],
        uselist=False,
        lazy="joined"
    )
    account_settings: Mapped[Optional["DriverAccountSettings"]] = relationship(
        "DriverAccountSettings",
        back_populates="driver",
        uselist=False
    )
    offer_profiles: Mapped[List["OfferProfile"]] = relationship(
        "OfferProfile",
        back_populates="driver",
        foreign_keys="OfferProfile.driver_id",
        lazy="dynamic"
    )
    
    # Indexes for geospatial queries
    __table_args__ = (
        Index('idx_driver_status_online', 'status', 'is_online'),
        Index('idx_driver_location', 'current_latitude', 'current_longitude'),
        Index('idx_driver_rating', 'average_rating'),
    )
    
    @property
    def is_available(self) -> bool:
        """Check if driver is available for rides"""
        return (
            self.status == DriverStatus.APPROVED and
            self.is_online and
            not self.is_on_ride
        )


class DriverDocument(BaseModel):
    """Driver uploaded documents for verification"""
    __tablename__ = "driver_documents"
    
    driver_id: Mapped[int] = mapped_column(
        ForeignKey("drivers.id", ondelete="CASCADE"),
        nullable=False,
        index=True
    )
    
    document_type: Mapped[DocumentType] = mapped_column(
        Enum(DocumentType),
        nullable=False
    )
    document_url: Mapped[str] = mapped_column(String(500), nullable=False)
    document_number: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    expiry_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True)
    
    # Verification
    is_verified: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    verified_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    verified_by: Mapped[Optional[int]] = mapped_column(
        ForeignKey("users.id", ondelete="SET NULL"),
        nullable=True
    )
    rejection_reason: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    
    # Extra Data
    extra_data: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
    
    # Relationship
    driver: Mapped["Driver"] = relationship(
        "Driver",
        back_populates="documents"
    )
    
    __table_args__ = (
        Index('idx_document_driver_type', 'driver_id', 'document_type'),
    )


# Import for type hints
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from app.models.user import User
    from app.models.vehicle import Vehicle
    from app.models.driver_account_settings import DriverAccountSettings
    from app.models.offer_profile import OfferProfile
