<?php
declare(strict_types=1);

/**
 * JSON client auth + appointments for native apps.
 * Cookie session matches the web client portal.
 *
 * GET  action=me|appointments
 * POST action=login|register|logout|cancel|delete
 */
require_once dirname(__DIR__) . '/lib/tenant.php';
require_once dirname(__DIR__) . '/lib/client.php';
require_once dirname(__DIR__) . '/lib/reminders.php';

if (session_status() !== PHP_SESSION_ACTIVE) {
    session_start();
}

$raw = file_get_contents('php://input') ?: '';
$json = json_decode($raw, true);
if (!is_array($json)) {
    $json = [];
}

$param = static function (string $key, mixed $default = '') use ($json): mixed {
    if (isset($_POST[$key]) && $_POST[$key] !== '') {
        return $_POST[$key];
    }
    if (isset($_GET[$key]) && $_GET[$key] !== '') {
        return $_GET[$key];
    }
    return $json[$key] ?? $default;
};

$tenantSlug = tenant_param();
if ($tenantSlug !== '') {
    $_GET['tenant'] = $tenantSlug;
}
$tenant = resolve_tenant_from_host();
if (!$tenant) {
    json_response(['ok' => false, 'error' => 'Shop not found'], 404);
}
$tenantId = (int) $tenant['id'];
$action = (string) $param('action', 'me');

function client_auth_public_user(?array $user): ?array
{
    if (!$user) {
        return null;
    }
    return [
        'id' => (int) $user['id'],
        'name' => (string) $user['name'],
        'email' => (string) ($user['email'] ?? ''),
        'phone' => (string) ($user['phone'] ?? ''),
    ];
}

