<?php
declare(strict_types=1);

namespace App\Controller;

use Cake\Http\Exception\ForbiddenException;
use Cake\Log\Log;

class AdminController extends AppController
{
    public function initialize(): void
    {
        parent::initialize();

        $this->loadComponent('Authentication.Authentication');
    }

    // Require admin role
    private function checkAdmin()
    {
        $user = $this->request->getAttribute('identity');

        if (!$user || $user->role !== 'admin') {
            Log::error('Unauthorized access to admin');
            throw new ForbiddenException('Admin only');
        }
    }

    // ================= DASHBOARD =================
    public function index()
    {
        $this->checkAdmin();

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('index');

        $usersTable     = $this->fetchTable('Users');
        $enquiriesTable = $this->fetchTable('Enquiries');
        $teachersTable  = $this->fetchTable('Teachers');
        $lessonsTable   = $this->fetchTable('Lessons');
        $bookingsTable  = $this->fetchTable('Bookings');

        $company = $this->fetchTable('CompanyInfos')->find()->first() ?? $this->fetchTable('CompanyInfos')->newEmptyEntity();

        $this->set([
            'totalUsers'       => $usersTable->find()->count(),
            'totalEnquiries'   => $enquiriesTable->find()->count(),
            'pending'          => $enquiriesTable->find()->where(['status' => 'pending'])->count(),
            'totalTeachers'    => $teachersTable->find()->count(),
            'totalLessons'     => $lessonsTable->find()->count(),
            'pendingBookings'  => $bookingsTable->find()->where(['status' => 'pending'])->count(),
            'pendingEnquiries' => $enquiriesTable->find()->where(['status' => 'pending'])->count(),
            'company'          => $company,
        ]);
    }

    // ================= ENQUIRIES =================
    public function enquiries()
    {
        $this->checkAdmin();

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('enquiries');

        $enquiriesTable = $this->fetchTable('Enquiries');

        $enquiries = $enquiriesTable->find()
            ->order(['created' => 'DESC'])
            ->all();

        $this->set(compact('enquiries'));
    }

    public function deleteEnquiry($id)
    {
        $this->checkAdmin();

        $enquiries = $this->fetchTable('Enquiries');
        $e = $enquiries->get($id);

        if ($enquiries->delete($e)) {
            $this->Flash->success('Enquiry deleted successfully');
            Log::debug("Deleted enquiry ID: $id");
        } else {
            $this->Flash->error('Delete failed');
            Log::error("Delete enquiry failed: $id");
        }

        return $this->redirect('/admin/enquiries');
    }

    // ================= USERS =================
    public function users()
    {
        $this->checkAdmin();

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('users');

        $usersTable = $this->fetchTable('Users');

        $users = $usersTable->find()
            ->contain(['Customers'])
            ->orderBy(['Users.id' => 'DESC'])
            ->all();

        $this->set(compact('users'));
    }

