"""
Lawyer Recommendation Service
"""
from typing import List, Optional
from sqlalchemy.orm import Session

from ..models.models import Lawyer, User


def get_lawyer_for_user(db: Session, user: User) -> Optional[Lawyer]:
    """
    Find the lawyer profile linked to this logged-in lawyer user.
    Priority:
      1. Exact email match (profile already claimed by this user)
      2. Auto-assign an UNCLAIMED profile in the user's city
      3. Auto-assign any unclaimed profile
    A profile is "claimed" when its contact_email belongs to another
    registered user — those are never reassigned, so two lawyer
    accounts can no longer steal profiles from each other.
    Saves the link so future logins are instant.
    """
    lawyer = db.query(Lawyer).filter(Lawyer.contact_email == user.email).first()
    if lawyer:
        return lawyer

    other_user_emails = [
        e for (e,) in db.query(User.email).filter(User.email != user.email).all()
    ]
    unclaimed = db.query(Lawyer)
    if other_user_emails:
        unclaimed = unclaimed.filter(~Lawyer.contact_email.in_(other_user_emails))

    if user.city:
        lawyer = unclaimed.filter(Lawyer.city.ilike(f"%{user.city}%")).first()
    if not lawyer:
        lawyer = unclaimed.first()

    if lawyer:
        lawyer.contact_email = user.email
        db.commit()
    return lawyer


def recommend_lawyers(
    db: Session,
    category: str,
    city: Optional[str] = None,
    top_n: int = 5,
) -> List[dict]:
    exact = db.query(Lawyer).filter(Lawyer.specialization == category).all()
    if len(exact) < top_n:
        others = db.query(Lawyer).filter(Lawyer.specialization != category).all()
        all_lawyers = exact + others
    else:
        all_lawyers = exact

    def score(l: Lawyer) -> float:
        s = 50.0 if l.specialization == category else 0.0
        if city and l.city and l.city.lower() == city.lower():
            s += 20.0
        s += (l.rating / 5.0) * 15.0
        s += (l.success_rate_percentage / 100.0) * 10.0
        s += min(l.experience_years / 30.0, 1.0) * 5.0
        return round(s, 2)

    scored = sorted(all_lawyers, key=score, reverse=True)[:top_n]
    results = []
    for l in scored:
        ms = score(l)
        parts = []
        if l.specialization == category:
            parts.append(f"Specializes in {category}")
        if city and l.city and l.city.lower() == city.lower():
            parts.append(f"Based in {l.city}")
        parts += [f"{l.experience_years} yrs exp", f"{l.success_rate_percentage}% success", f"Rated {l.rating}/5.0"]
        results.append({"lawyer": l, "match_score": ms, "reason": " • ".join(parts)})
    return results


def get_all_lawyers(db: Session) -> List[Lawyer]:
    return db.query(Lawyer).order_by(Lawyer.rating.desc()).all()


def get_lawyer_by_id(db: Session, lawyer_id: int) -> Optional[Lawyer]:
    return db.query(Lawyer).filter(Lawyer.id == lawyer_id).first()
