"""
Modèle College et Building - GMAO Collège
Gestion des collèges et bâtiments
Compatible avec la base de données existante
"""
from datetime import datetime, timezone
from ...extensions import db


class College(db.Model):
    """Collège."""
    __tablename__ = "colleges"
    
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), nullable=False)
    address = db.Column(db.Text, nullable=True)
    city = db.Column(db.String(100), nullable=True)
    zip_code = db.Column(db.String(10), nullable=True)
    phone = db.Column(db.String(20), nullable=True)
    email = db.Column(db.String(100), nullable=True)
    website = db.Column(db.String(255), nullable=True)
    logo = db.Column(db.String(255), nullable=True)
    is_active = db.Column(db.Boolean, default=True)
    created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
    updated_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
    
    # Relations - buildings n'a pas de college_id, pas de relation directe
    
    def __repr__(self):
        return f"<College {self.name}>"


class Site(db.Model):
    """Site physique : collège, logements de fonction, annexe, etc."""
    __tablename__ = "sites"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120), nullable=False, unique=True)
    site_type = db.Column(db.String(40), nullable=False, default="college")
    address = db.Column(db.Text, nullable=True)
    is_active = db.Column(db.Boolean, nullable=False, default=True)
    created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
    buildings = db.relationship("Building", back_populates="site", lazy="dynamic")


class Building(db.Model):
    """Bâtiment du collège."""
    __tablename__ = "buildings"
    
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text, nullable=True)
    site_id = db.Column(db.Integer, db.ForeignKey("sites.id"), nullable=True, index=True)
    
    # Relations - utiliser overlaps pour éviter warning SQLAlchemy
    rooms = db.relationship("Room", overlaps="building", lazy="dynamic")
    zones = db.relationship("Zone", back_populates="building", lazy="dynamic")
    site = db.relationship("Site", back_populates="buildings")
    
    @property
    def room_count(self):
        """Nombre de salles dans le bâtiment."""
        return self.rooms.count()
    
    def __repr__(self):
        return f"<Building {self.name}>"


class HousingUnit(db.Model):
    """Logement de fonction et historique courant de son occupation."""
    __tablename__ = "housing_units"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120), nullable=False)
    code = db.Column(db.String(40), nullable=True, unique=True)
    building_id = db.Column(db.Integer, db.ForeignKey("buildings.id"), nullable=False, index=True)
    housing_type = db.Column(db.String(40), nullable=False, default="fonction")
    occupancy_status = db.Column(db.String(30), nullable=False, default="vacant")
    occupant_name = db.Column(db.String(150), nullable=True)
    occupant_contact = db.Column(db.String(150), nullable=True)
    occupancy_start = db.Column(db.Date, nullable=True)
    occupancy_end = db.Column(db.Date, nullable=True)
    notes = db.Column(db.Text, nullable=True)
    is_active = db.Column(db.Boolean, nullable=False, default=True)
    created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
    updated_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))

    building = db.relationship("Building", backref=db.backref("housing_units", lazy="dynamic"))
    rooms = db.relationship("Room", back_populates="housing_unit", lazy="dynamic")
    occupancies = db.relationship("HousingOccupancy", back_populates="housing_unit",
                                  order_by="HousingOccupancy.start_date.desc()",
                                  cascade="all, delete-orphan")


class HousingOccupancy(db.Model):
    """Historique daté des occupants, clés et états des lieux."""
    __tablename__ = "housing_occupancies"

    id = db.Column(db.Integer, primary_key=True)
    housing_unit_id = db.Column(db.Integer, db.ForeignKey("housing_units.id", ondelete="CASCADE"), nullable=False, index=True)
    occupant_name = db.Column(db.String(150), nullable=False)
    occupant_contact = db.Column(db.String(150), nullable=True)
    start_date = db.Column(db.Date, nullable=False)
    end_date = db.Column(db.Date, nullable=True)
    key_count = db.Column(db.Integer, nullable=False, default=0)
    entry_condition = db.Column(db.Text, nullable=True)
    exit_condition = db.Column(db.Text, nullable=True)
    notes = db.Column(db.Text, nullable=True)
    created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))

    housing_unit = db.relationship("HousingUnit", back_populates="occupancies")


