<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Controller;
use App\Core\Csrf;
use App\Core\Response;
use App\Core\Session;
use App\Services\AssignmentService;
use App\Services\SessionService;
use InvalidArgumentException;
use RuntimeException;

final class SessionController extends Controller
{
    public function __construct(private ?SessionService $service=null, private ?AssignmentService $assignments=null)
    {
        $this->service ??= new SessionService();
        $this->assignments ??= new AssignmentService();
    }

    public function index(): Response
    {
        $therapistId=$this->therapistIdIfTherapist();
        $result=$this->service->list($_GET,$therapistId);
        return $this->view('sessions/index',[
            'pageTitle'=>'Therapy Sessions','pageDescription'=>$therapistId!==null?'Your current assigned-patient sessions.':'Manage therapy sessions and clinical notes.',
            'sessions'=>$result['items'],'pagination'=>$result,
            'filters'=>['search'=>(string)($_GET['search']??''),'status'=>(string)($_GET['status']??''),'date'=>(string)($_GET['date']??'')],
        ]);
    }

    public function createForm(): Response
    {
        $therapistId=$this->therapistIdIfTherapist();
        return $this->view('sessions/form',[
            'pageTitle'=>'Record Therapy Session','pageDescription'=>'Record a session only for a patient with a current therapist assignment.',
            'session'=>null,'csrf'=>Csrf::token(),'form'=>Session::pull('session_form')??(isset($_GET['appointment_id'])?['appointment_id'=>(int)$_GET['appointment_id']]:[]),
            'error'=>Session::pull('session_error'),'message'=>Session::pull('session_message'),
            ...($therapistId!==null?$this->service->therapistFormData($therapistId):$this->service->formData()),
            'therapistLocked'=>$therapistId!==null,
        ]);
    }

    public function create(): Response
    {
        Csrf::verify((string)($_POST['_csrf']??''));
        $therapistId=$this->therapistIdIfTherapist();
        try {
            $id=$this->service->create($_POST,Auth::id()??0,$therapistId);
            Session::put('session_message','Therapy session recorded successfully.');
            return Response::redirect('/crm/public/sessions/'.$id.'/edit');
        } catch(InvalidArgumentException $e) {
            Session::put('session_error',$e->getMessage()); Session::put('session_form',$_POST);
            return Response::redirect('/crm/public/sessions/create');
        }
    }

    public function editForm(int $id): Response
    {
        $therapistId=$this->therapistIdIfTherapist();
        $session=$this->service->find($id);
        $this->authorizeSession($session,$therapistId);
        return $this->view('sessions/form',[
            'pageTitle'=>'Edit Therapy Session','pageDescription'=>'Update the clinical session record.',
            'session'=>$session,'csrf'=>Csrf::token(),'form'=>Session::pull('session_form')??[],
            'error'=>Session::pull('session_error'),'message'=>Session::pull('session_message'),
            ...($therapistId!==null?$this->service->therapistFormData($therapistId):$this->service->formData()),
            'therapistLocked'=>$therapistId!==null,
        ]);
    }

    public function update(int $id): Response
    {
        Csrf::verify((string)($_POST['_csrf']??''));
        $therapistId=$this->therapistIdIfTherapist();
        try {
            $session=$this->service->find($id); $this->authorizeSession($session,$therapistId);
            $this->service->update($id,$_POST,Auth::id()??0,$therapistId);
            Session::put('session_message','Therapy session updated successfully.');
        } catch(InvalidArgumentException $e) {
            Session::put('session_error',$e->getMessage()); Session::put('session_form',$_POST);
        }
        return Response::redirect('/crm/public/sessions/'.$id.'/edit');
    }

    private function therapistIdIfTherapist(): ?int
    {
        if (!Auth::hasRole('THERAPIST')) return null;
        $id=$this->assignments->therapistIdForUser(Auth::id()??0);
        if ($id===null) throw new RuntimeException('Your therapist profile is not active.',403);
        return $id;
    }

    private function authorizeSession(array $session, ?int $therapistId): void
    {
        if ($therapistId!==null && ((int)$session['therapist_id']!==$therapistId || !$this->service->canTherapistAccess((int)$session['id'],$therapistId))) {
            throw new RuntimeException('You do not have permission to access this session.',403);
        }
    }
}
