<?php
/**
 * Branch Batch Controller — Updated with Edit + Modern Responsive UI
 *
 * Features:
 *   - List batches (with student count, course name)
 *   - Create batch (with course dropdown, time picker, status, max students)
 *   - Edit batch (full update)
 *   - Delete batch (with student count check)
 *
 * URL prefix: /branch/batches/*
 */

namespace BranchAdmin\Controllers;

use BranchAdmin\Controllers\BranchBaseController;

class BranchBatchController extends BranchBaseController
{
    /**
     * List all batches for this branch.
     */
    public function index(): void
    {
        requireBranchAdmin();
        $branchId = $this->getBranchId();

        $stmt = $this->db->prepare(
            "SELECT b.*, c.name AS course_name, c.duration AS course_duration,
                    (SELECT COUNT(*) FROM students s WHERE s.batch_id = b.id) AS student_count
             FROM batches b
             LEFT JOIN courses c ON b.course_id = c.id
             WHERE b.branch_id = :bid
             ORDER BY b.start_date DESC, b.id DESC"
        );
        $stmt->execute([':bid' => $branchId]);
        $batches = $stmt->fetchAll(\PDO::FETCH_ASSOC) ?: [];

        $stats = [
            'total'     => count($batches),
            'upcoming'  => 0,
            'running'   => 0,
            'completed' => 0,
        ];
        foreach ($batches as $b) {
            $st = $b['status'] ?? '';
            if ($st === 'upcoming')      $stats['upcoming']++;
            elseif ($st === 'running')   $stats['running']++;
            elseif ($st === 'completed') $stats['completed']++;
        }

        $this->branchAdminView('batches/index', [
            'title'       => 'Batches',
            'currentPage' => 'batches',
            'batches'     => $batches,
            'stats'       => $stats,
            'csrfToken'   => $this->csrfToken ?? '',
        ]);
    }

    /**
     * Show create batch form.
     */
    public function create(): void
    {
        requireBranchAdmin();
        $branchId = $this->getBranchId();

        $courses = [];
        try {
            $courses = $this->db->query("SELECT id, name, duration FROM courses WHERE active=1 ORDER BY name")
                                ->fetchAll(\PDO::FETCH_ASSOC) ?: [];
        } catch (\Throwable $e) {}

        $this->branchAdminView('batches/create', [
            'title'       => 'Create Batch',
            'currentPage' => 'batches',
            'courses'     => $courses,
            'csrfToken'   => $this->csrfToken ?? '',
        ]);
    }

    /**
     * Store new batch.
     */
    public function store(): void
    {
        requireBranchAdmin();
        $this->validateCsrf();
        $branchId = $this->getBranchId();

        $batchName   = trim($_POST['batch_name'] ?? '');
        $courseId    = (int)($_POST['course_id'] ?? 0);
        $startDate   = trim($_POST['start_date'] ?? date('Y-m-d'));
        $endDate     = trim($_POST['end_date'] ?? '');
        $startTime   = trim($_POST['start_time'] ?? '09:00');
        $endTime     = trim($_POST['end_time'] ?? '11:00');
        $status      = trim($_POST['status'] ?? 'upcoming');
        $maxStudents = (int)($_POST['max_students'] ?? 30);
        $description = trim($_POST['description'] ?? '');

        if (empty($batchName)) {
            flash('error', 'Batch name is required.');
            redirect(BASE_PATH . '/branch/batches/create');
        }

        $this->ensureBatchColumns();

        $cols = $this->getTableColumns('batches');
        $data = [
            'batch_name'   => $batchName,
            'course_id'    => $courseId > 0 ? $courseId : null,
            'branch_id'    => $branchId,
            'start_date'   => $startDate ?: date('Y-m-d'),
            'end_date'     => $endDate ?: null,
            'start_time'   => $startTime,
            'end_time'     => $endTime,
            'status'       => $status,
            'max_students' => $maxStudents,
            'description'  => $description,
            'created_at'   => date('Y-m-d H:i:s'),
        ];

        $insertData = [];
        foreach ($data as $k => $v) {
            if (in_array($k, $cols, true)) $insertData[$k] = $v;
        }

        $keys    = array_keys($insertData);
        $colList = implode(', ', array_map(fn($c) => "`{$c}`", $keys));
        $phList  = implode(', ', array_map(fn($c) => ":{$c}", $keys));
        $sql     = "INSERT INTO batches ({$colList}) VALUES ({$phList})";
        $params  = [];
        foreach ($insertData as $k => $v) $params[":{$k}"] = $v;

        try {
            $this->db->prepare($sql)->execute($params);
            $batchId = (int)$this->db->lastInsertId();
            $this->auditLog('batch_created', 'batches', $batchId, "Created batch '{$batchName}'");
            flash('success', "✅ Batch '{$batchName}' created successfully!");
            redirect(BASE_PATH . '/branch/batches');
        } catch (\Throwable $e) {
            flash('error', 'Failed to create batch: ' . $e->getMessage());
            redirect(BASE_PATH . '/branch/batches/create');
        }
    }

