<?php

declare(strict_types=1);

/**
 * Controlled patient dental-record release helpers.
 *
 * The portal never exposes the staff-only complete-record printout. Patient
 * copies are assembled from finalized/shared dental records only and exclude
 * queue movement, audit events, internal approvals, and draft clinical notes.
 */

function patient_record_release_schema_ready(): bool
{
    static $ready;
    if ($ready !== null) return $ready;
    return $ready = schema_table_exists(table('patient_record_releases'))
        && schema_column_exists(table('patient_portal_accounts'), 'preferred_channel')
        && schema_column_exists(table('patient_portal_accounts'), 'appointment_notifications')
        && schema_column_exists(table('patient_portal_accounts'), 'record_notifications');
}

function patient_record_scope_options(): array
{
    return [
        'summary' => 'Dental record summary',
        'complete' => 'Complete finalized dental record',
        'date_range' => 'Dental records for a date range',
        'referral' => 'Referral and supporting dental records',
        'financial' => 'Invoices, payments, and receipts only',
    ];
}

function patient_record_scope_label(string $scope): string
{
    return patient_record_scope_options()[$scope] ?? 'Dental record copy';
}

function patient_record_release_status_label(string $status): string
{
    return match ($status) {
        'pending_identity' => 'Identity review required',
        'pending_clinical' => 'Dentist approval required',
        'approved' => 'Approved for release',
        'released' => 'Available in portal',
        'revoked' => 'Access revoked',
        'expired' => 'Expired',
        'declined' => 'Declined',
        default => ucwords(str_replace('_', ' ', $status)),
    };
}

function patient_record_request_payload(array $request): array
{
    $payload = json_decode((string)($request['payload_json'] ?? ''), true);
    return is_array($payload) ? $payload : [];
}

function patient_record_release_for_request(PDO $pdo, int $requestId, bool $lock = false): ?array
{
    if ($requestId < 1 || !patient_record_release_schema_ready()) return null;
    $stmt = $pdo->prepare('SELECT * FROM `' . table('patient_record_releases') . '` WHERE request_id=? LIMIT 1' . ($lock ? ' FOR UPDATE' : ''));
    $stmt->execute([$requestId]);
    $row = $stmt->fetch();
    return $row ?: null;
}

function patient_record_release_create_for_request(PDO $pdo, array $request): int
{
    $existing = patient_record_release_for_request($pdo, (int)$request['id'], true);
    if ($existing) return (int)$existing['id'];
    $payload = patient_record_request_payload($request);
    $scope = (string)($payload['scope'] ?? 'summary');
    if (!array_key_exists($scope, patient_record_scope_options())) $scope = 'summary';
    $stmt = $pdo->prepare(
        'INSERT INTO `' . table('patient_record_releases') . '` '
        . '(request_id,patient_id,branch_id,release_scope,date_from,date_to,status,created_at,updated_at) '
        . 'VALUES (?,?,?,?,?,? ,"pending_identity",NOW(),NOW())'
    );
    $stmt->execute([
        (int)$request['id'],
        (int)$request['patient_id'],
        !empty($request['patient_branch_id']) ? (int)$request['patient_branch_id'] : null,
        $scope,
        !empty($payload['date_from']) ? (string)$payload['date_from'] : null,
        !empty($payload['date_to']) ? (string)$payload['date_to'] : null,
    ]);
    return (int)$pdo->lastInsertId();
}

function patient_record_release_can_receive(): bool
{
    return in_array(active_role(), ['super_admin','clinic_admin','receptionist','staff'], true)
        && task_context_action_allowed('records.release.receive')
        && can('records.release.receive');
}

function patient_record_release_can_clinically_approve(): bool
{
    return active_role() === 'dentist'
        && has_role('dentist')
        && task_context_action_allowed('records.release.clinical_approve')
        && can('records.release.clinical_approve');
}

function patient_record_release_can_release(string $scope): bool
{
    if ($scope === 'financial') {
        return in_array(active_role(), ['super_admin','clinic_admin','cashier','staff'], true)
            && task_context_action_allowed('records.release.financial')
            && can('records.release.financial');
    }
    return in_array(active_role(), ['super_admin','clinic_admin'], true)
        && task_context_action_allowed('records.release.manage')
        && can('records.release.manage');
}

function patient_record_release_patient_rows(PDO $pdo, int $patientId): array
{
    if (!patient_record_release_schema_ready()) return [];
    $stmt = $pdo->prepare(
        'SELECT r.*,pr.request_type,pr.reason,pr.staff_note,pr.created_at requested_at,pr.updated_at request_updated_at '
        . 'FROM `' . table('patient_record_releases') . '` r '
        . 'JOIN `' . table('patient_portal_requests') . '` pr ON pr.id=r.request_id '
        . 'WHERE r.patient_id=? ORDER BY r.created_at DESC,r.id DESC'
    );
    $stmt->execute([$patientId]);
    $rows = $stmt->fetchAll();
    foreach ($rows as &$row) {
        if ((string)$row['status'] === 'released' && !empty($row['expires_at']) && strtotime((string)$row['expires_at']) < time()) {
            $row['status'] = 'expired';
        }
    }
    unset($row);
    return $rows;
}

function patient_record_release_portal_access(PDO $pdo, int $releaseId, int $accountId, int $patientId): ?array
{
    if ($releaseId < 1 || $accountId < 1 || $patientId < 1 || !patient_record_release_schema_ready()) return null;
    $access = patient_portal_access_for_patient($accountId, $patientId);
    if (!$access || empty($access['can_view_records'])) return null;
    $stmt = $pdo->prepare(
        'SELECT r.*,pr.reason,pr.staff_note,pr.created_at requested_at '
        . 'FROM `' . table('patient_record_releases') . '` r '
        . 'JOIN `' . table('patient_portal_requests') . '` pr ON pr.id=r.request_id '
        . 'WHERE r.id=? AND r.patient_id=? AND r.status="released" AND r.revoked_at IS NULL '
        . 'AND (r.expires_at IS NULL OR r.expires_at>=NOW()) LIMIT 1'
    );
    $stmt->execute([$releaseId,$patientId]);
    $row = $stmt->fetch();
    return $row ?: null;
}

function patient_record_release_date_clause(array $release, string $column, array &$args): string
{
    $sql = '';
    if (!empty($release['date_from'])) { $sql .= ' AND DATE(' . $column . ')>=?'; $args[] = (string)$release['date_from']; }
    if (!empty($release['date_to'])) { $sql .= ' AND DATE(' . $column . ')<=?'; $args[] = (string)$release['date_to']; }
    return $sql;
}
