import uuid
from sqlalchemy import Column, String, Text, Integer, Boolean, Date, DateTime, ForeignKey, Numeric, CheckConstraint, UniqueConstraint
from sqlalchemy.orm import relationship
from sqlalchemy import Enum as SqlEnum
from utils.utils import Base, utc_now, LabTestStatus

class VitalSign(Base):
    __tablename__ = "vital_signs"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    patient_id = Column(String(36), ForeignKey("patients.id", ondelete="CASCADE"), nullable=False, index=True)
    recorded_by_user_id = Column(String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False, index=True)
    recorded_at = Column(DateTime(timezone=True), nullable=False)
    systolic_bp = Column(Integer, nullable=True)
    diastolic_bp = Column(Integer, nullable=True)
    pulse_rate = Column(Integer, nullable=True)
    temperature_celsius = Column(Numeric(4, 2), nullable=True)
    respiratory_rate = Column(Integer, nullable=True)
    weight_kg = Column(Numeric(6, 2), nullable=True)
    height_cm = Column(Numeric(6, 2), nullable=True)
    oxygen_saturation = Column(Integer, nullable=True)
    notes = Column(Text, nullable=True)
    created_at = Column(DateTime(timezone=True), default=utc_now, nullable=False)
    updated_at = Column(DateTime(timezone=True), default=utc_now, onupdate=utc_now, nullable=False)

    patient = relationship("Patient", back_populates="vital_signs")
    recorded_by = relationship("User", foreign_keys=[recorded_by_user_id], back_populates="vital_signs_recorded")


class Consultation(Base):
    __tablename__ = "consultations"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    appointment_id = Column(String(36), ForeignKey("appointments.id", ondelete="SET NULL"), nullable=True, unique=True, index=True)
    patient_id = Column(String(36), ForeignKey("patients.id", ondelete="CASCADE"), nullable=False, index=True)
    doctor_id = Column(String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False, index=True)
    consultation_date = Column(DateTime(timezone=True), nullable=False)
    chief_complaint = Column(Text, nullable=True)
    present_illness = Column(Text, nullable=True)
    examination_findings = Column(Text, nullable=True)
    diagnosis = Column(Text, nullable=True)
    treatment_plan = Column(Text, nullable=True)
    notes = Column(Text, nullable=True)
    follow_up_required = Column(Boolean, nullable=False, default=False)
    follow_up_date = Column(Date, nullable=True)
    created_at = Column(DateTime(timezone=True), default=utc_now, nullable=False)
    updated_at = Column(DateTime(timezone=True), default=utc_now, onupdate=utc_now, nullable=False)

    appointment = relationship("Appointment", back_populates="consultation", uselist=False)
    patient = relationship("Patient", back_populates="consultations")
    doctor = relationship("User", foreign_keys=[doctor_id], back_populates="consultations")
    prescriptions = relationship("Prescription", back_populates="consultation", cascade="all, delete-orphan", passive_deletes=True)
    lab_tests = relationship("LabTest", back_populates="consultation")


class Prescription(Base):
    __tablename__ = "prescriptions"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    consultation_id = Column(String(36), ForeignKey("consultations.id", ondelete="CASCADE"), nullable=False, index=True)
    patient_id = Column(String(36), ForeignKey("patients.id", ondelete="CASCADE"), nullable=False, index=True)
    doctor_id = Column(String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False, index=True)
    medication_name = Column(String(200), nullable=False)
    dosage = Column(String(100), nullable=False)
    frequency = Column(String(100), nullable=False)
    duration = Column(String(100), nullable=False)
    quantity = Column(Integer, nullable=True)
    route = Column(String(50), nullable=True)
    special_instructions = Column(Text, nullable=True)
    is_active = Column(Boolean, nullable=False, default=True)
    prescribed_date = Column(Date, nullable=False)
    created_at = Column(DateTime(timezone=True), default=utc_now, nullable=False)
    updated_at = Column(DateTime(timezone=True), default=utc_now, onupdate=utc_now, nullable=False)

    consultation = relationship("Consultation", back_populates="prescriptions")
    patient = relationship("Patient", back_populates="prescriptions")
    doctor = relationship("User", foreign_keys=[doctor_id], back_populates="prescriptions")


class LabTest(Base):
    __tablename__ = "lab_tests"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    patient_id = Column(String(36), ForeignKey("patients.id", ondelete="CASCADE"), nullable=False, index=True)
    consultation_id = Column(String(36), ForeignKey("consultations.id", ondelete="SET NULL"), nullable=True, index=True)
    ordered_by_doctor_id = Column(String(36), ForeignKey("users.id", ondelete="RESTRICT"), nullable=False, index=True)
    test_name = Column(String(200), nullable=False)
    test_type = Column(String(100), nullable=True)
    ordered_date = Column(DateTime(timezone=True), nullable=False)
    sample_collected_date = Column(DateTime(timezone=True), nullable=True)
    result_date = Column(DateTime(timezone=True), nullable=True)
    result_value = Column(Text, nullable=True)
    result_unit = Column(String(50), nullable=True)
    reference_range = Column(String(100), nullable=True)
    status = Column(SqlEnum(LabTestStatus, name="labteststatus_enum"), nullable=False)
    notes = Column(Text, nullable=True)
    created_at = Column(DateTime(timezone=True), default=utc_now, nullable=False)
    updated_at = Column(DateTime(timezone=True), default=utc_now, onupdate=utc_now, nullable=False)

    patient = relationship("Patient", back_populates="lab_tests")
    consultation = relationship("Consultation", back_populates="lab_tests")
    ordered_by_doctor = relationship("User", foreign_keys=[ordered_by_doctor_id], back_populates="lab_tests_ordered")