<?php
class DriverAssignments extends Model
{
    private function s($v): string { return trim((string)$v); }

    /**
     * Paginated list with filters.  Filters: driver_id, truck_id,
     * status = 'active' | 'ended' | ''.
     */
    public function listPaginated(int $page, int $perPage, array $filters = []): array
    {
        $where  = ['a.deleted = 0', 'a.tenant_id = :tenant'];
        $params = [':tenant' => defined('DEFAULT_TENANT_ID') ? DEFAULT_TENANT_ID : 1];

        if (!empty($filters['driver_id'])) { $where[] = 'a.driver_id = :did'; $params[':did'] = (int)$filters['driver_id']; }
        if (!empty($filters['truck_id']))  { $where[] = 'a.truck_id  = :tid'; $params[':tid'] = (int)$filters['truck_id']; }
        if (!empty($filters['status'])) {
            if ($filters['status'] === 'active') $where[] = 'a.assigned_to IS NULL';
            elseif ($filters['status'] === 'ended') $where[] = 'a.assigned_to IS NOT NULL';
        }

        $whereSql = implode(' AND ', $where);
        $db = new DB();

        $countRs = $db->mySelect("SELECT COUNT(*) AS n FROM driver_truck_assignments a WHERE $whereSql", $params);
        $total   = (int)($countRs[0]['n'] ?? 0);

        $page    = max(1, $page);
        $perPage = max(1, min(200, $perPage));
        $offset  = ($page - 1) * $perPage;

        $rows = $db->mySelect(
            "SELECT a.c0d, a.driver_id, a.truck_id, a.assigned_from, a.assigned_to,
                    a.role_type, a.reason,
                    d.full_name  AS driver_name, d.employee_no,
                    t.reg_no     AS truck_reg,   t.make, t.model
               FROM driver_truck_assignments a
          LEFT JOIN drivers d ON d.c0d = a.driver_id
          LEFT JOIN trucks  t ON t.c0d = a.truck_id
              WHERE $whereSql
           ORDER BY (a.assigned_to IS NULL) DESC, a.assigned_from DESC
              LIMIT $perPage OFFSET $offset",
            $params
        ) ?: [];

        return ['rows' => $rows, 'total' => $total];
    }

    /** Current active assignment for a driver (or empty array if none). */
    public function currentForDriver(int $driverId): array
    {
        $db = new DB();
        $rs = $db->mySelect(
            "SELECT a.*, t.reg_no AS truck_reg, t.make, t.model, t.truck_type_id
               FROM driver_truck_assignments a
          LEFT JOIN trucks t ON t.c0d = a.truck_id
              WHERE a.driver_id = :id AND a.assigned_to IS NULL AND a.deleted = 0
              LIMIT 1",
            [':id' => $driverId]
        );
        return $rs[0] ?? [];
    }

    /** All currently-active driver assignments on a specific truck. */
    public function activeForTruck(int $truckId): array
    {
        $db = new DB();
        return $db->mySelect(
            "SELECT a.*, d.full_name AS driver_name, d.employee_no, d.phone_1
               FROM driver_truck_assignments a
          LEFT JOIN drivers d ON d.c0d = a.driver_id
              WHERE a.truck_id = :id AND a.assigned_to IS NULL AND a.deleted = 0
           ORDER BY a.role_type = 'primary' DESC, a.assigned_from DESC",
            [':id' => $truckId]
        ) ?: [];
    }

    /** History (both active and ended) for a driver or a truck. */
    public function historyForDriver(int $driverId, int $limit = 20): array
    {
        $db = new DB();
        $limit = max(1, min(500, $limit));
        return $db->mySelect(
            "SELECT a.*, t.reg_no AS truck_reg, t.make, t.model
               FROM driver_truck_assignments a
          LEFT JOIN trucks t ON t.c0d = a.truck_id
              WHERE a.driver_id = :id AND a.deleted = 0
           ORDER BY (a.assigned_to IS NULL) DESC, a.assigned_from DESC
              LIMIT $limit",
            [':id' => $driverId]
        ) ?: [];
    }

