"""
Meeting request handling for MyACC Virtual Assistant.

Students submit meeting requests, which are stored in ./data/meetings/.
The appropriate staff member receives a notification email, and the request
can be accepted or declined from the planner view.
Students receive a follow-up email with the decision, and confirmed meetings
appear in the planner dashboards.

Email settings are configured through the .env file. If email values are left
blank, the app continues to function, but outgoing notifications are skipped.
"""

import json
import logging
import smtplib
from datetime import datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from pathlib import Path
from typing import Dict, List, Optional
from uuid import uuid4

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel

from app.auth import get_current_user
from app.config import get_settings

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/meetings", tags=["meetings"])

# Storage
_MEETINGS_DIR: Optional[Path] = None

def _meetings_dir() -> Path:
    global _MEETINGS_DIR
    if _MEETINGS_DIR is None:
        _MEETINGS_DIR = Path("./data/meetings")
        _MEETINGS_DIR.mkdir(parents=True, exist_ok=True)
    return _MEETINGS_DIR

def _load_meeting(meeting_id: str) -> Optional[Dict]:
    path = _meetings_dir() / f"{meeting_id}.json"
    if not path.exists():
        return None
    try:
        return json.loads(path.read_text(encoding="utf-8"))
    except Exception as exc:
        logger.warning("Could not load meeting %s: %s", meeting_id, exc)
        return None

def _save_meeting(meeting: Dict) -> None:
    path = _meetings_dir() / f"{meeting['meeting_id']}.json"
    path.write_text(json.dumps(meeting, indent=2, ensure_ascii=False), encoding="utf-8")

def _all_meetings() -> List[Dict]:
    meetings = []
    for p in _meetings_dir().glob("*.json"):
        try:
            meetings.append(json.loads(p.read_text(encoding="utf-8")))
        except Exception:
            continue
    meetings.sort(key=lambda m: m.get("requested_at", ""), reverse=True)
    return meetings


# Staff email map
# Replace these placeholder values with actual ACC staff email addresses.
# Format: "login_username": "real.email@austincc.edu"
STAFF_EMAILS: Dict[str, str] = {
    "advisor":       "advisor@austincc.edu",       # Replace with real email
    "counselor":     "counselor@austincc.edu",     # Replace with real email
    "financial-aid": "financialaid@austincc.edu",  # Replace with real email
}

# Human-readable role names shown in emails
ROLE_LABELS: Dict[str, str] = {
    "advisor":       "Academic Advisor",
    "counselor":     "Counselor",
    "financial-aid": "Financial Aid Officer",
}


# Email helper
def _send_email(to: str, subject: str, body_html: str) -> bool:
    """
    Thin shim around app.email_provider.send_email.
    The actual backend (Gmail API or SMTP) is chosen by EMAIL_BACKEND in .env.
    Kept here so existing call sites in this module don't need to change.
    """
    from app.email_provider import send_email
    return send_email(to, subject, body_html)