class Zone(db.Model):
    """Zone dans un bâtiment."""
    __tablename__ = "zones"
    
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    building_id = db.Column(db.Integer, db.ForeignKey("buildings.id"), nullable=False)
    # Durées propres aux espaces verts de cette zone (minutes). Elles restent
    # nulles pour les zones qui ne sont pas concernées.
    mowing_minutes = db.Column(db.Integer, nullable=True)
    edging_minutes = db.Column(db.Integer, nullable=True)
    hedge_minutes = db.Column(db.Integer, nullable=True)
    branch_removal_minutes = db.Column(db.Integer, nullable=True)
    
    # Relations
    building = db.relationship("Building", back_populates="zones")
    rooms = db.relationship("Room", back_populates="zone")
    
    @property
    def full_name(self):
        """Nom complet avec bâtiment."""
        if self.building:
            return f"{self.building.name} - {self.name}"
        return self.name
    
    def __repr__(self):
        return f"<Zone {self.name}>"


class Room(db.Model):
    """Salle du collège."""
    __tablename__ = "rooms"
    
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    code = db.Column(db.String(20), nullable=True)
    zone_id = db.Column(db.Integer, db.ForeignKey("zones.id"), nullable=True)
    floor = db.Column(db.Integer, default=0)
    building_id = db.Column(db.Integer, db.ForeignKey("buildings.id"), nullable=False)
    room_type_id = db.Column(db.Integer, db.ForeignKey("room_types.id"), nullable=True)
    room_profile_id = db.Column(db.Integer, db.ForeignKey("room_profiles.id"), nullable=True, index=True)
    housing_unit_id = db.Column(db.Integer, db.ForeignKey("housing_units.id"), nullable=True, index=True)
    # Libelle historique conserve pour les imports anterieurs a zone_id.
    legacy_zone_name = db.Column("zone", db.String(100), nullable=True)
    
    # Relations - utiliser overlaps pour éviter warning SQLAlchemy
    building = db.relationship("Building", overlaps="rooms")
    zone = db.relationship("Zone", back_populates="rooms")
    room_type = db.relationship("RoomType", back_populates="rooms")
    room_profile = db.relationship("RoomProfile", backref=db.backref("rooms", lazy="dynamic"))
    equipments = db.relationship("Equipment", back_populates="room")
    housing_unit = db.relationship("HousingUnit", back_populates="rooms")
    
    @property
    def full_name(self):
        """Nom complet avec bâtiment."""
        if self.building:
            return f"{self.building.name} - {self.name}"
        return self.name
    
    def __repr__(self):
        return f"<Room {self.name}>"


class RoomType(db.Model):
    """Type de salle."""
    __tablename__ = "room_types"
    
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text, nullable=True)
    is_teaching = db.Column(db.Boolean, default=False)
    color = db.Column(db.String(20), nullable=True)
    icon = db.Column(db.String(50), nullable=True)
    
    # Relation vers les salles
    rooms = db.relationship("Room", back_populates="room_type")
    
    def __repr__(self):
        return f"<RoomType {self.name}>"


class RoomProfile(db.Model):
    """Modèle de proposition pour préconfigurer un local.

    ``RoomType`` reste un classement structurel (notamment utilisé par les
    emplois du temps).  Un profil est une proposition éditable qui ne crée
    aucun équipement tant que l'utilisateur n'a pas validé l'application.
    """
    __tablename__ = "room_profiles"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120), nullable=False, unique=True)
    description = db.Column(db.Text, nullable=True)
    room_type_id = db.Column(db.Integer, db.ForeignKey("room_types.id"), nullable=True, index=True)
    is_active = db.Column(db.Boolean, nullable=False, default=True)
    created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
    updated_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))

    room_type = db.relationship("RoomType", backref=db.backref("profiles", lazy="dynamic"))
    items = db.relationship("RoomProfileItem", back_populates="profile", cascade="all, delete-orphan",
                            order_by="RoomProfileItem.sort_order, RoomProfileItem.id")
    surfaces = db.relationship("RoomSurface", back_populates="profile", cascade="all, delete-orphan")

    def __repr__(self):
        return f"<RoomProfile {self.name}>"


