from fastapi import APIRouter, Depends, Query, HTTPException
from sqlalchemy.orm import Session
from typing import Optional
from app.database import get_db
from app.models.assignment import Assignment
from app.models.mass_schedule import MassSchedule
from app.models.mass_template import MassTemplate
from app.models.special_mass import SpecialMass
from app.models.special_event import SpecialEvent
from app.models.position_type import PositionType
from app.models.asim import Asim
from app.models.user import User
from app.core.security import get_current_user
import calendar

router = APIRouter(prefix="/api/portal", tags=["Portal ASIM"])

@router.get("/jadwal-saya")
def get_jadwal_saya(
    asim_id: Optional[int] = Query(None),
    date_from: Optional[str] = Query(None),
    date_to: Optional[str] = Query(None),
    month: Optional[int] = Query(None),
    year: Optional[int] = Query(None),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    if current_user.role == "asim":
        if not current_user.asim:
            raise HTTPException(status_code=403, detail="Akun tidak terhubung ke data ASIM")
        asim_id = current_user.asim.id
    elif asim_id is None:
        raise HTTPException(status_code=400, detail="asim_id diperlukan")

    from datetime import date
    import datetime as dt

    if date_from and date_to:
        _date_from = dt.date.fromisoformat(date_from)
        _date_to = dt.date.fromisoformat(date_to)
    elif month and year:
        _date_from = date(year, month, 1)
        _date_to = date(year, month, calendar.monthrange(year, month)[1])
    else:
        today = dt.date.today()
        _date_from = date(today.year, today.month, 1)
        _date_to = date(today.year, today.month, calendar.monthrange(today.year, today.month)[1])

    assignments = db.query(Assignment).join(MassSchedule).filter(
        Assignment.asim_id == asim_id,
        MassSchedule.is_published == True,
        MassSchedule.date >= _date_from,
        MassSchedule.date <= _date_to,
    ).all()

    if not assignments:
        return []

    # Pre-batch: position types
    pt_codes = {a.position_type_code for a in assignments}
    pt_map = {pt.code: pt for pt in db.query(PositionType).filter(PositionType.code.in_(pt_codes)).all()}

    # Separate special vs weekly
    special_mass_ids = [a.schedule.special_mass_id for a in assignments if a.schedule.special_mass_id]
    template_ids = [a.schedule.template_id for a in assignments if a.schedule.template_id]

    # Pre-batch: special masses, events, templates
    sm_map = {}
    event_map = {}
    if special_mass_ids:
        sms = db.query(SpecialMass).filter(SpecialMass.id.in_(special_mass_ids)).all()
        sm_map = {sm.id: sm for sm in sms}
        event_ids = {sm.event_id for sm in sms}
        events = db.query(SpecialEvent).filter(SpecialEvent.id.in_(event_ids)).all()
        event_map = {e.id: e for e in events}

    template_map = {}
    if template_ids:
        templates = db.query(MassTemplate).filter(MassTemplate.id.in_(template_ids)).all()
        template_map = {t.id: t for t in templates}

    result = []
    for a in assignments:
        schedule = a.schedule
        pt = pt_map.get(a.position_type_code)
        is_special = schedule.special_mass_id is not None
        event_name = None
        mass_name = None
        template_name = None
        time = '-'

        if is_special:
            sm = sm_map.get(schedule.special_mass_id)
            if sm:
                event = event_map.get(sm.event_id)
                event_name = event.name if event else None
                mass_name = sm.name
                time = sm.time
        else:
            tmpl = template_map.get(schedule.template_id)
            if tmpl:
                time = tmpl.time
                template_name = tmpl.name

        result.append({
            "schedule_id": schedule.id,
            "date": str(schedule.date),
            "time": time,
            "position_number": a.position_number,
            "position_type_code": a.position_type_code,
            "position_type_color": pt.color if pt else None,
            "position_type_label": pt.label if pt else None,
            "is_published": schedule.is_published,
            "is_special": is_special,
            "event_name": event_name,
            "mass_name": mass_name,
            "template_name": template_name,
        })

    result.sort(key=lambda x: (x["date"], x["time"]))
    return result


@router.get("/jadwal-detail/{schedule_id}")
def get_jadwal_detail(schedule_id: int, db: Session = Depends(get_db)):
    from app.models.template_position import TemplatePosition
    from app.models.special_position import SpecialPosition

    schedule = db.query(MassSchedule).filter(MassSchedule.id == schedule_id).first()
    if not schedule:
        return []

    assignments = db.query(Assignment).filter(
        Assignment.schedule_id == schedule_id
    ).all()

    if not assignments:
        return []

    # Pre-batch: sort order from positions
    position_order = {}
    if schedule.special_mass_id:
        positions = db.query(SpecialPosition).filter(
            SpecialPosition.special_mass_id == schedule.special_mass_id
        ).all()
        for p in positions:
            position_order[p.position_number] = p.sort_order
    elif schedule.template_id:
        positions = db.query(TemplatePosition).filter(
            TemplatePosition.template_id == schedule.template_id
        ).all()
        for p in positions:
            position_order[p.position_number] = p.sort_order

    # Pre-batch: position types
    pt_codes = {a.position_type_code for a in assignments}
    pt_map = {pt.code: pt for pt in db.query(PositionType).filter(PositionType.code.in_(pt_codes)).all()}

    # Pre-batch: asim
    asim_ids = [a.asim_id for a in assignments if a.asim_id]
    asim_map = {}
    if asim_ids:
        asims = db.query(Asim).filter(Asim.id.in_(asim_ids)).all()
        asim_map = {asim.id: asim for asim in asims}

    result = []
    for a in assignments:
        pt = pt_map.get(a.position_type_code)
        asim = asim_map.get(a.asim_id) if a.asim_id else None
        result.append({
            "position_number": a.position_number,
            "position_type_code": a.position_type_code,
            "position_type_label": pt.label if pt else None,
            "position_type_color": pt.color if pt else None,
            "asim_id": a.asim_id,
            "no_asim": asim.no_asim if asim else None,
            "full_name": asim.full_name if asim else None,
            "photo": asim.photo if asim else None,
            "sort_order": position_order.get(a.position_number, 999),
        })

    result.sort(key=lambda x: x["sort_order"])
    return result
