<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Login extends MY_Controller
{
	protected bool $requireAuth = false;

	public function __construct()
	{
		parent::__construct();
		$this->load->model('Login_model', 'auth');
	}

	public function index(): void
	{
		if ($this->auth->logged_in()) {
			redirect($this->resolveRedirect());
			return;
		}

		$this->form_validation->set_rules($this->auth->rules());


		if ($this->form_validation->run() === true) {
			$remember = (bool) $this->input->post('remember');
			$success = $this->auth->attempt(
				(string) $this->input->post('user_name', true),
				(string) $this->input->post('password', true),
				$remember
			);

			if ($success) {
				$next = $this->resolveRedirect();
				$this->session->set_userdata('url', $next);
				redirect($next);
				return;
			}

			$this->session->set_flashdata('error', 'Incorrect username or password.');
			redirect('login');
			return;
		}

		$data = array(
			'title' => 'Sign in',
			'error' => $this->session->flashdata('error'),
		);

		$this->load->view('auth/login', $data);
	}

	public function register(): void
	{
		if ($this->isPost()) {
			$this->form_validation->set_rules('company_name', 'Company name', 'trim|required|max_length[255]');
			$this->form_validation->set_rules('fullname', 'Full name', 'trim|required|max_length[160]');
			$this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email|max_length[100]');
			$this->form_validation->set_rules('username', 'Username', 'trim|required|max_length[50]|alpha_dash');
			$this->form_validation->set_rules('password', 'Password', 'trim|required|min_length[6]');
			$this->form_validation->set_rules('confirm_password', 'Confirm password', 'trim|required|matches[password]');

			if ($this->form_validation->run() === true) {
				$result = $this->auth->register_client_company(array(
					'company_name' => (string) $this->input->post('company_name', true),
					'fullname' => (string) $this->input->post('fullname', true),
					'email' => (string) $this->input->post('email', true),
					'username' => (string) $this->input->post('username', true),
					'password' => (string) $this->input->post('password', true),
					'phone' => (string) $this->input->post('phone', true),
					'address' => (string) $this->input->post('address', true),
					'city' => (string) $this->input->post('city', true),
					'country' => (string) $this->input->post('country', true),
					'website' => (string) $this->input->post('website', true),
				));

				if (!empty($result['success'])) {
					$this->session->set_flashdata('success', 'Your client account has been created. Please sign in.');
					redirect('login');
					return;
				}

				$this->session->set_flashdata('error', $result['message'] ?? 'Unable to create account.');
				redirect('login/register');
				return;
			}
		}

		$data = array(
			'title' => 'Create client account',
			'error' => $this->session->flashdata('error'),
		);
		$this->load->view('auth/register', $data);
	}

	public function forgot_password(): void
	{
		if ($this->auth->logged_in()) {
			redirect($this->resolveRedirect());
			return;
		}

		if ($this->isPost()) {
			$this->form_validation->set_rules('identity', 'Email or username', 'trim|required|max_length[100]');

			if ($this->form_validation->run() === true) {
				$identity = (string) $this->input->post('identity', true);
				$result = $this->auth->request_password_reset($identity);

				if (!empty($result['email_sent'])) {
					$this->session->set_flashdata('success', 'If the account exists, password reset instructions have been sent.');
				} else {
					$this->session->set_flashdata('error', $result['message'] ?? 'Unable to send password reset instructions. Please contact support.');
				}
				redirect('login/forgot_password');
				return;
			}
		}

		$data = array(
			'title' => 'Forgot password',
			'error' => $this->session->flashdata('error'),
		);
		$this->load->view('auth/forgot_password', $data);
	}

	public function reset_password($userId = null, $key = null): void
	{
		if ($this->auth->logged_in()) {
			redirect($this->resolveRedirect());
			return;
		}

		$userId = (int) $userId;
		$key = (string) $key;
		$user = $this->auth->get_valid_password_reset($userId, $key);

		if (!$user) {
			$this->session->set_flashdata('error', 'This password reset link is invalid or has expired.');
			redirect('login/forgot_password');
			return;
		}

		if ($this->isPost()) {
			$this->form_validation->set_rules('password', 'New password', 'trim|required|min_length[6]');
			$this->form_validation->set_rules('confirm_password', 'Confirm password', 'trim|required|matches[password]');

			if ($this->form_validation->run() === true) {
				$password = (string) $this->input->post('password', true);
				if ($this->auth->complete_password_reset($userId, $key, $password)) {
					$this->session->set_flashdata('success', 'Your password has been reset. Please sign in with the new password.');
					redirect('login');
					return;
				}

				$this->session->set_flashdata('error', 'This password reset link is invalid or has expired.');
				redirect('login/forgot_password');
				return;
			}
		}

		$data = array(
			'title' => 'Reset password',
			'error' => $this->session->flashdata('error'),
			'user_id' => $userId,
			'reset_key' => $key,
			'user' => $user,
		);
		$this->load->view('auth/reset_password', $data);
	}

	private function isPost(): bool
	{
		return strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')) === 'POST';
	}

	private function resolveRedirect(): string
	{
		$userType = (int) ($this->session->userdata('user_type') ?? 0);
		$target = (string) ($this->session->userdata('url') ?? '');
		if ($userType === 2) {
			// Force client users to client panel if old/stale admin URL is in session.
			if ($target === '' || strpos($target, 'client/') !== 0) {
				return 'client/dashboard';
			}
			return $target;
		}
		if ($userType === 3) {
			$allowedRoutes = $this->staffRoutes();
			if (!empty($target) && $target !== 'admin/dashboard' && in_array($target, $allowedRoutes, true)) {
				return $target;
			}
			foreach ($allowedRoutes as $route) {
				if ($route !== 'admin/dashboard') {
					return $route;
				}
			}
			if (!empty($allowedRoutes)) {
				return $allowedRoutes[0];
			}
			return 'admin/dashboard';
		}
		if ($target === '') {
			return 'admin/dashboard';
		}
		if (strpos($target, 'admin/') !== 0) {
			return 'admin/dashboard';
		}
		return $target;
	}

	private function staffRoutes(): array
	{
		$this->load->model('Menu_model');
		$tree = $this->Menu_model->get_active_tree(true);
		$routes = array();
		$collect = function (array $items) use (&$collect, &$routes) {
			foreach ($items as $item) {
				$route = trim((string) ($item['route'] ?? ''));
				if ($route !== '' && $route !== '#' && !in_array($route, $routes, true)) {
					$routes[] = $route;
				}
				if (!empty($item['children']) && is_array($item['children'])) {
					$collect($item['children']);
				}
			}
		};
		$collect($tree);
		return $routes;
	}

	public function logout(): void
	{
		$this->auth->logout();
		redirect('login');
	}
}
