<?php

namespace App\Models;

use App\Models\BaseModel;
use Illuminate\Support\Carbon;
use Illuminate\Database\QueryException;

class AttendanceDay extends BaseModel
{
    protected $table = 'attendance_day';

    // ✅ You are storing created_at / updated_at manually in CI (timestamps off there)
    // User didn't explicitly ask to auto-manage here, so we keep it OFF to match CI.
    // If you want auto-manage, tell me and I’ll flip it.
    public $timestamps = true;

    protected $fillable = [
        'class_section_id',
        'date',
        'status',
        'submitted_by',
        'submitted_at',
        'published_by',
        'published_at',
        'auto_publish_at',
        'reopened_by',
        'reopened_at',
        'reopen_reason',
        'semester',
        'school_year',
        'created_at',
        'updated_at',
    ];

    protected $casts = [
        'class_section_id' => 'integer',
        'submitted_by'     => 'integer',
        'published_by'     => 'integer',
        'reopened_by'      => 'integer',

        // If these are DATETIME columns:
        'submitted_at'     => 'datetime',
        'published_at'     => 'datetime',
        'auto_publish_at'  => 'datetime',
        'reopened_at'      => 'datetime',
        'created_at'       => 'datetime',
        'updated_at'       => 'datetime',

        // If date is stored as DATE string; if it's DATETIME, change to 'datetime'
        'date'             => 'date',
    ];

    /* =========================
     * CI method equivalents
     * ========================= */

    /**
     * Legacy helper: True iff (section, date, term) is hard-locked for everyone.
     * Treats 'published' and legacy 'finalized' as finalized.
     */
    public static function isFinalized(
        int $classSectionId,
        string $date,
        ?string $semester = null,
        ?string $schoolYear = null
    ): bool {
        $q = static::query()
            ->select('id')
            ->where('class_section_id', $classSectionId)
            ->whereDate('date', $date)
            ->where(function ($w) {
                $w->where('status', 'published')
                  ->orWhere('status', 'finalized'); // legacy
            });

        if ($semester !== null)   $q->where('semester', $semester);
        if ($schoolYear !== null) $q->where('school_year', $schoolYear);

        return $q->exists();
    }

    /**
     * Find day row by (section, date, term).
     */
    public static function findBySectionDate(
        int $classSectionId,
        string $date,
        ?string $semester,
        ?string $schoolYear
    ): ?self {
        return static::query()
            ->where('class_section_id', $classSectionId)
            ->whereDate('date', $date)
            ->where('semester', $semester)
            ->where('school_year', $schoolYear)
            ->first();
    }

    /**
     * Get draft row for (section,date,term), create it if missing.
     * Requires unique index: (class_section_id, date, semester, school_year)
     */
    public static function getOrCreateDraft(
        int $classSectionId,
        string $date,
        ?string $semester,
        ?string $schoolYear,
        int $userId = 0
    ): self {
        $row = static::findBySectionDate($classSectionId, $date, $semester, $schoolYear);
        if ($row) return $row;

        $now = now();
        $normalizedDate = Carbon::parse($date)->toDateString();

        try {
            return static::create([
                'class_section_id' => $classSectionId,
                'date'             => $normalizedDate,
                'status'           => 'draft',
                'submitted_by'     => null,
                'submitted_at'     => null,
                'published_by'     => null,
                'published_at'     => null,
                'auto_publish_at'  => null,
                'reopened_by'      => null,
                'reopened_at'      => null,
                'reopen_reason'    => null,
                'semester'         => $semester,
                'school_year'      => $schoolYear,
                'created_at'       => $now,
                'updated_at'       => $now,
            ]);
        } catch (QueryException $e) {
            // Race: someone inserted same unique key.
            $row = static::findBySectionDate($classSectionId, $date, $semester, $schoolYear);
            if ($row) return $row;
            throw $e;
        }
    }

    /**
     * DEPRECATED legacy finalize => submit (teacher submit).
     */
    public function finalize(int $userId): bool
    {
        return $this->submit($userId, null);
    }

    /**
     * Teacher submit: status => submitted (teacher locked, admin editable).
     */
    public function submit(int $userId, ?string $autoPublishAt = null): bool
    {
        $now = now();

        $payload = [
            'status'       => 'submitted',
            'submitted_by' => $userId,
            'submitted_at' => $now,
            'updated_at'   => $now,
        ];

        if ($autoPublishAt !== null) {
            $payload['auto_publish_at'] = $autoPublishAt;
        }

        return static::query()->whereKey($this->id)->update($payload) >= 0;
    }

    /**
     * Admin publish (hard lock): status => published.
     */
    public function publish(int $userId): bool
    {
        $now = now();

        return static::query()->whereKey($this->id)->update([
            'status'       => 'published',
            'published_by' => $userId,
            'published_at' => $now,
            'updated_at'   => $now,
        ]) >= 0;
    }

    /**
     * Admin reopen a day back to 'draft' (default) or 'submitted'.
     */
    public function reopen(int $userId, string $toStatus = 'draft', ?string $reason = null): bool
    {
        if (!in_array($toStatus, ['draft', 'submitted'], true)) {
            throw new \InvalidArgumentException('toStatus must be "draft" or "submitted".');
        }

        $now = now();

        return static::query()->whereKey($this->id)->update([
            'status'        => $toStatus,
            'reopened_by'   => $userId,
            'reopened_at'   => $now,
            'reopen_reason' => $reason,
            'updated_at'    => $now,
        ]) >= 0;
    }
}
