<?php

declare(strict_types=1);

/**
 * Canonical chairside treatment flow helpers.
 * These helpers are deliberately schema-safe so status guidance can render on
 * mixed-version installs without causing white screens.
 */

function treatment_flow_steps(): array
{
    return [
        'appointment' => ['label' => 'Appointment', 'queue' => [], 'appointment' => ['requested','pending_confirmation','confirmed']],
        'checked_in' => ['label' => 'Checked in', 'queue' => ['waiting'], 'appointment' => ['checked_in']],
        'called' => ['label' => 'Called', 'queue' => ['called'], 'appointment' => ['checked_in']],
        'seated' => ['label' => 'Seated', 'queue' => ['seated'], 'appointment' => ['checked_in']],
        'in_treatment' => ['label' => 'In treatment', 'queue' => ['in_treatment'], 'appointment' => ['in_treatment']],
        'billing' => ['label' => 'Billing', 'queue' => ['waiting_billing','cashier_called'], 'appointment' => ['awaiting_billing']],
        'paid' => ['label' => 'Paid / closed', 'queue' => ['completed'], 'appointment' => ['completed']],
    ];
}

function treatment_flow_rank(string $status, string $source = 'queue'): int
{
    $status = strtolower(trim($status));
    $index = 0;
    foreach (treatment_flow_steps() as $step) {
        $index++;
        $values = (array)($step[$source] ?? []);
        if (in_array($status, $values, true)) return $index;
    }
    if (in_array($status, ['cancelled','no_show','left_before_treatment','voided'], true)) return -1;
    return 0;
}

function treatment_flow_label(?string $status): string
{
    $status = trim((string)$status);
    if ($status === '') return 'Not started';
    return ucwords(str_replace('_', ' ', $status));
}

function treatment_flow_stage_from_rows(array $row): string
{
    $queueStatus = (string)($row['queue_status'] ?? $row['status'] ?? '');
    $appointmentStatus = (string)($row['appointment_status'] ?? '');
    $encounterStatus = (string)($row['encounter_status'] ?? '');
    if (in_array($queueStatus, ['completed'], true) || $appointmentStatus === 'completed') return 'paid';
    if (in_array($queueStatus, ['waiting_billing','cashier_called'], true) || $appointmentStatus === 'awaiting_billing') return 'billing';
    if ($queueStatus === 'in_treatment' || in_array($encounterStatus, ['draft','pending_review'], true) || $appointmentStatus === 'in_treatment') return 'in_treatment';
    if ($queueStatus === 'seated') return 'seated';
    if ($queueStatus === 'called') return 'called';
    if ($queueStatus === 'waiting' || $appointmentStatus === 'checked_in') return 'checked_in';
    if ($appointmentStatus !== '') return 'appointment';
    return 'appointment';
}

function treatment_flow_stage_index(string $stage): int
{
    $keys = array_keys(treatment_flow_steps());
    $index = array_search($stage, $keys, true);
    return $index === false ? 0 : (int)$index + 1;
}

function treatment_flow_patient_name(array $row): string
{
    if (function_exists('patient_full_name')) {
        return patient_full_name($row);
    }
    return trim(implode(' ', array_filter([
        (string)($row['first_name'] ?? ''),
        (string)($row['middle_name'] ?? ''),
        (string)($row['last_name'] ?? ''),
    ]))) ?: 'Patient';
}

function treatment_flow_state(PDO $pdo, array $row): array
{
    $stage = treatment_flow_stage_from_rows($row);
    $currentIndex = treatment_flow_stage_index($stage);
    $steps = [];
    $i = 0;
    foreach (treatment_flow_steps() as $key => $step) {
        $i++;
        $steps[] = [
            'key' => $key,
            'label' => (string)$step['label'],
            'state' => $i < $currentIndex ? 'done' : ($i === $currentIndex ? 'current' : 'pending'),
        ];
    }
    return [
        'stage' => $stage,
        'steps' => $steps,
        'queue_status' => (string)($row['queue_status'] ?? $row['status'] ?? ''),
        'appointment_status' => (string)($row['appointment_status'] ?? ''),
        'encounter_status' => (string)($row['encounter_status'] ?? ''),
        'patient' => treatment_flow_patient_name($row),
        'problems' => treatment_flow_problems($pdo, $row),
        'next_action' => treatment_flow_next_action($row),
    ];
}