    public function addUser()
    {
        $this->checkAdmin();

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('user_form');

        $usersTable = $this->fetchTable('Users');
        $customersTable = $this->fetchTable('Customers');
        $user = $usersTable->newEmptyEntity();
        $user->role = 'customer';
        $customer = $customersTable->newEmptyEntity();

        if ($this->request->is('post')) {
            $data = $this->request->getData();
            $role = (($data['role'] ?? '') === 'admin') ? 'admin' : 'customer';

            if (($data['password'] ?? '') !== ($data['confirm_password'] ?? '')) {
                $this->Flash->error('Passwords do not match.');
                $user = $usersTable->patchEntity($user, $data, [
                    'fields' => ['email', 'password'],
                    'validate' => false,
                ]);
                $user->role = $role;
                $fullName = trim((string) ($data['full_name'] ?? ''));
                $phone = trim((string) ($data['phone'] ?? ''));
                $address = trim((string) ($data['address'] ?? ''));
                $customer = $customersTable->patchEntity($customer, [
                    'name' => $fullName,
                    'phone' => $phone,
                    'address' => $address !== '' ? $address : null,
                ], ['validate' => false]);
                $this->set(compact('user', 'customer'));

                return;
            }

            $user = $usersTable->patchEntity($user, $data, [
                'fields' => ['email', 'password'],
                'validate' => 'register',
            ]);
            $user->role = $role;

            if ($user->hasErrors()) {
                $this->Flash->error('Please fix the errors below and try again.');
                $fullName = trim((string) ($data['full_name'] ?? ''));
                $phone = trim((string) ($data['phone'] ?? ''));
                $address = trim((string) ($data['address'] ?? ''));
                $customer = $customersTable->patchEntity($customersTable->newEmptyEntity(), [
                    'name' => $fullName,
                    'phone' => $phone,
                    'address' => $address !== '' ? $address : null,
                ], ['validate' => false]);
                $this->set(compact('user', 'customer'));

                return;
            }

            if ($role === 'customer') {
                $fullName = trim((string) ($data['full_name'] ?? ''));
                $phone = trim((string) ($data['phone'] ?? ''));
                $address = trim((string) ($data['address'] ?? ''));

                $customer = $customersTable->patchEntity($customersTable->newEmptyEntity(), [
                    'name' => $fullName,
                    'phone' => $phone,
                    'address' => $address !== '' ? $address : null,
                ], [
                    'validate' => 'register',
                ]);

                if ($customer->hasErrors()) {
                    $this->Flash->error('Please check contact details for the customer account.');
                    $this->set(compact('user', 'customer'));

                    return;
                }

                $connection = $usersTable->getConnection();
                $saved = $connection->transactional(function () use ($usersTable, $customersTable, $user, $customer) {
                    if (!$usersTable->save($user)) {
                        return false;
                    }
                    $customer->user_id = $user->id;

                    return (bool) $customersTable->save($customer);
                });

                if ($saved) {
                    $this->Flash->success('User created successfully.');
                    Log::debug('Admin created user ID: ' . $user->id);

                    return $this->redirect(['action' => 'users']);
                }

                $this->Flash->error('Could not create user. Please try again.');
                Log::error('Admin addUser save failed: ' . json_encode($user->getErrors()) . json_encode($customer->getErrors()));
            } else {
                if ($usersTable->save($user)) {
                    $this->Flash->success('User created successfully.');
                    Log::debug('Admin created admin user ID: ' . $user->id);

                    return $this->redirect(['action' => 'users']);
                }

                $this->Flash->error('Could not create user. Please try again.');
                Log::error('Admin addUser admin save failed: ' . json_encode($user->getErrors()));
            }
        }

        $this->set(compact('user', 'customer'));
    }

    public function deleteUser($id)
    {
        $this->checkAdmin();

        $id = (int) $id;
        $users = $this->fetchTable('Users');
        $customersTable = $this->fetchTable('Customers');
        $connection = $users->getConnection();

        $deleted = $connection->transactional(function () use ($users, $customersTable, $id) {
            $customersTable->deleteAll(['user_id' => $id]);
            $user = $users->get($id);

            return $users->delete($user);
        });

        if ($deleted) {
            $this->Flash->success('User deleted');
            Log::debug("Deleted user ID: $id");
        } else {
            $this->Flash->error('Delete failed');
            Log::error("Delete user failed: $id");
        }

        return $this->redirect('/admin/users');
    }
    public function unlockUser($id)
    {
        $this->checkAdmin();

        $usersTable = $this->fetchTable('Users');
        $user = $usersTable->get($id);

        $user->failed_login_attempts = 0;
        $user->last_failed_login = null;

        if ($usersTable->save($user)) {
            $this->Flash->success('User account has been unlocked successfully.');
            Log::info("Unlocked user ID: {$id}");
        } else {
            $this->Flash->error('Failed to unlock user account.');
            Log::error("Unlock user failed: ID {$id}");
        }

        return $this->redirect('/admin/users');
    }

    public function markReplied($id)
    {
        $this->request->allowMethod(['post']);

        $enquiriesTable = $this->fetchTable('Enquiries');

        $enquiry = $enquiriesTable->get($id);
        $enquiry->status = 'replied';

        if ($enquiriesTable->save($enquiry)) {
            $this->Flash->success('Marked as replied');
        } else {
            $this->Flash->error('Failed');
        }

        return $this->redirect(['action' => 'enquiries']);
    }
    // ================= TEACHERS =================

// ================= TEACHERS LIST =================
    public function teachers()
    {
        $this->checkAdmin();

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('teachers');

        $teachersTable = $this->fetchTable('Teachers');

        $teachers = $this->paginate($teachersTable);

        $this->set(compact('teachers'));
    }

    // ================= ADD =================
    public function addTeacher()
    {
        $this->checkAdmin();

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('teacher_form');

        $teachersTable = $this->fetchTable('Teachers');
        $teacher = $teachersTable->newEmptyEntity();

        if ($this->request->is('post')) {
            $teacher = $teachersTable->patchEntity($teacher, $this->request->getData());

            if ($teachersTable->save($teacher)) {
                $this->Flash->success('Teacher created successfully');
                return $this->redirect(['action' => 'teachers']);
            }

            $this->Flash->error('Failed to create teacher');
        }

        $this->set(compact('teacher'));
    }