    /**
     * Show edit batch form.
     */
    public function edit(?int $id = null): void
    {
        requireBranchAdmin();
        $branchId = $this->getBranchId();

        if (!$id || $id <= 0) {
            flash('error', 'Invalid batch ID.');
            redirect(BASE_PATH . '/branch/batches');
        }

        $stmt = $this->db->prepare(
            "SELECT b.*, c.name AS course_name
             FROM batches b
             LEFT JOIN courses c ON b.course_id = c.id
             WHERE b.id = :id AND b.branch_id = :bid LIMIT 1"
        );
        $stmt->execute([':id' => $id, ':bid' => $branchId]);
        $batch = $stmt->fetch(\PDO::FETCH_ASSOC) ?: null;

        if (!$batch) {
            flash('error', 'Batch not found.');
            redirect(BASE_PATH . '/branch/batches');
        }

        $courses = [];
        try {
            $courses = $this->db->query("SELECT id, name, duration FROM courses WHERE active=1 ORDER BY name")
                                ->fetchAll(\PDO::FETCH_ASSOC) ?: [];
        } catch (\Throwable $e) {}

        // Student count in this batch
        $studentCount = 0;
        try {
            $stmt = $this->db->prepare("SELECT COUNT(*) FROM students WHERE batch_id = :bid");
            $stmt->execute([':bid' => $id]);
            $studentCount = (int)$stmt->fetchColumn();
        } catch (\Throwable $e) {}

        $this->branchAdminView('batches/edit', [
            'title'        => 'Edit Batch',
            'currentPage'  => 'batches',
            'batch'        => $batch,
            'courses'      => $courses,
            'studentCount' => $studentCount,
            'csrfToken'    => $this->csrfToken ?? '',
        ]);
    }

    /**
     * Update existing batch.
     *
     * Route: POST /branch/batches/{id}/update
     * (Uses /update suffix to avoid conflict with POST /branch/batches store route)
     */
    public function update(?int $id = null): void
    {
        requireBranchAdmin();
        $this->validateCsrf();
        $branchId = $this->getBranchId();

        if (!$id || $id <= 0) {
            flash('error', 'Invalid batch ID.');
            redirect(BASE_PATH . '/branch/batches');
        }

        // Verify ownership
        $stmt = $this->db->prepare("SELECT id, batch_name FROM batches WHERE id = :id AND branch_id = :bid LIMIT 1");
        $stmt->execute([':id' => $id, ':bid' => $branchId]);
        $existing = $stmt->fetch(\PDO::FETCH_ASSOC) ?: null;
        if (!$existing) {
            flash('error', 'Batch not found or you do not have permission to edit it.');
            redirect(BASE_PATH . '/branch/batches');
        }

        $batchName   = trim($_POST['batch_name'] ?? '');
        $courseId    = (int)($_POST['course_id'] ?? 0);
        $startDate   = trim($_POST['start_date'] ?? date('Y-m-d'));
        $endDate     = trim($_POST['end_date'] ?? '');
        $startTime   = trim($_POST['start_time'] ?? '09:00');
        $endTime     = trim($_POST['end_time'] ?? '11:00');
        $status      = trim($_POST['status'] ?? 'upcoming');
        $maxStudents = (int)($_POST['max_students'] ?? 30);
        $description = trim($_POST['description'] ?? '');

        if (empty($batchName)) {
            flash('error', 'Batch name is required.');
            redirect(BASE_PATH . "/branch/batches/{$id}/edit");
        }

        $this->ensureBatchColumns();

        $cols = $this->getTableColumns('batches');
        $data = [
            'batch_name'   => $batchName,
            'course_id'    => $courseId > 0 ? $courseId : null,
            'start_date'   => $startDate ?: date('Y-m-d'),
            'end_date'     => $endDate ?: null,
            'start_time'   => $startTime,
            'end_time'     => $endTime,
            'status'       => $status,
            'max_students' => $maxStudents,
            'description'  => $description,
            'updated_at'   => date('Y-m-d H:i:s'),
        ];

        // Filter to only existing columns
        $updateData = [];
        foreach ($data as $k => $v) {
            if (in_array($k, $cols, true)) $updateData[$k] = $v;
        }

        if (empty($updateData)) {
            flash('error', 'No valid columns to update.');
            redirect(BASE_PATH . '/branch/batches');
        }

        $setParts = [];
        $params   = [];
        foreach ($updateData as $k => $v) {
            $setParts[] = "`{$k}` = :set_{$k}";
            $params[":set_{$k}"] = $v;
        }
        $sql = "UPDATE batches SET " . implode(', ', $setParts) . " WHERE id = :id AND branch_id = :bid";
        $params[':id']  = $id;
        $params[':bid'] = $branchId;

        try {
            $stmt = $this->db->prepare($sql);
            $stmt->execute($params);
            $affectedRows = $stmt->rowCount();

            $this->auditLog('batch_updated', 'batches', $id, "Updated batch '{$batchName}' (rows: {$affectedRows})");
            flash('success', "✅ Batch '{$batchName}' updated successfully!");
        } catch (\Throwable $e) {
            error_log('BranchBatch update failed: ' . $e->getMessage() . ' | SQL: ' . $sql);
            flash('error', '❌ Failed to update batch: ' . $e->getMessage());
        }
        redirect(BASE_PATH . '/branch/batches');
    }

