<?php
declare(strict_types=1);

namespace App\Controller;

use App\Controller\AppController;
use Cake\Event\EventInterface;
use Cake\Http\Exception\UnauthorizedException;

class UsersController extends AppController
{
    public function initialize(): void
    {
        parent::initialize();
    
        // If using CakePHP Authentication plugin:
        // allow guests to reach login/register/password reset
        if ($this->components()->has('Authentication')) {
            $this->Authentication->allowUnauthenticated(['login', 'register', 'forgotPassword', 'resetPassword']);
        }
        $this->viewBuilder()->setHelpers(['Form', 'Html']);
    }
    private function isAdmin(): bool
    {
        $id = $this->request->getAttribute('identity');
        return (bool)($id && $id->get('role') === 'admin');
    }

    public function beforeFilter(EventInterface $event)
    {
        parent::beforeFilter($event);
    }

    /* =========================
     *  Auth: Login / Logout
     * ========================= */

    public function login()
    {
        $this->request->allowMethod(['get', 'post']);

        // If already logged in, go to profile
        $identity = $this->request->getAttribute('identity');
        if ($identity) {
            return $this->redirect(['action' => 'profile']);
        }

        if ($this->request->is('post')) {
            $result = $this->Authentication->getResult();
            if ($result && $result->isValid()) {
                $redirect = $this->Authentication->getLoginRedirect() ?? ['action' => 'profile'];
                return $this->redirect($redirect);
            }
            $this->Flash->error('Invalid email or password.');
        }
    }
    public function editProfile()
    {
        $identity = $this->request->getAttribute('identity');
        if (!$identity) {
            throw new UnauthorizedException('Please log in to edit your profile.');
        }
    
        $userId = (int)$identity->get('id');
        $user = $this->Users->get($userId);
    
        if ($this->request->is(['patch', 'post', 'put'])) {
            $data = $this->request->getData();
    
            if (empty($data['password'])) {
                unset($data['password'], $data['password_confirm']);
            }
    
            $user = $this->Users->patchEntity($user, $data, [
                'fields' => [
                    'email', 'first_name', 'last_name', 'avatar',
                    'phone', 'date_of_birth',
                    'password', 'password_confirm',
                ],
            ]);
    
            if (!$user->getErrors() && $this->Users->save($user)) {
                $this->Flash->success('Profile updated.');
                return $this->redirect(['action' => 'profile']);
            }
    
            $this->Flash->error('Could not save your changes. Please fix the errors and try again.');
        }
    
        $this->set(compact('user'));
    }

    public function logout()
    {
        if ($this->components()->has('Authentication')) {
            $this->Authentication->logout();
        }
        return $this->redirect(['action' => 'login']);
    }

    /* =========================
     *  Registration
     * ========================= */

    public function register()
    {
        $user = $this->Users->newEmptyEntity();

        if ($this->request->is('post')) {
            $data = $this->request->getData();

            // Optional: default role for customer signups
            if (empty($data['role'])) {
                $data['role'] = 'customer';
            }

            $user = $this->Users->patchEntity($user, $data, [
                'fields' => [
                    'email', 'password', 'password_confirm',
                    'first_name', 'last_name', 'avatar',
                    'phone', 'date_of_birth', 'role'
                ],
            ]);

            if (!$user->getErrors() && $this->Users->save($user)) {
                $this->Flash->success('Account created successfully. Please log in.');
                return $this->redirect(['action' => 'login']);
            }

            $this->Flash->error('Could not create account. Please check the form for errors.');
        }

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

    /* =========================
     *  Profile (with Past Orders)
     * ========================= */

    public function profile()
    {
        $identity = $this->request->getAttribute('identity');
        if (!$identity) {
            throw new UnauthorizedException('Please log in to view your profile.');
        }

        $userId = (int)$identity->get('id');

        $user = $this->Users->find()
            ->select(['id', 'email', 'first_name', 'last_name', 'phone', 'avatar', 'date_of_birth', 'created', 'modified'])
            ->where(['Users.id' => $userId])
            ->contain([
                'UserPreferences',
                'Orders' => function ($q) {
                    return $q->orderBy(['Orders.created' => 'DESC']);
                },
                'Orders.OrderItems'
            ])
            ->firstOrFail();


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

    /* =========================
     *  Edit Profile
     * ========================= */

    public function edit()
    {
        if (!$this->isAdmin()) {
            throw new \Cake\Http\Exception\ForbiddenException('Admins only.');
        }
        $identity = $this->request->getAttribute('identity');
        if (!$identity) {
            throw new UnauthorizedException('Please log in to edit your profile.');
        }

        $userId = (int)$identity->get('id');
        $user   = $this->Users->get($userId);

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

            // If password fields are left empty, avoid overwriting password
            if (empty($data['password'])) {
                unset($data['password'], $data['password_confirm']);
            }

            $user = $this->Users->patchEntity($user, $data, [
                'fields' => [
                    'email',
                    'first_name', 'last_name', 'avatar',
                    'phone', 'date_of_birth',
                    'password', 'password_confirm',
                ],
            ]);

            if (!$user->getErrors() && $this->Users->save($user)) {
                $this->Flash->success('Profile updated.');
                return $this->redirect(['action' => 'profile']);
            }

            $this->Flash->error('Could not save your changes. Please fix the errors and try again.');
        }

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

    /* =========================
     *  Preferences (Upsert)
     * ========================= */

    public function savePreference()
    {
        $this->request->allowMethod(['post']);
        $identity = $this->request->getAttribute('identity');
        if (!$identity) {
            throw new UnauthorizedException('Please log in to update preferences.');
        }

        $userId = (int)$identity->get('id');
        $key    = trim((string)$this->request->getData('pref_key'));
        $value  = trim((string)$this->request->getData('pref_value'));

        if ($key === '' || $value === '') {
            $this->Flash->error('Preference key and value are required.');
            return $this->redirect(['action' => 'profile']);
        }

        // Upsert on (user_id, pref_key)
        $pref = $this->UserPreferences->find()
            ->where(['user_id' => $userId, 'pref_key' => $key])
            ->first();

        if (!$pref) {
            $pref = $this->UserPreferences->newEmptyEntity();
            $pref = $this->UserPreferences->patchEntity($pref, [
                'user_id'   => $userId,
                'pref_key'  => $key,
                'pref_value'=> $value,
            ]);
        } else {
            $pref = $this->UserPreferences->patchEntity($pref, ['pref_value' => $value]);
        }

        if ($this->UserPreferences->save($pref)) {
            $this->Flash->success('Preference saved.');
        } else {
            $this->Flash->error('Could not save preference.');
        }

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

    /* =========================
     *  (Optional) Admin-ish: list users
     * ========================= */
    public function index()
    {
        if (!$this->isAdmin()) {
            throw new \Cake\Http\Exception\ForbiddenException('Admins only.');
        }
        // Basic list, restrict as needed
        $this->paginate = [
            'order' => ['Users.created' => 'DESC'],
            'limit' => 25,
        ];
        $users = $this->paginate($this->Users->find());
        $this->set(compact('users'));
    }

    /* =========================
     *  (Optional) View user by id (admin use)
     * ========================= */
    public function view($id = null)
    {
        if (!$this->isAdmin()) {
            throw new \Cake\Http\Exception\ForbiddenException('Admins only.');
        }
        $user = $this->Users->get((int)$id, [
            'contain' => ['UserPreferences', 'Orders.OrderItems'],
        ]);
        $this->set(compact('user'));
    }
}
