# routes/attendance_admin.py
from flask import Blueprint, jsonify, render_template, request
from flask_login import login_required
from subprocess import Popen, PIPE
import sys, os

from extensions import db
from models import Employee, Department, Designation  # 🔹 add these

attendance_admin_bp = Blueprint("attendance_admin", __name__, url_prefix="/attendance-admin")


@attendance_admin_bp.route("/run-now", methods=["POST"])
@login_required
def run_attendance_now():
    """
    Trigger the daily attendance engine manually.
    Runs the CLI command:
        flask daily-attendance
    """
    project_root = os.getcwd()
    python_exec = sys.executable  # active venv python
    cmd = [python_exec, "-m", "flask", "daily-attendance"]

    try:
        proc = Popen(cmd, cwd=project_root, stdout=PIPE, stderr=PIPE)
        out, err = proc.communicate()

        return jsonify({
            "ok": True,
            "output": out.decode("utf-8"),
            "error": err.decode("utf-8")
        })
    except Exception as e:
        return jsonify({"ok": False, "error": str(e)}), 500


# ------------------------------
# NEW: Sync Tools Dashboard UI
# ------------------------------

@attendance_admin_bp.route("/sync-tools", methods=["GET"])
@login_required
def sync_tools_dashboard():
    """
    Render the UI page where admin/HR can trigger:
      - flask desktime-sync
      - flask biometric-sync
      - flask attendance-run
    with a date range + filters.
    """
    departments = Department.query.order_by(Department.name.asc()).all()
    designations = Designation.query.order_by(Designation.title.asc()).all()
    employees = Employee.query.order_by(Employee.full_name.asc()).all()

    return render_template(
        "sync_tools.html",
        departments=departments,
        designations=designations,
        employees=employees,
    )


@attendance_admin_bp.route("/run-sync", methods=["POST"])
@login_required
def run_sync_command():
    """
    Run one of the following commands based on the payload:
      - flask desktime-sync --from YYYY-MM-DD --to YYYY-MM-DD --employees <value>
      - flask biometric-sync --from YYYY-MM-DD --to YYYY-MM-DD --employees <value>
      - flask attendance-run --from YYYY-MM-DD --to YYYY-MM-DD --employees <value>

    Filters:
      - department_id
      - designation_id
      - employee_id

    Behaviour (fixed):
      - If no filters and sync_type != 'desktime' => employees='all'
      - For 'desktime':
          * If filters are applied => restrict to employees with desktime_id and pass explicit employee IDs
          * If NO filters => pass employees='all' (CLI should itself pick employees with desktime_id)
    """
    data = request.get_json() or request.form

    sync_type = (data.get("sync_type") or "").strip()
    from_date = (data.get("from_date") or "").strip()
    to_date = (data.get("to_date") or "").strip()

    department_id = (data.get("department_id") or "").strip() or None
    designation_id = (data.get("designation_id") or "").strip() or None
    employee_id = (data.get("employee_id") or "").strip() or None

    # Map UI type -> actual flask CLI command name
    command_map = {
        "desktime": "desktime-sync",
        "biometric": "biometric-sync",
        "attendance": "attendance-run",
    }

    if sync_type not in command_map:
        return jsonify({"ok": False, "error": "Invalid sync type"}), 400

    if not from_date or not to_date:
        return jsonify({"ok": False, "error": "From and To dates are required"}), 400

    # -----------------------------
    # Build employee query from filters
    # -----------------------------
    query = Employee.query
    has_any_filter = False

    if department_id:
        try:
            dept_id_int = int(department_id)
            query = query.filter(Employee.department_id == dept_id_int)
            has_any_filter = True
        except ValueError:
            pass

    if designation_id:
        try:
            desig_id_int = int(designation_id)
            query = query.filter(Employee.designation_id == desig_id_int)
            has_any_filter = True
        except ValueError:
            pass

    if employee_id:
        try:
            emp_id_int = int(employee_id)
            query = query.filter(Employee.id == emp_id_int)
            has_any_filter = True
        except ValueError:
            pass

    # DeskTime-only: apply DeskTime-id constraint for filtered runs
    # (for unfiltered "all", we let CLI handle it by passing employees=all)
    if sync_type == "desktime" and has_any_filter:
        query = query.filter(
            Employee.desktime_id.isnot(None),
            Employee.desktime_id != "",
            Employee.desktime_id != 0,  # safe if desktime_id is int; harmless if string
        )

    employees_param = "all"
    employee_count = None

    # -----------------------------
    # Decide employees_param
    # -----------------------------
    if sync_type == "desktime":
        if has_any_filter:
            matched_emps = query.all()

            if not matched_emps:
                return jsonify({
                    "ok": False,
                    "error": "No employees with DeskTime ID found for selected filters."
                }), 400

            # IMPORTANT: pass Employee IDs (PK), not employee_code
            emp_ids = [str(e.id) for e in matched_emps]
            employees_param = ",".join(emp_ids)
            employee_count = len(emp_ids)
        else:
            # NO filters: run for ALL (CLI should internally restrict to employees with desktime_id)
            employees_param = "all"
            # Optional: show how many have desktime_id
            employee_count = Employee.query.filter(
                Employee.desktime_id.isnot(None),
                Employee.desktime_id != "",
                Employee.desktime_id != 0,
            ).count()

    else:
        # biometric / attendance
        if has_any_filter:
            matched_emps = query.all()

            if not matched_emps:
                return jsonify({"ok": False, "error": "No employees found for selected filters."}), 400

            # Pass Employee IDs (PK)
            emp_ids = [str(e.id) for e in matched_emps]
            employees_param = ",".join(emp_ids)
            employee_count = len(emp_ids)
        else:
            employees_param = "all"
            employee_count = None

    project_root = os.getcwd()
    python_exec = sys.executable
    base_cmd = [
        python_exec,
        "-m",
        "flask",
        command_map[sync_type],
        "--from",
        from_date,
        "--to",
        to_date,
        "--employees",
        employees_param,
    ]

    try:
        proc = Popen(base_cmd, cwd=project_root, stdout=PIPE, stderr=PIPE)
        out, err = proc.communicate()

        return jsonify({
            "ok": proc.returncode == 0,
            "command": " ".join(base_cmd),
            "output": out.decode("utf-8"),
            "error": err.decode("utf-8"),
            "employees_param": employees_param,
            "employee_count": employee_count,
        })
    except Exception as e:
        return jsonify({"ok": False, "error": str(e)}), 500