    /**
     * Delete a batch (only if no students are assigned).
     */
    public function delete(?int $id = null): void
    {
        requireBranchAdmin();
        $this->validateCsrf();
        $branchId = $this->getBranchId();

        if (!$id || $id <= 0) {
            flash('error', 'Invalid batch ID.');
            redirect(BASE_PATH . '/branch/batches');
        }

        // Check if any students are in this batch
        $stmt = $this->db->prepare("SELECT COUNT(*) FROM students WHERE batch_id = :bid");
        $stmt->execute([':bid' => $id]);
        $count = (int)$stmt->fetchColumn();

        if ($count > 0) {
            flash('error', "❌ Cannot delete: {$count} student(s) are in this batch. Move them to another batch first.");
            redirect(BASE_PATH . '/branch/batches');
        }

        try {
            $stmt = $this->db->prepare("SELECT batch_name FROM batches WHERE id = :id AND branch_id = :bid LIMIT 1");
            $stmt->execute([':id' => $id, ':bid' => $branchId]);
            $batchName = $stmt->fetchColumn() ?: 'Unknown';

            $this->db->prepare("DELETE FROM batches WHERE id = :id AND branch_id = :bid")
                ->execute([':id' => $id, ':bid' => $branchId]);

            $this->auditLog('batch_deleted', 'batches', $id, "Deleted batch '{$batchName}'");
            flash('success', "✅ Batch '{$batchName}' deleted.");
        } catch (\Throwable $e) {
            flash('error', 'Error: ' . $e->getMessage());
        }
        redirect(BASE_PATH . '/branch/batches');
    }

    // ════════════════════════════════════════════════════════════════════════
    // PRIVATE HELPERS
    // ════════════════════════════════════════════════════════════════════════

    private function getTableColumns(string $table): array
    {
        try {
            $stmt = $this->db->prepare("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :table");
            $stmt->execute([':table' => $table]);
            return array_map('strtolower', $stmt->fetchAll(\PDO::FETCH_COLUMN) ?: []);
        } catch (\Throwable $e) { return []; }
    }

    /**
     * Ensure batches table has all required columns.
     */
    private function ensureBatchColumns(): void
    {
        $existing = $this->getTableColumns('batches');
        $needed = [
            'course_id'    => "ADD COLUMN `course_id` INT UNSIGNED NULL DEFAULT NULL",
            'start_date'   => "ADD COLUMN `start_date` DATE NULL DEFAULT NULL",
            'end_date'     => "ADD COLUMN `end_date` DATE NULL DEFAULT NULL",
            'start_time'   => "ADD COLUMN `start_time` VARCHAR(10) NULL DEFAULT NULL",
            'end_time'     => "ADD COLUMN `end_time` VARCHAR(10) NULL DEFAULT NULL",
            'max_students' => "ADD COLUMN `max_students` INT UNSIGNED NOT NULL DEFAULT 30",
            'description'  => "ADD COLUMN `description` TEXT NULL DEFAULT NULL",
            'updated_at'   => "ADD COLUMN `updated_at` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP",
        ];
        foreach ($needed as $col => $ddl) {
            if (!in_array($col, $existing, true)) {
                try { $this->db->exec("ALTER TABLE `batches` {$ddl}"); } catch (\Throwable $e) {}
            }
        }

        // Ensure status enum supports all three values
        try {
            $this->db->exec("ALTER TABLE `batches` MODIFY COLUMN `status` ENUM('upcoming','running','completed') NOT NULL DEFAULT 'upcoming'");
        } catch (\Throwable $e) {}
    }
}
