"""
Modele Contract - GMAO College
Suivi des contrats d'entreprise pour les equipements/lots.
"""
from datetime import datetime, timezone, date
from ..extensions import db


class Contract(db.Model):
    """Contrat d'entreprise pour un lot ou un equipement."""
    __tablename__ = "contracts"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(200), nullable=False)
    contract_number = db.Column(db.String(100), nullable=True)
    
    # Liaison : un contrat est lie a un lot et/ou un equipement
    lot_id = db.Column(db.Integer, db.ForeignKey("lots.id"), nullable=True)
    equipment_id = db.Column(db.Integer, db.ForeignKey("equipments.id"), nullable=True)
    company_id = db.Column(db.Integer, db.ForeignKey("companies.id"), nullable=True)
    
    # Dates
    signed_date = db.Column(db.Date, nullable=True)
    start_date = db.Column(db.Date, nullable=False)
    end_date = db.Column(db.Date, nullable=True)  # NULL = duree indeterminee
    
    # Tacite reconduction
    tacit_renewal = db.Column(db.Boolean, default=True)
    renewal_period_days = db.Column(db.Integer, default=365)  # reconduction par periode de X jours
    
    # Delai de preavis pour resilier (en jours avant la date de fin)
    notice_period_days = db.Column(db.Integer, nullable=True)
    notice_deadline = db.Column(db.Date, nullable=True)  # date limite pour envoyer le preavis
    
    # Montant
    annual_amount = db.Column(db.Float, nullable=True)
    currency = db.Column(db.String(3), default="EUR")
    
    # Statut
    status = db.Column(db.String(20), default="actif")  # actif, expire, resilie, en_attente
    notes = db.Column(db.Text, nullable=True)
    visit_interval_days = db.Column(db.Integer, nullable=True)
    last_visit_date = db.Column(db.Date, nullable=True)
    next_visit_date = db.Column(db.Date, nullable=True)
    
    # Documents
    contract_file = db.Column(db.String(500), nullable=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
    lot = db.relationship("Lot", backref=db.backref("contracts", lazy="dynamic"))
    equipment = db.relationship("Equipment", backref=db.backref("contracts", lazy="dynamic"))
    company = db.relationship("Company", backref=db.backref("contracts", lazy="dynamic"))
    visits = db.relationship("ContractVisit", back_populates="contract", cascade="all, delete-orphan",
                             order_by="ContractVisit.scheduled_date")
    
    @property
    def is_active(self):
        """True si le contrat est actif aujourd'hui."""
        if self.status != "actif":
            return False
        today = date.today()
        if self.start_date and today < self.start_date:
            return False
        if self.end_date and today > self.end_date:
            return False
        return True
    
    @property
    def is_expiring_soon(self):
        """True si le contrat expire dans les 90 prochains jours."""
        if not self.end_date:
            return False
        days_left = (self.end_date - date.today()).days
        return 0 <= days_left <= 90
    
    @property
    def days_until_expiry(self):
        """Nombre de jours avant l'expiration (negatif = expire)."""
        if not self.end_date:
            return None
        return (self.end_date - date.today()).days
    
    @property
    def notice_deadline_calculated(self):
        """Calcule la date limite de preavis si pas definie manuellement."""
        if self.notice_deadline:
            return self.notice_deadline
        if self.end_date and self.notice_period_days:
            from datetime import timedelta
            return self.end_date - timedelta(days=self.notice_period_days)
        return None
    
    @property
    def must_send_notice_now(self):
        """True si le preavis doit etre envoye maintenant (deadline proche)."""
        deadline = self.notice_deadline_calculated
        if not deadline:
            return False
        days_left = (deadline - date.today()).days
        return days_left <= 60  # alerte 60 jours avant
    
    @property
    def status_color(self):
        """Couleur du badge."""
        if not self.is_active:
            return "danger" if self.status == "expire" else "secondary"
        if self.is_expiring_soon:
            return "warning"
        if self.must_send_notice_now:
            return "warning"
        return "success"
    
    def __repr__(self):
        return f"<Contract {self.name} ({self.status})>"


class ContractVisit(db.Model):
    """Visite planifiée ou réalisée par le prestataire d'un contrat."""
    __tablename__ = "contract_visits"
    __table_args__ = (db.UniqueConstraint("contract_id", "scheduled_date", name="uq_contract_visit_date"),)

    id = db.Column(db.Integer, primary_key=True)
    contract_id = db.Column(db.Integer, db.ForeignKey("contracts.id", ondelete="CASCADE"), nullable=False, index=True)
    scheduled_date = db.Column(db.Date, nullable=False, index=True)
    status = db.Column(db.String(30), nullable=False, default="planifiee")
    lot_task_id = db.Column(db.Integer, db.ForeignKey("lot_tasks.id", ondelete="SET NULL"), nullable=True, index=True)
    passage_mode = db.Column(db.String(20), nullable=False, default="appointment")
    start_time = db.Column(db.Time, nullable=True)
    end_time = db.Column(db.Time, nullable=True)
    window_start = db.Column(db.Date, nullable=True)
    window_end = db.Column(db.Date, nullable=True)
    actual_date = db.Column(db.Date, nullable=True)
    arrival_at = db.Column(db.DateTime, nullable=True)
    accompaniment_mode = db.Column(db.String(20), nullable=False, default="none")
    accompaniment_minutes = db.Column(db.Integer, nullable=True)
    technician_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
    completed_at = db.Column(db.DateTime, nullable=True)
    report = db.Column(db.Text, nullable=True)
    created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)

    contract = db.relationship("Contract", back_populates="visits")
    lot_task = db.relationship("LotTask")
    technician = db.relationship("User")

    @property
    def is_fixed_for_planning(self):
        return self.passage_mode == "appointment" and self.start_time is not None

    @property
    def display_mode(self):
        return {
            "appointment": "Sur rendez-vous",
            "date_only": "Date connue, heure inconnue",
            "open_window": "Passage libre / sans rendez-vous",
        }.get(self.passage_mode, self.passage_mode)