    // ================= EDIT =================
    public function editTeacher($id = null)
    {
        $this->checkAdmin();

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('teacher_form');

        $teachersTable = $this->fetchTable('Teachers');
        $teacher = $teachersTable->get($id);

        if ($this->request->is(['patch', 'post', 'put'])) {
            $teacher = $teachersTable->patchEntity($teacher, $this->request->getData());

            if ($teachersTable->save($teacher)) {
                $this->Flash->success('Teacher updated');
                return $this->redirect(['action' => 'teachers']);
            }

            $this->Flash->error('Update failed');
        }

        $this->set(compact('teacher'));
    }

    // ================= DELETE =================
    public function deleteTeacher($id = null)
    {
        $this->checkAdmin();

        $this->request->allowMethod(['post', 'delete']);

        $teachersTable = $this->fetchTable('Teachers');
        $teacher = $teachersTable->get($id);

        if ($teachersTable->delete($teacher)) {
            $this->Flash->success('Teacher deleted');
        } else {
            $this->Flash->error('Delete failed');
        }

        return $this->redirect(['action' => 'teachers']);
    }
    // ================= LESSONS =================

    public function lessons()
    {
        $this->checkAdmin();

        $lessonsTable = $this->fetchTable('Lessons');

        $lessons = $this->paginate(
            $lessonsTable->find()->contain(['Teachers'])
        );

        
        $teachers = $this->fetchTable('Teachers')
            ->find('list', [
                'keyField' => 'id',
                'valueField' => 'name'
            ])
            ->toArray();

        $this->set(compact('lessons','teachers'));

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('lessons');
    }
    public function addLesson()
    {
        $this->checkAdmin();

        $lessonsTable = $this->fetchTable('Lessons');
        $lesson = $lessonsTable->newEmptyEntity();

        if ($this->request->is('post')) {
            $lesson = $lessonsTable->patchEntity($lesson, $this->request->getData());

            if ($lessonsTable->save($lesson)) {
                $this->Flash->success('Lesson created');
                return $this->redirect(['action'=>'lessons']);
            }

            $this->Flash->error('Failed');
        }
    }
    public function editLesson($id)
    {
        $this->checkAdmin();

        $lessonsTable = $this->fetchTable('Lessons');
        $lesson = $lessonsTable->get($id);

        if ($this->request->is(['post','put','patch'])) {
            $lesson = $lessonsTable->patchEntity($lesson, $this->request->getData());

            if ($lessonsTable->save($lesson)) {
                $this->Flash->success('Updated');
                return $this->redirect(['action'=>'lessons']);
            }

            $this->Flash->error('Failed');
        }
    }
    public function deleteLesson($id)
    {
        $this->checkAdmin();

        $this->request->allowMethod(['post','delete']);

        $lessonsTable = $this->fetchTable('Lessons');
        $lesson = $lessonsTable->get($id);

        if ($lessonsTable->delete($lesson)) {
            $this->Flash->success('Deleted');
        } else {
            $this->Flash->error('Failed');
        }

        return $this->redirect(['action'=>'lessons']);
    }

 // ================= MATERIAL =================
    public function materials()
    {
        $this->checkAdmin();

        $materialsTable = $this->fetchTable('Materials');

        $materials = $this->paginate(
            $materialsTable->find()->contain(['Lessons'])
        );

        $lessons = $this->fetchTable('Lessons')
            ->find('list', [
                'keyField' => 'id',
                'valueField' => 'lesson_name'
            ])
            ->toArray();

        $this->set(compact('materials','lessons'));

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('materials');
    }

    public function addMaterial()
    {
        $this->checkAdmin();

        $table = $this->fetchTable('Materials');
        $entity = $table->newEmptyEntity();

        if ($this->request->is('post')) {
            $entity = $table->patchEntity($entity, $this->request->getData());

            if ($table->save($entity)) {
                $this->Flash->success('Material created');
            } else {
                $this->Flash->error('Create failed');
            }
        }

        return $this->redirect(['action'=>'materials']);
    }

    public function editMaterial($id)
    {
        $this->checkAdmin();

        $table = $this->fetchTable('Materials');
        $entity = $table->get($id);

        if ($this->request->is(['post','put','patch'])) {
            $entity = $table->patchEntity($entity, $this->request->getData());

            if ($table->save($entity)) {
                $this->Flash->success('Updated');
            } else {
                $this->Flash->error('Update failed');
            }
        }

        return $this->redirect(['action'=>'materials']);
    }

