from datetime import date, datetime, timedelta
from zoneinfo import ZoneInfo
from typing import List, Optional, Tuple

from flask import current_app
from flask_mail import Message

from extensions import db, mail
from models import Employee, Role, BirthdayEmailLog


def _employee_email(emp: Employee) -> Optional[str]:
    return (
        getattr(emp, "email", None)
        or getattr(emp, "work_email", None)
        or getattr(emp, "personal_email", None)
    )


def _get_mail_sender():
    sender = current_app.config.get("MAIL_DEFAULT_SENDER")
    if sender:
        return sender
    return current_app.config.get("MAIL_USERNAME")


def _hr_emails() -> List[str]:
    """All HR users"""
    emails = []
    try:
        hrs = Employee.query.join(Role).filter(Role.name.ilike("%hr%")).all()
        for e in hrs:
            em = _employee_email(e)
            if em:
                emails.append(em)
    except Exception:
        pass
    return sorted(set(emails))


def _manager_email(emp: Employee) -> Optional[str]:
    """Reporting Manager email"""
    mgr = getattr(emp, "reporting_manager", None)
    if mgr:
        return _employee_email(mgr)
    return None


def send_birthday_reminders(
    lead_days: int = 2,
    tz_name: str = "Asia/Kolkata"
) -> Tuple[int, int]:
    """
    Sends birthday reminder email to Reporting Manager + HR
    lead_days before DOB.
    """

    tz = ZoneInfo(tz_name)
    today = datetime.now(tz).date()
    target_date = today + timedelta(days=lead_days)

    sender = _get_mail_sender()
    if not sender:
        current_app.logger.warning("Birthday reminder: mail sender not configured.")
        return (0, 0)

    employees = Employee.query.filter_by(status="active").all()

    sent, skipped = 0, 0

    for emp in employees:
        dob = getattr(emp, "dob", None) or getattr(emp, "date_of_birth", None)
        if not dob:
            skipped += 1
            continue

        # match month + day
        if dob.month != target_date.month or dob.day != target_date.day:
            continue

        # prevent duplicate mail per year
        exists = BirthdayEmailLog.query.filter_by(
            employee_id=emp.id,
            year=target_date.year
        ).first()
        if exists:
            skipped += 1
            continue

        recipients = []

        mgr_email = _manager_email(emp)
        if mgr_email:
            recipients.append(mgr_email)

        recipients.extend(_hr_emails())
        recipients = sorted(set([r for r in recipients if r]))

        if not recipients:
            skipped += 1
            continue

        subject = f"[Reminder] {emp.full_name}'s birthday on {target_date.strftime('%d %b')}"
        dept = emp.department.name if emp.department else "-"

        body = f"""
Hello,

This is a reminder that {emp.full_name}
(Employee Code: {emp.employee_code or '-'})
Department: {dept}

has a birthday on {target_date.strftime('%d %B %Y')}.

Please plan greetings accordingly.

— HRMS Automated Notification
"""

        msg = Message(
            subject=subject,
            recipients=recipients,
            body=body.strip(),
            sender=sender
        )

        mail.send(msg)

        db.session.add(BirthdayEmailLog(
            employee_id=emp.id,
            year=target_date.year,
            target_date=target_date,
            recipients=",".join(recipients),
            subject=subject,
            sent_at=datetime.utcnow()
        ))
        db.session.commit()

        sent += 1

    return sent, skipped