<?php

namespace App\Models;

use CodeIgniter\Model;

class AttendanceDayModel extends Model
{
    protected $table         = 'attendance_day';
    protected $primaryKey    = 'id';
    protected $returnType    = 'array';
    protected $useTimestamps = false;

    protected $allowedFields = [
        'class_section_id',
        'date',
        'status',            // 'draft','submitted','published'  (legacy: 'finalized')
        'submitted_by',
        'submitted_at',
        'published_by',
        'published_at',
        'auto_publish_at',
        'reopened_by',
        'reopened_at',
        'reopen_reason',
        'semester',
        'school_year',
        'created_at',
        'updated_at',
    ];

    /**
     * Legacy helper kept for compatibility.
     * True iff this (section, date, term) is hard-locked for everyone.
     * Treats 'published' (new) and 'finalized' (old) as finalized.
     */
    public function isFinalized(int $classSectionId, string $date, ?string $semester = null, ?string $schoolYear = null): bool
    {
        $builder = $this->builder()
            ->select('id')
            ->where('class_section_id', $classSectionId)
            ->where('date', $date)
            ->groupStart()
                ->where('status', 'published')
                ->orWhere('status', 'finalized') // tolerate legacy data
            ->groupEnd();

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

        return (bool) $builder->get()->getFirstRow();
    }

    /**
     * Find a day row by (section, date, term). Returns array|null.
     */
    public function findBySectionDate(int $classSectionId, string $date, ?string $semester, ?string $schoolYear): ?array
    {
        return $this->where([
                'class_section_id' => $classSectionId,
                'date'             => $date,
                'semester'         => $semester,
                'school_year'      => $schoolYear,
            ])->first() ?: null;
    }

    /**
     * Get the draft row for (section,date,term), creating it if missing.
     * Relies on the unique key (class_section_id, date, semester, school_year) to prevent duplicates.
     */
    public function getOrCreateDraft(
        int $classSectionId,
        string $date,
        ?string $semester,
        ?string $schoolYear,
        int $userId = 0
    ): array {
        // Try existing
        $row = $this->findBySectionDate($classSectionId, $date, $semester, $schoolYear);
        if ($row) return $row;

        $now = utc_now();
        $data = [
            'class_section_id' => $classSectionId,
            'date'             => $date,
            '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,
        ];

        try {
            $id = $this->insert($data, true);
            return $this->find($id);
        } catch (\Throwable $e) {
            // Race: someone else inserted the same unique key. Fetch it.
            $row = $this->findBySectionDate($classSectionId, $date, $semester, $schoolYear);
            if ($row) return $row;
            throw $e;
        }
    }

    /**
     * DEPRECATED: Prior code used "finalize" to lock immediately.
     * In the new workflow, "finalize" means "teacher submit"
     * (locks teachers, keeps admins editable). Use submit() or publish().
     */
    public function finalize(int $id, int $userId): bool
    {
        // Alias to submit() to avoid hard-locking admins by legacy calls.
        return $this->submit($id, $userId, null);
    }

    /**
     * Teacher submit: status => submitted (teacher locked, admin editable).
     * Optionally set auto_publish_at (controller can compute second-Sunday rule).
     */
    public function submit(int $id, int $userId, ?string $autoPublishAt = null): bool
    {
        $now = utc_now();
        return (bool) $this->update($id, [
            'status'          => 'submitted',
            'submitted_by'    => $userId,
            'submitted_at'    => $now,
            'auto_publish_at' => $autoPublishAt,
            'updated_at'      => $now,
        ]);
    }

    /**
     * Admin publish (hard lock): status => published.
     */
    public function publish(int $id, int $userId): bool
    {
        $now = utc_now();
        return (bool) $this->update($id, [
            'status'        => 'published',
            'published_by'  => $userId,
            'published_at'  => $now,
            'updated_at'    => $now,
        ]);
    }

    /**
     * Admin reopen a submitted/published day back to 'draft' (default) or 'submitted'.
     * Provide an optional reason for audit.
     */
    public function reopen(int $id, 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 = utc_now();
        return (bool) $this->update($id, [
            'status'        => $toStatus,
            'reopened_by'   => $userId,
            'reopened_at'   => $now,
            'reopen_reason' => $reason,
            'updated_at'    => $now,
        ]);
    }
}