class RoomProfileItem(db.Model):
    """Une proposition d'équipement dans un profil de local."""
    __tablename__ = "room_profile_items"

    id = db.Column(db.Integer, primary_key=True)
    profile_id = db.Column(db.Integer, db.ForeignKey("room_profiles.id", ondelete="CASCADE"), nullable=False, index=True)
    label = db.Column(db.String(200), nullable=False)
    category_id = db.Column(db.Integer, db.ForeignKey("equipment_categories.id"), nullable=True, index=True)
    lot_id = db.Column(db.Integer, db.ForeignKey("lots.id"), nullable=True, index=True)
    quantity = db.Column(db.Integer, nullable=False, default=1)
    is_group = db.Column(db.Boolean, nullable=False, default=False)
    enabled_by_default = db.Column(db.Boolean, nullable=False, default=True)
    sort_order = db.Column(db.Integer, nullable=False, default=0)

    profile = db.relationship("RoomProfile", back_populates="items")
    category = db.relationship("EquipmentCategory")
    lot = db.relationship("Lot")


class RoomSurface(db.Model):
    """Composition facultative d'une surface réelle ou proposée."""
    __tablename__ = "room_surfaces"

    id = db.Column(db.Integer, primary_key=True)
    room_id = db.Column(db.Integer, db.ForeignKey("rooms.id", ondelete="CASCADE"), nullable=True, index=True)
    profile_id = db.Column(db.Integer, db.ForeignKey("room_profiles.id", ondelete="CASCADE"), nullable=True, index=True)
    surface_type = db.Column(db.String(30), nullable=False)  # mur, sol, plafond
    material = db.Column(db.String(80), nullable=False)
    finish = db.Column(db.String(80), nullable=True)
    label = db.Column(db.String(120), nullable=True)
    sort_order = db.Column(db.Integer, nullable=False, default=0)

    room = db.relationship("Room", backref=db.backref("surfaces", cascade="all, delete-orphan"))
    profile = db.relationship("RoomProfile", back_populates="surfaces")


class RoomSchedule(db.Model):
    """Emploi du temps d'une salle."""
    __tablename__ = "room_schedules"
    
    id = db.Column(db.Integer, primary_key=True)
    room_id = db.Column(db.Integer, db.ForeignKey("rooms.id"), nullable=False)
    week_start = db.Column(db.Date, nullable=False)
    day_of_week = db.Column(db.Integer, nullable=False)
    start_time = db.Column(db.Time, nullable=False)
    end_time = db.Column(db.Time, nullable=False)
    subject = db.Column(db.String(100), nullable=True)
    teacher = db.Column(db.String(100), nullable=True)
    class_name = db.Column(db.String(50), nullable=True)
    course_name = db.Column(db.String(255), nullable=True)
    source = db.Column(db.String(20), nullable=False, default="manual", index=True)
    external_id = db.Column(db.String(191), nullable=True, index=True)
    last_synced_at = db.Column(db.DateTime, nullable=True)
    source_updated_at = db.Column(db.DateTime, nullable=True)
    protected_from_sync = db.Column(db.Boolean, nullable=False, default=False, index=True)
    resolution_status = db.Column(db.String(20), nullable=False, default="active", index=True)
    valid_from = db.Column(db.Date, nullable=True)
    valid_to = db.Column(db.Date, nullable=True)
    event_type = db.Column(db.String(30), nullable=False, default="cours")
    conflict_note = db.Column(db.Text, nullable=True)
    created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
    
    # Relations
    room = db.relationship("Room", backref="schedules")
    
    def __repr__(self):
        return f"<RoomSchedule {self.room.name} - {self.day_of_week}>"
