import calendar
from calendar import monthrange
from flask import Blueprint, render_template, request, redirect, url_for, flash
from flask_login import login_required
from datetime import datetime,date, timedelta
from models import Attendance, Employee, Payroll,WeekendSettings,Holiday
from extensions import db

attendance_summary_bp = Blueprint('attendance_summary', __name__)

@attendance_summary_bp.route('/attendance/monthly-summary', methods=['GET'])
@login_required
def monthly_attendance_summary():
    selected_month = request.args.get('month') or datetime.today().strftime('%Y-%m')
    employee_name = request.args.get('employee_name', '')

    try:
        month_year = datetime.strptime(selected_month, '%Y-%m')
    except ValueError:
        flash('Invalid month format', 'danger')
        return redirect(request.referrer)

    year = month_year.year
    month = month_year.month
    _, last_day = calendar.monthrange(year, month)
    month_end_date = datetime(year, month, last_day).date()

    employees = Employee.query.filter_by(status='active')
    employees = employees.filter(Employee.date_of_joining <= month_end_date)

    if employee_name:
        employees = employees.filter(Employee.full_name.ilike(f"%{employee_name}%"))

    employees = employees.order_by(Employee.full_name).all()

    frozen_employee_ids = {
        p.employee_id for p in Payroll.query.filter_by(month=selected_month).all()
    }

    summary_data = []
    for emp in employees:
        emp_data = {
            'employee': emp,
            'days': []
        }
        for day in range(1, last_day + 1):
            date_obj = datetime(year, month, day).date()
            attendance = Attendance.query.filter_by(employee_id=emp.id, date=date_obj).first()
            emp_data['days'].append({
                'date': date_obj,
                'record': attendance
            })

        emp_data['payroll_frozen'] = emp.id in frozen_employee_ids
        summary_data.append(emp_data)

    return render_template(
        'attendance/attendance_monthly_summary.html',
        summary_data=summary_data,
        selected_month=selected_month,
        employee_name=employee_name
    )
@attendance_summary_bp.route('/attendance/manual-update', methods=['POST'])
@login_required
def manual_update_attendance():
    employee_id = request.form.get('employee_id')
    date_str = request.form.get('date')
    remarks = request.form.get('remarks')
    note = (request.form.get('note') or '').strip()

    try:
        date = datetime.strptime(date_str, '%Y-%m-%d').date()
    except ValueError:
        flash('Invalid date format', 'danger')
        return redirect(request.referrer)

    # Check if payroll is frozen
    month_str = date.strftime('%Y-%m')
    if Payroll.query.filter_by(employee_id=employee_id, month=month_str).first():
        flash('❌ Cannot update. Payroll frozen for this employee.', 'danger')
        return redirect(request.referrer)

    # Fetch or create attendance
    attendance = Attendance.query.filter_by(employee_id=employee_id, date=date).first()
    if not attendance:
        attendance = Attendance(employee_id=employee_id, date=date)
        db.session.add(attendance)

    attendance.remarks = remarks
    attendance.source = 'Manual'
    if hasattr(attendance, 'note'):      # only if you've added this column
        attendance.note = note
    db.session.commit()

    flash('✅ Attendance updated.', 'success')
    return redirect(request.referrer)

# routes/attendance_summary.py
@attendance_summary_bp.route('/attendance/bulk-month-update', methods=['POST'])
@login_required
def bulk_month_update():
    from calendar import monthrange
    month = request.form.get('month')            # "YYYY-MM"
    status = request.form.get('status')          # Present/Half Day/Leave/Holiday/Weekend/LWP or blank
    note = (request.form.get('note') or '').strip()
    skip_weekends = bool(request.form.get('skip_weekends'))
    skip_holidays = bool(request.form.get('skip_holidays'))
    employee_ids = request.form.getlist('employee_ids')  # list of strings

    # validate
    try:
        y, m = map(int, month.split('-'))
    except Exception:
        flash('Invalid month.', 'danger')
        return redirect(request.referrer)

    if not employee_ids:
        flash('Select at least one employee.', 'warning')
        return redirect(request.referrer)

    # weekend config
    weekend_cfg = WeekendSettings.query.order_by(WeekendSettings.updated_on.desc()).first()
    sun_off = weekend_cfg and weekend_cfg.sunday == 'off'
    def is_saturday_off(day):
        if not weekend_cfg: return False
        week_number = (day.day - 1) // 7 + 1
        attr = f"{['first','second','third','fourth','fifth'][week_number-1]}_saturday"
        return getattr(weekend_cfg, attr) == 'off'

    # month range
    last_day = monthrange(y, m)[1]
    start_date = date(y, m, 1)
    end_date = date(y, m, last_day)

    # payroll freeze map for fast checks
    frozen = {(p.employee_id) for p in Payroll.query.filter_by(month=month).all()}

    updated, skipped_frozen = 0, 0
    for eid_str in employee_ids:
        try:
            eid = int(eid_str)
        except ValueError:
            continue

        # frozen — skip
        if eid in frozen:
            skipped_frozen += 1
            continue

        emp = Employee.query.get(eid)
        if not emp:
            continue

        d = start_date
        while d <= end_date:
            # skip pre-join days
            if emp.date_of_joining and d < emp.date_of_joining:
                d += timedelta(days=1); continue

            # weekend/holiday logic
            wd = d.weekday()
            is_we = (wd == 6 and sun_off) or (wd == 5 and is_saturday_off(d))
            is_hol = Holiday.query.filter_by(date=d).first() is not None

            if skip_weekends and is_we:
                d += timedelta(days=1); continue
            if skip_holidays and is_hol:
                d += timedelta(days=1); continue

            att = Attendance.query.filter_by(employee_id=eid, date=d).first()
            if not att:
                att = Attendance(employee_id=eid, date=d)
                db.session.add(att)

            att.remarks = status or ''  # allow clearing if needed
            att.source = 'Bulk'
            if hasattr(att, 'note'):
                att.note = note
            updated += 1
            d += timedelta(days=1)

    db.session.commit()
    msg = f"✅ Bulk update done. {updated} day(s) marked."
    if skipped_frozen:
        msg += f" Skipped {skipped_frozen} employee(s) due to payroll freeze."
    flash(msg, 'success')
    return redirect(request.referrer or url_for('attendance_summary.monthly_attendance_summary'))