def _email_to_staff(meeting: Dict) -> None:
    """Send meeting request notification email to the staff member."""
    staff_role  = meeting.get("staff_role", "")
    staff_email = STAFF_EMAILS.get(staff_role, "")
    if not staff_email:
        logger.warning("No email configured for role: %s", staff_role)
        return

    role_label    = ROLE_LABELS.get(staff_role, staff_role.title())
    student_name  = meeting.get("student_name", "A student")
    preferred_date = meeting.get("preferred_date", "TBD")
    preferred_time = meeting.get("preferred_time", "TBD")
    reason         = meeting.get("reason", "Not specified")
    meeting_id     = meeting.get("meeting_id", "")

    subject = f"[MyACC Virtual Assistant] New Meeting Request from {student_name}"
    body    = f"""
    <html><body style="font-family: Arial, sans-serif; color: #333;">
    <h2 style="color:#007bff;">New Meeting Request</h2>
    <p>Dear {role_label},</p>
    <p><strong>{student_name}</strong> has requested a meeting with you.</p>
    <table style="border-collapse:collapse; width:100%; max-width:500px;">
        <tr><td style="padding:8px; border:1px solid #ddd;"><strong>Date Requested</strong></td>
            <td style="padding:8px; border:1px solid #ddd;">{preferred_date}</td></tr>
        <tr><td style="padding:8px; border:1px solid #ddd;"><strong>Time Requested</strong></td>
            <td style="padding:8px; border:1px solid #ddd;">{preferred_time}</td></tr>
        <tr><td style="padding:8px; border:1px solid #ddd;"><strong>Reason</strong></td>
            <td style="padding:8px; border:1px solid #ddd;">{reason}</td></tr>
        <tr><td style="padding:8px; border:1px solid #ddd;"><strong>Meeting ID</strong></td>
            <td style="padding:8px; border:1px solid #ddd;">{meeting_id}</td></tr>
    </table>
    <p style="margin-top:20px;">Please log in to <strong>MyACC Virtual Assistant</strong> to Accept or Decline this request.</p>
    <p style="color:#888; font-size:12px;">This is an automated message from MyACC Virtual Assistant. Do not reply directly.</p>
    </body></html>
    """
    _send_email(staff_email, subject, body)


def _email_to_student(meeting: Dict, decision: str) -> None:
    """Send Accept/Decline notification email to the student."""
    student_email = meeting.get("student_email", "")
    if not student_email:
        logger.warning("No student email on meeting %s — skipping notification", meeting.get("meeting_id"))
        return

    student_name  = meeting.get("student_name", "Student")
    staff_role    = meeting.get("staff_role", "")
    role_label    = ROLE_LABELS.get(staff_role, staff_role.title())
    preferred_date = meeting.get("preferred_date", "TBD")
    preferred_time = meeting.get("preferred_time", "TBD")
    note           = meeting.get("staff_note", "")

    if decision == "accepted":
        status_text = "Accepted"
        color       = "#28a745"
        msg         = "Your meeting has been confirmed. Please attend at the scheduled time."
    else:
        status_text = "Declined"
        color       = "#dc3545"
        msg         = "Your meeting request was declined. Please submit a new request with a different date/time."

    subject = f"[MyACC Virtual Assistant] Your Meeting Request was {decision.title()}"
    body    = f"""
    <html><body style="font-family: Arial, sans-serif; color: #333;">
    <h2 style="color:{color};">Meeting Request {status_text}</h2>
    <p>Dear {student_name},</p>
    <p>{msg}</p>
    <table style="border-collapse:collapse; width:100%; max-width:500px;">
        <tr><td style="padding:8px; border:1px solid #ddd;"><strong>With</strong></td>
            <td style="padding:8px; border:1px solid #ddd;">{role_label}</td></tr>
        <tr><td style="padding:8px; border:1px solid #ddd;"><strong>Date</strong></td>
            <td style="padding:8px; border:1px solid #ddd;">{preferred_date}</td></tr>
        <tr><td style="padding:8px; border:1px solid #ddd;"><strong>Time</strong></td>
            <td style="padding:8px; border:1px solid #ddd;">{preferred_time}</td></tr>
        {"<tr><td style='padding:8px; border:1px solid #ddd;'><strong>Note from Staff</strong></td><td style='padding:8px; border:1px solid #ddd;'>" + note + "</td></tr>" if note else ""}
    </table>
    <p style="color:#888; font-size:12px;">This is an automated message from MyACC Virtual Assistant. Do not reply directly.</p>
    </body></html>
    """
    _send_email(student_email, subject, body)


# Pydantic models
class MeetingRequest(BaseModel):
    staff_role:     str   # "advisor" | "counselor" | "financial-aid"
    preferred_date: str   # e.g. "2026-05-10"
    preferred_time: str   # e.g. "10:00 AM"
    reason:         str   # student's reason for meeting


class MeetingDecision(BaseModel):
    decision:   str             # "accepted" | "declined"
    staff_note: str = ""        # optional message back to student


# API Endpoints

