<?php

namespace App\Controllers;

use App\Models\UserModel;
use App\Services\AuditService;

class Auth extends BaseController
{
    public function loginForm() { return $this->render('auth/login',['title'=>'Sign in | TibaLeta']); }
    public function registerForm() { return $this->render('auth/register',['title'=>'Create account | TibaLeta','practitioner'=>false]); }
    public function practitionerRegisterForm() { return $this->render('auth/register',['title'=>'Join as practitioner | TibaLeta','practitioner'=>true]); }

    public function login()
    {
        $rules=['email'=>'required|valid_email|max_length[190]','password'=>'required|max_length[200]'];
        if(!$this->validate($rules)) return redirect()->back()->withInput()->with('errors',$this->validator->getErrors());
        $email=strtolower(trim((string)$this->request->getPost('email')));
        $user=(new UserModel())->where('email',$email)->first();
        if(!$user || !password_verify((string)$this->request->getPost('password'),$user['password_hash']) || $user['status']!=='active') {
            return redirect()->back()->withInput()->with('error','We could not sign you in with those details.');
        }
        (new UserModel())->update($user['id'],['last_login_at'=>date('Y-m-d H:i:s')]);
        $this->session->regenerate(true);
        $this->session->set('auth_user',['id'=>(int)$user['id'],'full_name'=>$user['full_name'],'email'=>$user['email'],'role'=>$user['role'],'avatar'=>$user['avatar']]);
        (new AuditService())->log('auth.login','user',(int)$user['id']);
        $target=$this->session->get('intended_url'); $this->session->remove('intended_url');
        if($target) return redirect()->to($target);
        return redirect()->to(match($user['role']){'admin','operations'=>'/admin','practitioner'=>'/practitioner','partner'=>'/partner',default=>'/patient'});
    }

    public function register(bool $practitioner=false)
    {
        $rules=['full_name'=>'required|min_length[2]|max_length[120]','email'=>'required|valid_email|max_length[190]|is_unique[users.email]','phone'=>'required|min_length[8]|max_length[30]','password'=>'required|min_length[10]|max_length[200]','password_confirm'=>'required|matches[password]'];
        if(!$this->validate($rules)) return redirect()->back()->withInput()->with('errors',$this->validator->getErrors());
        $role=$practitioner?'practitioner':'patient';
        $db=db_connect(); $db->transStart();
        $model=new UserModel();
        $id=$model->insert(['full_name'=>trim((string)$this->request->getPost('full_name')),'email'=>strtolower(trim((string)$this->request->getPost('email'))),'phone'=>trim((string)$this->request->getPost('phone')),'password_hash'=>password_hash((string)$this->request->getPost('password'),PASSWORD_DEFAULT),'role'=>$role,'status'=>'active']);
        if($practitioner){$db->table('practitioner_profiles')->insert(['user_id'=>$id,'profession'=>trim((string)$this->request->getPost('profession')) ?: 'Healthcare Practitioner','verification_status'=>'pending','is_online'=>0,'created_at'=>date('Y-m-d H:i:s'),'updated_at'=>date('Y-m-d H:i:s')]);}
        else {$db->table('patient_profiles')->insert(['user_id'=>$id,'created_at'=>date('Y-m-d H:i:s'),'updated_at'=>date('Y-m-d H:i:s')]);}
        $db->transComplete();
        if(!$db->transStatus()) return redirect()->back()->withInput()->with('error','Account creation failed. Please try again.');
        (new AuditService())->log('auth.register','user',(int)$id,['role'=>$role]);
        return redirect()->to('/login')->with('success',$practitioner?'Account created. Your practitioner profile is pending verification.':'Your TibaLeta account is ready. Sign in to request care.');
    }

    public function patientRegister(){ return $this->register(false); }
    public function practitionerRegister(){ return $this->register(true); }
    public function forgotForm(){ return $this->render('auth/forgot',['title'=>'Reset password | TibaLeta']); }

    public function forgot()
    {
        $email=strtolower(trim((string)$this->request->getPost('email')));
        if(!filter_var($email,FILTER_VALIDATE_EMAIL)) return redirect()->back()->with('success','If an account exists for that email, a reset link will be sent.');
        $user=(new UserModel())->where('email',$email)->first();
        if($user){$token=bin2hex(random_bytes(32));$hash=hash('sha256',$token);$db=db_connect();$db->table('password_reset_tokens')->where('user_id',$user['id'])->where('used_at',null)->delete();$db->table('password_reset_tokens')->insert(['user_id'=>$user['id'],'token_hash'=>$hash,'expires_at'=>date('Y-m-d H:i:s',time()+3600),'created_at'=>date('Y-m-d H:i:s')]);(new \App\Services\EmailService())->sendPasswordReset($email,$token);(new AuditService())->log('auth.password_reset_requested','user',(int)$user['id']);}
        return redirect()->to('/login')->with('success','If an account exists for that email, a reset link has been sent.');
    }

    public function resetForm(string $token)
    {
        $row=db_connect()->table('password_reset_tokens')->where('token_hash',hash('sha256',$token))->where('used_at',null)->where('expires_at >=',date('Y-m-d H:i:s'))->get()->getRowArray();
        if(!$row) return redirect()->to('/login')->with('error','That password reset link is invalid or has expired.');
        return $this->render('auth/reset',['title'=>'Choose a new password | TibaLeta','token'=>$token]);
    }

    public function reset(string $token)
    {
        $rules=['password'=>'required|min_length[10]|max_length[200]','password_confirm'=>'required|matches[password]'];
        if(!$this->validate($rules)) return redirect()->back()->with('errors',$this->validator->getErrors());
        $db=db_connect();$row=$db->table('password_reset_tokens')->where('token_hash',hash('sha256',$token))->where('used_at',null)->where('expires_at >=',date('Y-m-d H:i:s'))->get()->getRowArray();if(!$row)return redirect()->to('/login')->with('error','That password reset link is invalid or has expired.');
        $db->transStart();(new UserModel())->update((int)$row['user_id'],['password_hash'=>password_hash((string)$this->request->getPost('password'),PASSWORD_DEFAULT)]);$db->table('password_reset_tokens')->where('id',$row['id'])->update(['used_at'=>date('Y-m-d H:i:s')]);$db->transComplete();(new AuditService())->log('auth.password_reset_completed','user',(int)$row['user_id']);
        return redirect()->to('/login')->with('success','Your password has been updated.');
    }

    public function logout(){ $this->session->destroy(); return redirect()->to('/')->with('success','You have been signed out securely.'); }
}