function treatment_flow_problems(PDO $pdo, array $row): array
{
    $problems = [];
    $queueStatus = (string)($row['queue_status'] ?? $row['status'] ?? '');
    $encounterStatus = (string)($row['encounter_status'] ?? '');
    $providerType = ((string)($row['provider_type'] ?? 'dentist') === 'inhouse') ? 'inhouse' : 'dentist';
    $queueId = (int)($row['queue_entry_id'] ?? $row['id'] ?? 0);
    $encounterId = (int)($row['encounter_id'] ?? 0);

    if ($providerType === 'dentist') {
        if ((int)($row['dentist_user_id'] ?? 0) < 1) $problems[] = 'Responsible Dentist is not assigned.';
        if (in_array($queueStatus, ['seated','in_treatment'], true) && (int)($row['chair_id'] ?? 0) < 1 && trim((string)($row['chair_name'] ?? '')) === '') {
            $problems[] = 'Treatment chair is not assigned.';
        }
        if ($queueStatus === 'in_treatment' && $encounterId < 1) {
            $problems[] = 'Queue is in treatment but no clinical encounter is linked.';
        }
        if ($queueStatus === 'waiting_billing' && $encounterStatus !== '' && !in_array($encounterStatus, ['finalized','addendum'], true)) {
            $problems[] = 'Queue is waiting for billing, but the clinical encounter is not finalized.';
        }
        if ($queueStatus === 'in_treatment' && in_array($encounterStatus, ['finalized','addendum'], true)) {
            $problems[] = 'Clinical encounter is finalized but the queue is still in treatment.';
        }
        if ($queueId > 0 && function_exists('queue_active_chair_occupants') && in_array($queueStatus, ['seated','in_treatment'], true)) {
            try {
                $duplicates = queue_active_chair_occupants($pdo, $row, ['seated','in_treatment'], $queueId);
                if ($duplicates) $problems[] = 'Another active queue ticket is using the same chair.';
            } catch (Throwable $exception) {
                error_log('DentalCare treatment-flow chair check failed: ' . $exception->getMessage());
            }
        }
    }

    if ($queueStatus === 'called' && !empty($row['called_at']) && strtotime((string)$row['called_at']) < time() - 30 * 60) {
        $problems[] = 'Patient has been called for more than 30 minutes without seating.';
    }
    if ($queueStatus === 'seated' && !empty($row['seated_at']) && strtotime((string)$row['seated_at']) < time() - 45 * 60) {
        $problems[] = 'Patient has been seated for more than 45 minutes without treatment start.';
    }

    return array_values(array_unique(array_filter($problems)));
}

function treatment_flow_next_action(array $row): string
{
    $stage = treatment_flow_stage_from_rows($row);
    return match ($stage) {
        'appointment' => 'Confirm appointment and check in the patient.',
        'checked_in' => 'Call the patient when the chair/provider is ready.',
        'called' => 'Seat the patient in the assigned chair.',
        'seated' => 'Open Start treatment to create or resume the clinical encounter.',
        'in_treatment' => 'Complete clinical record, verify procedures, then send to Cashier or discharge as no-payment.',
        'billing' => 'Cashier should collect payment and print the itemized receipt.',
        'paid' => 'Visit is closed. Book recall or follow-up if needed.',
        default => 'Review the patient journey and complete the next valid step.',
    };
}

function treatment_flow_render_steps(array $state, bool $compact = false): void
{
    $class = $compact ? ' treatment-flow-steps-compact' : '';
    echo '<div class="treatment-flow-steps' . $class . '">';
    foreach ((array)($state['steps'] ?? []) as $step) {
        $stepClass = preg_replace('/[^a-z_\-]/', '', (string)($step['state'] ?? 'pending')) ?: 'pending';
        echo '<span class="treatment-flow-step ' . e($stepClass) . '"><i></i><strong>' . e((string)($step['label'] ?? 'Step')) . '</strong></span>';
    }
    echo '</div>';
}

function treatment_flow_render_card(array $state, string $title = 'Visit flow'): void
{
    $problems = (array)($state['problems'] ?? []);
    echo '<section class="card treatment-flow-card">';
    echo '<div class="card-head"><div><span class="eyebrow">Treatment status flow</span><h2>' . e($title) . '</h2><p>' . e((string)($state['next_action'] ?? 'Review the next valid step.')) . '</p></div><span class="badge ' . ($problems ? 'warning' : 'success') . '">' . ($problems ? 'Needs review' : 'On track') . '</span></div>';
    treatment_flow_render_steps($state, false);
    if ($problems) {
        echo '<div class="alert warning compact-alert"><strong>Flow checks needing attention</strong><ul>';
        foreach (array_slice($problems, 0, 5) as $problem) echo '<li>' . e((string)$problem) . '</li>';
        echo '</ul></div>';
    }
    echo '</section>';
}

function treatment_flow_render_mini(array $row, ?PDO $pdo = null): void
{
    if (!$pdo) $pdo = db();
    $state = treatment_flow_state($pdo, $row);
    echo '<div class="treatment-flow-mini">';
    treatment_flow_render_steps($state, true);
    echo '<small>' . e((string)$state['next_action']) . '</small>';
    if (!empty($state['problems'])) echo '<small class="danger-text">' . e(implode(' · ', array_slice((array)$state['problems'], 0, 2))) . '</small>';
    echo '</div>';
}

function treatment_flow_schema_ready(): bool
{
    return function_exists('schema_table_exists')
        && schema_table_exists(table('queue_entries'))
        && schema_table_exists(table('clinical_encounters'))
        && schema_table_exists(table('appointments'))
        && schema_column_exists(table('queue_entries'), 'status')
        && schema_column_exists(table('clinical_encounters'), 'status');
}