    public function historyForTruck(int $truckId, int $limit = 20): array
    {
        $db = new DB();
        $limit = max(1, min(500, $limit));
        return $db->mySelect(
            "SELECT a.*, d.full_name AS driver_name, d.employee_no, d.phone_1
               FROM driver_truck_assignments a
          LEFT JOIN drivers d ON d.c0d = a.driver_id
              WHERE a.truck_id = :id AND a.deleted = 0
           ORDER BY (a.assigned_to IS NULL) DESC, a.assigned_from DESC
              LIMIT $limit",
            [':id' => $truckId]
        ) ?: [];
    }

    public function byId(int $id): array
    {
        $db = new DB();
        $rs = $db->mySelect(
            "SELECT a.*, d.full_name AS driver_name, d.employee_no, d.phone_1,
                    t.reg_no AS truck_reg, t.make, t.model
               FROM driver_truck_assignments a
          LEFT JOIN drivers d ON d.c0d = a.driver_id
          LEFT JOIN trucks  t ON t.c0d = a.truck_id
              WHERE a.c0d = :id AND a.deleted = 0
              LIMIT 1",
            [':id' => $id]
        );
        return $rs[0] ?? [];
    }

    /**
     * Create a new assignment.  Auto-closes any prior open assignment for
     * this driver — a driver can only be on one truck at a time.
     */
    public function create(array $d, int $uid): array
    {
        $driverId = (int)($d['driver_id'] ?? 0);
        $truckId  = (int)($d['truck_id']  ?? 0);
        $from     = $this->s($d['assigned_from'] ?? '');
        if (!$driverId || !$truckId) return ['ok' => false, 'msg' => 'Driver and truck are required.', 'id' => 0];
        if ($from === '') $from = date('Y-m-d');

        $db = new DB();

        // Auto-close any existing open assignment for this driver.
        $db->insertUpdate(
            "UPDATE driver_truck_assignments
                SET assigned_to = :end_date,
                    ended_by    = :uid,
                    end_reason  = COALESCE(NULLIF(end_reason,''), 'Reassignment'),
                    edited_by   = :uid,
                    edited_on   = NOW()
              WHERE driver_id = :did AND assigned_to IS NULL AND deleted = 0",
            [':end_date' => $from, ':uid' => $uid, ':did' => $driverId]
        );

        $r = $db->insertUpdate(
            "INSERT INTO driver_truck_assignments
                (tenant_id, driver_id, truck_id, assigned_from, role_type, reason, notes,
                 created_by, created_on)
             VALUES
                (:tenant, :did, :tid, :from, :role, :reason, :notes, :uid, NOW())",
            [
                ':tenant' => defined('DEFAULT_TENANT_ID') ? DEFAULT_TENANT_ID : 1,
                ':did'    => $driverId,
                ':tid'    => $truckId,
                ':from'   => $from,
                ':role'   => $this->s(($d['role_type'] ?? '') ?: 'primary'),
                ':reason' => $this->s($d['reason'] ?? ''),
                ':notes'  => $this->s($d['notes']  ?? ''),
                ':uid'    => $uid,
            ]
        );
        return ['ok' => $r['success'] > 0, 'msg' => $r['success'] > 0 ? 'Assignment created.' : 'Save failed.', 'id' => (int)$r['last_id']];
    }

    /** Explicitly end an assignment (driver leaves this truck). */
    public function endAssignment(int $id, string $endDate, string $endReason, int $uid): array
    {
        $endDate = $endDate ?: date('Y-m-d');
        $db = new DB();
        $db->insertUpdate(
            "UPDATE driver_truck_assignments
                SET assigned_to = :end_date,
                    ended_by    = :uid,
                    end_reason  = :reason,
                    edited_by   = :uid,
                    edited_on   = NOW()
              WHERE c0d = :id AND assigned_to IS NULL AND deleted = 0",
            [':end_date' => $endDate, ':uid' => $uid, ':reason' => $this->s($endReason), ':id' => $id]
        );
        return ['ok' => true];
    }

    public function softDelete(int $id, int $uid): array
    {
        $db = new DB();
        $db->insertUpdate(
            "UPDATE driver_truck_assignments SET deleted = 1, edited_by = :uid, edited_on = NOW() WHERE c0d = :id",
            [':uid' => $uid, ':id' => $id]
        );
        return ['ok' => true];
    }
}
