<?php

namespace App\Models;

use App\Models\BaseModel;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class BadgePrintLog extends BaseModel
{
    protected $table = 'badge_print_logs';

    // CI: useTimestamps = false
    public $timestamps = false;

    protected $fillable = [
        'user_id',
        'printed_by',
        'school_year',
        'printed_at',
        'role',
        'class_section_name',
        'copies',
    ];

    protected $casts = [
        'user_id'     => 'integer',
        'printed_by'  => 'integer',
        'printed_at'  => 'datetime',
        'copies'      => 'integer',
    ];

    /**
     * Insert a batch of print logs. Swallows errors if table is missing.
     *
     * @param int[]       $userIds
     * @param int|null    $printedBy
     * @param string|null $schoolYear
     * @param array       $roleMap        userId => role label
     * @param array       $classMap       userId => class name
     * @param int         $copies         copies per user (defaults to 1)
     * @return int rows inserted (best-effort)
     */
    public static function logPrints(
        array $userIds,
        ?int $printedBy,
        ?string $schoolYear,
        array $roleMap = [],
        array $classMap = [],
        int $copies = 1
    ): int {
        $now = now();
        $rows = [];

        foreach ($userIds as $uid) {
            $uid = (int) $uid;
            if ($uid <= 0) continue;

            $rows[] = [
                'user_id'            => $uid,
                'printed_by'         => $printedBy,
                'school_year'        => $schoolYear,
                'printed_at'         => $now,
                'role'               => (string)($roleMap[$uid] ?? ''),
                'class_section_name' => (string)($classMap[$uid] ?? ''),
                'copies'             => max(1, (int) $copies),
            ];
        }

        if (empty($rows)) return 0;

        try {
            // insert returns bool; we return count best-effort like CI
            DB::table((new static)->getTable())->insert($rows);
            return count($rows);
        } catch (QueryException $e) {
            // Avoid breaking badge/PDF generation if the table is missing or other DB error
            Log::error('BadgePrintLog::logPrints failed: ' . $e->getMessage());
            return 0;
        } catch (\Throwable $e) {
            Log::error('BadgePrintLog::logPrints failed: ' . $e->getMessage());
            return 0;
        }
    }

    /**
     * Return counts and last printed info for given user IDs.
     *
     * @param int[]       $userIds
     * @param string|null $schoolYear Optional filter by school year
     * @return array userId => [count, last_printed_at, last_printed_by]
     */
    public static function getStatus(array $userIds, ?string $schoolYear = null): array
    {
        $userIds = array_values(array_unique(array_map('intval', array_filter($userIds))));
        if (empty($userIds)) return [];

        try {
            $q = DB::table((new static)->getTable() . ' as l')
                ->selectRaw('l.user_id, COUNT(*) AS prints, MAX(l.printed_at) AS last_printed_at, MAX(l.printed_by) AS last_printed_by')
                ->whereIn('l.user_id', $userIds)
                ->groupBy('l.user_id');

            if (!empty($schoolYear)) {
                $q->where('l.school_year', $schoolYear);
            }

            $rows = $q->get();
        } catch (QueryException $e) {
            Log::error('BadgePrintLog::getStatus failed: ' . $e->getMessage());
            return [];
        } catch (\Throwable $e) {
            Log::error('BadgePrintLog::getStatus failed: ' . $e->getMessage());
            return [];
        }

        $out = [];
        foreach ($rows as $r) {
            $uid = (int) ($r->user_id ?? 0);
            $out[$uid] = [
                'count'           => (int) ($r->prints ?? 0),
                'last_printed_at' => (string) ($r->last_printed_at ?? ''),
                'last_printed_by' => isset($r->last_printed_by) ? (int) $r->last_printed_by : null,
            ];
        }

        return $out;
    }

    /* Optional relationships */
    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function printedByUser()
    {
        return $this->belongsTo(User::class, 'printed_by');
    }
}