<?php

declare(strict_types=1);

namespace App\Repositories;

use App\Core\Database;
use PDO;

final class TreatmentPlanRepository
{
    public function paginate(array $filters, ?int $therapistId = null, int $perPage = 25): array
    {
        $where = ['tp.status <> "closed"']; $params = [];
        if ($therapistId !== null) { $where[] = 'tp.therapist_id=:therapist_id'; $params['therapist_id']=$therapistId; }
        if (($filters['search'] ?? '') !== '') {
            $where[]='(p.patient_reference LIKE :search_ref OR p.first_name LIKE :search_first OR p.last_name LIKE :search_last OR u.full_name LIKE :search_therapist)';
            $search='%'.trim((string)$filters['search']).'%';
            $params['search_ref']=$search; $params['search_first']=$search; $params['search_last']=$search; $params['search_therapist']=$search;
        }
        if (($filters['status'] ?? '') !== '') { $where[]='tp.status=:status'; $params['status']=$filters['status']; }
        $whereSql='WHERE '.implode(' AND ',$where); $pdo=Database::connection();
        $count=$pdo->prepare("SELECT COUNT(*) FROM treatment_plans tp INNER JOIN patients p ON p.id=tp.patient_id INNER JOIN therapists t ON t.id=tp.therapist_id INNER JOIN users u ON u.id=t.user_id $whereSql");
        $count->execute($params); $total=(int)$count->fetchColumn(); $pages=max(1,(int)ceil($total/$perPage)); $page=min(max(1,(int)($filters['page']??1)),$pages); $offset=($page-1)*$perPage;
        $sql="SELECT tp.*, p.patient_reference,p.first_name,p.last_name,u.full_name AS therapist_name
              FROM treatment_plans tp INNER JOIN patients p ON p.id=tp.patient_id INNER JOIN therapists t ON t.id=tp.therapist_id INNER JOIN users u ON u.id=t.user_id
              $whereSql ORDER BY tp.updated_at DESC,tp.id DESC LIMIT :limit OFFSET :offset";
        $stmt=$pdo->prepare($sql); foreach($params as $k=>$v)$stmt->bindValue(':'.$k,$v); $stmt->bindValue(':limit',$perPage,PDO::PARAM_INT);$stmt->bindValue(':offset',$offset,PDO::PARAM_INT);$stmt->execute();
        return ['items'=>$stmt->fetchAll(),'total'=>$total,'page'=>$page,'pages'=>$pages,'perPage'=>$perPage];
    }

    public function find(int $id): ?array
    { $stmt=Database::connection()->prepare('SELECT tp.*,p.patient_reference,p.first_name,p.last_name,u.full_name AS therapist_name FROM treatment_plans tp INNER JOIN patients p ON p.id=tp.patient_id INNER JOIN therapists t ON t.id=tp.therapist_id INNER JOIN users u ON u.id=t.user_id WHERE tp.id=:id LIMIT 1');$stmt->execute(['id'=>$id]);$r=$stmt->fetch();return is_array($r)?$r:null; }

    public function patientsForTherapist(int $therapistId): array
    { $stmt=Database::connection()->prepare('SELECT DISTINCT p.id,p.patient_reference,p.first_name,p.last_name FROM patients p INNER JOIN patient_assignments pa ON pa.patient_id=p.id WHERE p.status="active" AND p.deleted_at IS NULL AND pa.therapist_id=:tid AND pa.status="active" AND pa.ended_at IS NULL ORDER BY p.last_name,p.first_name');$stmt->execute(['tid'=>$therapistId]);return $stmt->fetchAll(); }
    public function allPatients(): array { return Database::connection()->query('SELECT id,patient_reference,first_name,last_name FROM patients WHERE status="active" AND deleted_at IS NULL ORDER BY last_name,first_name')->fetchAll(); }
    public function therapists(): array { return Database::connection()->query('SELECT t.id,u.full_name,u.email,t.professional_title FROM therapists t INNER JOIN users u ON u.id=t.user_id WHERE t.status="active" AND u.status="active" ORDER BY u.full_name')->fetchAll(); }
    public function activeAssignment(int $patientId,int $therapistId): ?array { $s=Database::connection()->prepare('SELECT id,patient_id,therapist_id,assigned_at FROM patient_assignments WHERE patient_id=:p AND therapist_id=:t AND status="active" AND ended_at IS NULL ORDER BY assigned_at DESC,id DESC LIMIT 1');$s->execute(['p'=>$patientId,'t'=>$therapistId]);$r=$s->fetch();return is_array($r)?$r:null; }
    public function create(array $d): int { $s=Database::connection()->prepare('INSERT INTO treatment_plans (patient_id,therapist_id,assignment_id,goals,short_term_goals,long_term_goals,interventions,frequency,review_date,recommendations,status) VALUES (:patient_id,:therapist_id,:assignment_id,:goals,:short_term_goals,:long_term_goals,:interventions,:frequency,:review_date,:recommendations,"draft")'); $params=array_intersect_key($d,array_flip(['patient_id','therapist_id','assignment_id','goals','short_term_goals','long_term_goals','interventions','frequency','review_date','recommendations'])); $s->execute($params); return (int)Database::connection()->lastInsertId(); }
    public function update(int $id,array $d): void { $s=Database::connection()->prepare('UPDATE treatment_plans SET patient_id=:patient_id,therapist_id=:therapist_id,assignment_id=:assignment_id,goals=:goals,short_term_goals=:short_term_goals,long_term_goals=:long_term_goals,interventions=:interventions,frequency=:frequency,review_date=:review_date,recommendations=:recommendations,status=:status,updated_at=NOW() WHERE id=:id');$d['id']=$id;$s->execute($d); }
    public function setStatus(int $id,string $status): void { $s=Database::connection()->prepare('UPDATE treatment_plans SET status=:status,updated_at=NOW() WHERE id=:id');$s->execute(['id'=>$id,'status'=>$status]); }
    public function audit(int $userId,string $action,int $entityId,array $metadata=[]): void { $s=Database::connection()->prepare('INSERT INTO audit_logs (user_id,action,entity_type,entity_id,ip_address,metadata,created_at) VALUES (:user_id,:action,:entity_type,:entity_id,:ip,:metadata,NOW())');$s->execute(['user_id'=>$userId,'action'=>$action,'entity_type'=>'treatment_plan','entity_id'=>$entityId,'ip'=>$_SERVER['REMOTE_ADDR']??null,'metadata'=>json_encode($metadata,JSON_THROW_ON_ERROR)]); }
}
