<?php
/**
 * POST /api/lab/save_domicilio.php
 * Crea, actualiza o cambia estado de un domicilio.
 * Body JSON:
 *   { id?, paciente_id, orden_id?, direccion, ciudad?, barrio?,
 *     indicaciones_dir?, fecha_programada, hora_programada?,
 *     tipo_servicio?, estado?,
 *     -- Para cambio de estado solamente:
 *     solo_estado?: true, nuevo_estado?, motivo_cancelacion?, ... }
 */
require_once __DIR__ . '/_helpers.php';
requireMethod('POST');

try {
    $datos = inputJson();
    $dom   = new Domicilio();
    $admin = adminId();

    // ── Reprogramar ──
    if (!empty($datos['id']) && !empty($datos['reprogramar'])) {
        $id = (int)$datos['id'];
        // Enfermero solo puede reprogramar domicilios que él mismo creó
        if (userRole() === 'enfermero') {
            $dbCheck = Database::getInstance();
            $chk     = $dbCheck->fetchOne("SELECT creado_por FROM lab_domicilios WHERE id = ?", [$id]);
            if (!$chk || (int)($chk['creado_por'] ?? 0) !== adminId()) {
                jsonError('Solo puedes reprogramar domicilios que tú mismo agendaste.');
            }
        }
        $nuevaFecha = trim($datos['nueva_fecha'] ?? '');
        $nuevaHora  = trim($datos['nueva_hora']  ?? '');
        $motivo     = trim($datos['motivo']       ?? '');
        if (!$nuevaFecha) jsonError('nueva_fecha es obligatoria');
        $nuevoId = $dom->reprogramar($id, $nuevaFecha, $nuevaHora, $motivo, $admin);
        jsonOk(['id_origen' => $id, 'id_nuevo' => $nuevoId], 'Domicilio reprogramado correctamente');
    }

    // Solo cambio de estado
    if (!empty($datos['id']) && !empty($datos['solo_estado'])) {
        $id          = (int)$datos['id'];
        $nuevoEstado = $datos['nuevo_estado'] ?? '';
        $extras      = array_filter([
            'motivo_cancelacion' => $datos['motivo_cancelacion'] ?? null,
            'fecha_reprogramada' => $datos['fecha_reprogramada'] ?? null,
            'hora_llegada'       => $datos['hora_llegada']       ?? null,
            'hora_salida'        => $datos['hora_salida']        ?? null,
            'observaciones'      => $datos['observaciones']      ?? null,
            'muestras_tomadas'   => $datos['muestras_tomadas']   ?? null,
        ]);
        $dom->cambiarEstado($id, $nuevoEstado, $admin, $extras);
        jsonOk(['id' => $id], 'Estado actualizado');
    }

    if (!empty($datos['id'])) {
        // Actualización general
        $id = (int)$datos['id'];
        // Enfermero puede editar domicilios que creó o que tiene asignados
        if (userRole() === 'enfermero') {
            $dbCheck = Database::getInstance();
            $chk = $dbCheck->fetchOne(
                "SELECT d.creado_por,
                        (SELECT COUNT(*) FROM lab_asignaciones a
                          WHERE a.domicilio_id = d.id AND a.enfermera_id = ?) AS asignado
                   FROM lab_domicilios d WHERE d.id = ?",
                [enfermeraId(), $id]
            );
            if (!$chk || ((int)($chk['creado_por'] ?? 0) !== adminId() && !(int)$chk['asignado'])) {
                jsonError('Solo puedes editar domicilios que agendaste o que tienes asignados.');
            }
        }
        unset($datos['id'], $datos['solo_estado']);
        // Normalizar orden_id: vacío o 0 → null
        if (isset($datos['orden_id']) && ($datos['orden_id'] === '' || (int)$datos['orden_id'] === 0)) {
            $datos['orden_id'] = null;
        }
        $dom->actualizar($id, $datos, $admin);
        jsonOk(['id' => $id], 'Domicilio actualizado correctamente');
    } else {
        // Creación
        foreach (['paciente_id', 'direccion', 'fecha_programada'] as $req) {
            if (empty($datos[$req])) {
                jsonError("El campo $req es obligatorio");
            }
        }
        // Validar formato mínimo de dirección
        $dirVal = trim($datos['direccion'] ?? '');
        if (strlen($dirVal) < 5) {
            jsonError('La dirección es muy corta. Ingresa una dirección completa. Ej: Cra 15 # 32-10.');
        }
        // Normalizar orden_id: vacío o 0 → null (evita FK constraint)
        if (isset($datos['orden_id']) && ($datos['orden_id'] === '' || (int)$datos['orden_id'] === 0)) {
            $datos['orden_id'] = null;
        }
        // Si el creador es un enfermero y no vino enfermera_id, auto-asignarlo desde la sesión
        if (empty($datos['enfermera_id']) && userRole() === 'enfermero') {
            $eid = enfermeraId();
            if ($eid) $datos['enfermera_id'] = $eid;
        }
        // Asignar número de orden D-YYYYMMDD-NNN si no viene uno
        if (empty($datos['numero_orden'])) {
            $pdo    = db();
            $prefix = 'D-' . date('Ymd') . '-';
            $st     = $pdo->prepare(
                "SELECT MAX(CAST(SUBSTRING_INDEX(numero_orden, '-', -1) AS UNSIGNED)) AS ultimo
                   FROM lab_domicilios WHERE numero_orden LIKE ?"
            );
            $st->execute([$prefix . '%']);
            $ultimo               = (int)($st->fetch(\PDO::FETCH_ASSOC)['ultimo'] ?? 0);
            $datos['numero_orden'] = $prefix . str_pad($ultimo + 1, 3, '0', STR_PAD_LEFT);
        }

        $id = $dom->crear($datos, $admin);

        // Crear asignación automática si se indicó enfermera_id
        if (!empty($datos['enfermera_id'])) {
            $asig = new Asignacion();
            $asig->asignar($id, (int)$datos['enfermera_id'], $admin);
        }

        jsonOk(['id' => $id], 'Domicilio creado correctamente');
    }
} catch (InvalidArgumentException $e) {
    jsonError($e->getMessage());
} catch (Exception $e) {
    jsonError($e->getMessage(), 500);
}