@router.post("/request")
async def request_meeting(
    body: MeetingRequest,
    current_user: Dict = Depends(get_current_user),
):
    """
    Student submits a meeting request.
    Creates a meeting record and emails the staff member.
    """
    if current_user.get("role") != "student":
        raise HTTPException(status_code=403, detail="Only students can request meetings.")

    if body.staff_role not in ("advisor", "counselor", "financial-aid"):
        raise HTTPException(status_code=400, detail="Invalid staff role.")

    student_name  = current_user.get("first_name", "") or current_user.get("username", "Student")
    last_name     = current_user.get("last_name", "")
    if last_name:
        student_name = f"{student_name} {last_name}"

    meeting = {
        "meeting_id":     str(uuid4()),
        "student_id":     current_user.get("username"),
        "student_name":   student_name,
        "student_email":  current_user.get("email", ""),
        "staff_role":     body.staff_role,
        "preferred_date": body.preferred_date,
        "preferred_time": body.preferred_time,
        "reason":         body.reason,
        "status":         "pending",   # pending | accepted | declined
        "staff_note":     "",
        "requested_at":   datetime.utcnow().isoformat(),
        "decided_at":     None,
    }

    _save_meeting(meeting)
    logger.info("Meeting request created: %s by student %s", meeting["meeting_id"], meeting["student_id"])

    # Send email to staff member
    _email_to_staff(meeting)

    return {
        "status":     "ok",
        "meeting_id": meeting["meeting_id"],
        "message":    f"Your meeting request has been sent to the {ROLE_LABELS.get(body.staff_role, body.staff_role)}. You will be notified by email once they respond.",
    }


@router.post("/{meeting_id}/decide")
async def decide_meeting(
    meeting_id: str,
    body: MeetingDecision,
    current_user: Dict = Depends(get_current_user),
):
    """
    Staff member accepts or declines a meeting request.
    Updates the record and emails the student.
    """
    role = current_user.get("role")
    if role not in ("advisor", "counselor", "financial-aid"):
        raise HTTPException(status_code=403, detail="Only staff can accept or decline meetings.")

    if body.decision not in ("accepted", "declined"):
        raise HTTPException(status_code=400, detail="Decision must be 'accepted' or 'declined'.")

    meeting = _load_meeting(meeting_id)
    if not meeting:
        raise HTTPException(status_code=404, detail="Meeting not found.")

    if meeting.get("staff_role") != role:
        raise HTTPException(status_code=403, detail="This meeting was not assigned to your role.")

    if meeting.get("status") != "pending":
        raise HTTPException(status_code=400, detail="This meeting has already been decided.")

    meeting["status"]     = body.decision
    meeting["staff_note"] = body.staff_note
    meeting["decided_at"] = datetime.utcnow().isoformat()
    _save_meeting(meeting)

    logger.info("Meeting %s %s by %s", meeting_id, body.decision, current_user.get("username"))

    # Email the student
    _email_to_student(meeting, body.decision)

    return {
        "status":     "ok",
        "meeting_id": meeting_id,
        "decision":   body.decision,
        "message":    f"Meeting {body.decision}. Student has been notified by email.",
    }


@router.get("/my")
async def my_meetings(current_user: Dict = Depends(get_current_user)):
    """
    Returns meetings relevant to the logged-in user.
    - Students see their own requests.
    - Staff see requests assigned to their role.
    """
    role     = current_user.get("role")
    username = current_user.get("username")
    all_m    = _all_meetings()

    if role == "student":
        return {"meetings": [m for m in all_m if m.get("student_id") == username]}
    else:
        return {"meetings": [m for m in all_m if m.get("staff_role") == role]}


@router.get("/pending-count")
async def pending_count(current_user: Dict = Depends(get_current_user)):
    """
    Returns count of pending meeting requests for the logged-in staff member.
    Used by dashboard to show the notification badge.
    """
    role = current_user.get("role")
    if role == "student":
        return {"count": 0}
    all_m = _all_meetings()
    count = sum(1 for m in all_m if m.get("staff_role") == role and m.get("status") == "pending")
    return {"count": count}