try {
    if ($action === 'login') {
        $email = trim((string) $param('email', ''));
        $password = (string) $param('password', '');
        $user = client_find_by_email($tenantId, $email);
        if (!$user) {
            json_response(['ok' => false, 'error' => 'No account for that email. Create an account first.']);
        }
        if (user_is_owner($user)) {
            json_response(['ok' => false, 'error' => 'Owner accounts use the shop admin website, not the customer app.']);
        }
        if (!client_verify_password($user, $password)) {
            json_response(['ok' => false, 'error' => 'Incorrect password.']);
        }
        client_login_user($user);
        json_response(['ok' => true, 'user' => client_auth_public_user($user)]);
    }

    if ($action === 'register') {
        $name = trim((string) $param('name', ''));
        $email = trim((string) $param('email', ''));
        $phone = trim((string) $param('phone', ''));
        $password = (string) $param('password', '');
        $password2 = (string) $param('password2', $password);
        if ($password !== $password2) {
            json_response(['ok' => false, 'error' => 'Passwords do not match.']);
        }
        try {
            $user = client_register_account($tenantId, $name, $email, $password, $phone !== '' ? $phone : null);
        } catch (InvalidArgumentException $e) {
            json_response(['ok' => false, 'error' => $e->getMessage()]);
        } catch (RuntimeException $e) {
            json_response(['ok' => false, 'error' => $e->getMessage()]);
        }
        client_login_user($user);
        json_response(['ok' => true, 'user' => client_auth_public_user($user)]);
    }

    if ($action === 'logout') {
        client_logout();
        json_response(['ok' => true]);
    }

    $user = client_current_user();
    if (!$user || (int) $user['tenant_id'] !== $tenantId) {
        json_response(['ok' => false, 'error' => 'Not signed in', 'user' => null]);
    }

    if ($action === 'me') {
        json_response(['ok' => true, 'user' => client_auth_public_user($user)]);
    }

    if ($action === 'appointments') {
        $email = (string) ($user['email'] ?? '');
        $stmt = db()->prepare(
            'SELECT b.*, s.name AS service_name, sb.name AS staff_name
             FROM bookings b
             LEFT JOIN services s ON s.id = b.service_id
             LEFT JOIN staff_barbers sb ON sb.id = b.staff_id
             WHERE b.tenant_id = ?
               AND (b.user_id = ? OR (b.customer_email IS NOT NULL AND b.customer_email = ?))
             ORDER BY b.starts_at DESC
             LIMIT 50'
        );
        $stmt->execute([$tenantId, (int) $user['id'], $email]);
        $rows = [];
        foreach ($stmt->fetchAll() as $b) {
            $rows[] = [
                'id' => (int) $b['id'],
                'service_id' => (int) ($b['service_id'] ?? 0),
                'staff_id' => (int) ($b['staff_id'] ?? 0),
                'service_name' => (string) ($b['service_name'] ?? ''),
                'staff_name' => (string) ($b['staff_name'] ?? ''),
                'starts_at' => (string) $b['starts_at'],
                'ends_at' => (string) ($b['ends_at'] ?? ''),
                'status' => (string) $b['status'],
                'payment_status' => (string) ($b['payment_status'] ?? ''),
            ];
        }
        json_response(['ok' => true, 'user' => client_auth_public_user($user), 'appointments' => $rows]);
    }

    if ($action === 'delete') {
        if (user_is_owner($user)) {
            json_response(['ok' => false, 'error' => 'Owner accounts cannot be deleted from the customer app.']);
        }
        $uid = (int) $user['id'];
        $email = (string) ($user['email'] ?? '');
        db()->prepare(
            "UPDATE bookings
             SET user_id = NULL,
                 customer_name = 'Deleted account',
                 customer_phone = NULL,
                 customer_email = NULL
             WHERE tenant_id = ? AND (user_id = ? OR customer_email = ?)"
        )->execute([$tenantId, $uid, $email]);
        db()->prepare('DELETE FROM users WHERE id = ? AND tenant_id = ? AND role = ?')
            ->execute([$uid, $tenantId, 'customer']);
        client_logout();
        json_response(['ok' => true, 'message' => 'Your account and personal data were deleted.']);
    }

    if ($action === 'cancel') {
        $bookingId = (int) $param('booking_id', 0);
        $stmt = db()->prepare(
            'SELECT * FROM bookings WHERE id = ? AND tenant_id = ? AND (user_id = ? OR customer_email = ?) LIMIT 1'
        );
        $stmt->execute([$bookingId, $tenantId, (int) $user['id'], (string) ($user['email'] ?? '')]);
        $booking = $stmt->fetch();
        if (!$booking) {
            json_response(['ok' => false, 'error' => 'Appointment not found.']);
        }
        if (in_array((string) $booking['status'], ['cancelled', 'completed'], true)) {
            json_response(['ok' => false, 'error' => 'This appointment can no longer be changed.']);
        }
        $policy = client_policy($tenantId);
        $check = client_policy_check($tenantId, (string) $booking['starts_at']);
        if (empty($policy['allow_cancel'])) {
            json_response(['ok' => false, 'error' => 'Online cancel is disabled. Please call the shop.']);
        }
        if (empty($check['allowed'])) {
            json_response(['ok' => false, 'error' => (string) ($check['message'] ?? 'Cannot cancel online.')]);
        }
        $note = !empty($check['fee_applies'])
            ? trim((string) ($booking['notes'] ?? '') . "\n[App cancel] Fee may apply: $" . number_format((float) ($check['cancel_fee'] ?? 0), 2))
            : trim((string) ($booking['notes'] ?? '') . "\n[App cancel] Free (outside notice window)");
        db()->prepare('UPDATE bookings SET status = ?, notes = ? WHERE id = ? AND tenant_id = ?')
            ->execute(['cancelled', $note, $bookingId, $tenantId]);
        if (function_exists('reminder_cancel_pending')) {
            reminder_cancel_pending($bookingId);
        }
        json_response([
            'ok' => true,
            'message' => !empty($check['fee_applies']) ? 'Cancelled. ' . ($check['message'] ?? '') : 'Appointment cancelled.',
            'fee_applies' => (bool) ($check['fee_applies'] ?? false),
        ]);
    }

    json_response(['ok' => false, 'error' => 'Unknown action']);
} catch (Throwable $e) {
    json_response(['ok' => false, 'error' => $e->getMessage()]);
}