    public function deleteMaterial($id)
    {
        $this->checkAdmin();

        $this->request->allowMethod(['post','delete']);

        $table = $this->fetchTable('Materials');
        $entity = $table->get($id);

        if ($table->delete($entity)) {
            $this->Flash->success('Deleted');
        } else {
            $this->Flash->error('Delete failed');
        }

        return $this->redirect(['action'=>'materials']);
    }
    public function company()
    {
        $this->checkAdmin();

        $table = $this->fetchTable('CompanyInfos');

        
        $company = $table->find()->first();

        if (!$company) {
            $company = $table->newEmptyEntity();
        }

        if ($this->request->is(['post','put'])) {
            $company = $table->patchEntity($company, $this->request->getData());

            if ($table->save($company)) {
                $this->Flash->success('Company info saved successfully');
            } else {
                $this->Flash->error('Failed to save');
            }
        }

        $this->set(compact('company'));

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('company');
    }
    public function faqs()
    {
        $this->checkAdmin();

        $table = $this->fetchTable('Faqs');

        $faqs = $this->paginate(
            $table->find()->order(['display_order'=>'ASC'])
        );

        $this->set(compact('faqs'));

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('faqs');
    }

    public function addFaq()
    {
        $table = $this->fetchTable('Faqs');
        $entity = $table->newEmptyEntity();

        if ($this->request->is('post')) {
            $entity = $table->patchEntity($entity, $this->request->getData());

            if ($table->save($entity)) {
                $this->Flash->success('FAQ added');
            } else {
                $this->Flash->error('Add failed');
            }
        }

        return $this->redirect(['action'=>'faqs']);
    }

    public function editFaq($id)
    {
        $table = $this->fetchTable('Faqs');
        $entity = $table->get($id);

        if ($this->request->is(['post','put','patch'])) {
            $entity = $table->patchEntity($entity, $this->request->getData());

            if ($table->save($entity)) {
                $this->Flash->success('Updated');
            } else {
                $this->Flash->error('Update failed');
            }
        }

        return $this->redirect(['action'=>'faqs']);
    }

    public function deleteFaq($id)
    {
        $this->request->allowMethod(['post','delete']);

        $table = $this->fetchTable('Faqs');
        $entity = $table->get($id);

        if ($table->delete($entity)) {
            $this->Flash->success('Deleted');
        } else {
            $this->Flash->error('Delete failed');
        }

        return $this->redirect(['action'=>'faqs']);
    }
    public function bookings()
    {
        $this->checkAdmin();

        $bookings = $this->paginate(
            $this->fetchTable('Bookings')
                ->find()
                ->contain(['Users','Lessons','Payments'])
        );

        $this->set(compact('bookings'));

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('bookings');
    }

    public function updateBooking($id, $status)
    {
        $table = $this->fetchTable('Bookings');

        $booking = $table->get($id);

        $booking->status = $status;

        $table->save($booking);

        return $this->redirect(['action'=>'bookings']);
    }

    public function teacherAvailabilitySlots()
    {
        $this->checkAdmin();

        $this->viewBuilder()->setTemplatePath('Pages/Admin');
        $this->viewBuilder()->setTemplate('teacher_availability_slots');

        $slotsTable = $this->fetchTable('TeacherAvailabilitySlots');
        $slots = $slotsTable->find()
            ->contain(['Teachers', 'Lessons'])
            ->orderBy(['TeacherAvailabilitySlots.session_date' => 'ASC', 'TeacherAvailabilitySlots.id' => 'ASC'])
            ->all();

        $teachers = $this->fetchTable('Teachers')->find()->orderBy(['name' => 'ASC'])->all();
        $lessons = $this->fetchTable('Lessons')->find()->orderBy(['lesson_name' => 'ASC'])->all();

        $slot = $slotsTable->newEmptyEntity();
        if ($this->request->is('post')) {
            $data = $this->request->getData();
            if (($data['lesson_id'] ?? '') === '') {
                $data['lesson_id'] = null;
            }
            $slot = $slotsTable->patchEntity($slot, $data);
            if ($slotsTable->save($slot)) {
                $this->Flash->success('Published session added');

                return $this->redirect(['action' => 'teacherAvailabilitySlots']);
            }
            $this->Flash->error('Could not save. Check the form and try again.');
        }

        $this->set(compact('slots', 'teachers', 'lessons', 'slot'));
    }

    public function deleteTeacherAvailabilitySlot(?string $id = null)
    {
        $this->checkAdmin();
        $this->request->allowMethod(['post', 'delete']);

        $slotsTable = $this->fetchTable('TeacherAvailabilitySlots');
        $slot = $slotsTable->get((int)$id);

        if ($slotsTable->delete($slot)) {
            $this->Flash->success('Session removed');
        } else {
            $this->Flash->error('Delete failed');
        }

        return $this->redirect(['action' => 'teacherAvailabilitySlots']);
    }
}