<?php
require __DIR__ . '/bootstrap.php';

use App\Core\Auth;
use App\Core\Csrf;
use App\Core\Database;
use App\Core\Response;
use App\Services\UploadService;

$user = Auth::requireUser();
$input = request_input();
$action = $input['action'] ?? '';


function pyrk_self_normalize_member_date(?string $value): ?string
{
    $value = trim((string)$value);
    if ($value === '') return null;
    if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) return $value;
    if (preg_match('/^(\d{2})\/(\d{2})\/(\d{4})$/', $value, $m)) {
        $iso = $m[3] . '-' . $m[2] . '-' . $m[1];
        return strtotime($iso) ? $iso : null;
    }
    $time = strtotime($value);
    return $time ? date('Y-m-d', $time) : null;
}

function pyrk_self_person_name_from_input(array $input, array $fallbackUser): array
{
    $first = trim((string)($input['first_name'] ?? ''));
    $last = trim((string)($input['last_name'] ?? ''));
    $full = trim((string)($input['full_name'] ?? ''));
    if ($full === '') {
        $full = trim($first . ' ' . $last);
    }
    if ($full === '') {
        $full = trim((string)($fallbackUser['full_name'] ?? ''));
    }
    if ($first === '' || $last === '') {
        $parts = preg_split('/\s+/', $full, 2);
        if ($first === '') $first = (string)($parts[0] ?? '');
        if ($last === '') $last = (string)($parts[1] ?? '');
    }
    if ($full === '') {
        Response::error('Full name is required.');
    }
    return ['first_name' => $first, 'last_name' => $last, 'full_name' => $full];
}

function pyrk_self_avatar_from_request(): string
{
    if (empty($_FILES['profile_photo']) || (int)($_FILES['profile_photo']['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE) {
        return '';
    }
    return (new UploadService())->storeAvatar($_FILES['profile_photo']);
}

function pyrk_self_profile_edit_allowed(PDO $pdo, int $userId): bool
{
    try {
        $stmt = $pdo->prepare('SELECT can_edit_own_profile FROM users WHERE id = ? LIMIT 1');
        $stmt->execute([$userId]);
        $value = $stmt->fetchColumn();
        return $value === false ? false : (int)$value === 1;
    } catch (Throwable) {
        // Backward-compatible during deployment: migration 046 should be imported first.
        return true;
    }
}


if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'update_profile') {
    Csrf::validateFromRequest();

    $pdo = Database::connection();
    $userId = (int)$user['id'];

    if (!pyrk_self_profile_edit_allowed($pdo, $userId)) {
        Response::error('Profile editing has been disabled for your account by an administrator.', 403);
    }

    $profileCheck = $pdo->prepare('SELECT u.id, u.full_name, u.email, u.mobile, r.name AS role_name, mp.user_id AS has_member_profile FROM users u JOIN roles r ON r.id = u.role_id LEFT JOIN member_profiles mp ON mp.user_id = u.id WHERE u.id = ? LIMIT 1');
    $profileCheck->execute([$userId]);
    $current = $profileCheck->fetch(PDO::FETCH_ASSOC);
    if (!$current) Response::error('Account not found.', 404);
    if (($current['role_name'] ?? '') !== 'member' && empty($current['has_member_profile'])) {
        Response::error('Profile editing is available for member accounts only.', 403);
    }

    $person = pyrk_self_person_name_from_input($input, $current);
    $email = strtolower(trim((string)($input['email'] ?? $current['email'] ?? '')));
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) Response::error('Enter a valid email address.');

    $mobile = trim((string)($input['mobile'] ?? ''));
    $gender = trim((string)($input['gender'] ?? ''));
    $allowedGender = ['', 'female', 'male', 'other', 'prefer_not_to_say'];
    if (!in_array($gender, $allowedGender, true)) $gender = '';

    $photoConsent = !empty($input['photo_consent']) ? 1 : 0;
    $avatar = '';
    try {
        $avatar = pyrk_self_avatar_from_request();
    } catch (Throwable $e) {
        Response::error($e->getMessage());
    }

    $beforeStmt = $pdo->prepare('SELECT u.id, u.full_name, u.email, u.mobile, u.profile_photo_path, mp.date_of_birth, mp.gender, mp.emergency_contact_name, mp.emergency_contact_mobile, mp.medical_conditions, mp.photo_consent FROM users u LEFT JOIN member_profiles mp ON mp.user_id = u.id WHERE u.id = ? LIMIT 1');
    $beforeStmt->execute([$userId]);
    $before = $beforeStmt->fetch(PDO::FETCH_ASSOC) ?: [];

    $pdo->beginTransaction();
    try {
        $pdo->prepare('UPDATE users SET full_name = ?, email = ?, mobile = ?, updated_at = NOW() WHERE id = ?')
            ->execute([$person['full_name'], $email, $mobile, $userId]);
        if ($avatar !== '') {
            $pdo->prepare('UPDATE users SET profile_photo_path = ?, updated_at = NOW() WHERE id = ?')->execute([$avatar, $userId]);
        }

        $profile = $pdo->prepare('INSERT INTO member_profiles (user_id, date_of_birth, gender, emergency_contact_name, emergency_contact_mobile, medical_conditions, photo_consent, total_walks, total_kilometers, loyalty_points, created_at, updated_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, 0, 0.00, 0, NOW(), NOW())
            ON DUPLICATE KEY UPDATE date_of_birth = VALUES(date_of_birth), gender = VALUES(gender), emergency_contact_name = VALUES(emergency_contact_name), emergency_contact_mobile = VALUES(emergency_contact_mobile), medical_conditions = VALUES(medical_conditions), photo_consent = VALUES(photo_consent), updated_at = NOW()');
        $profile->execute([
            $userId,
            pyrk_self_normalize_member_date($input['date_of_birth'] ?? ''),
            $gender !== '' ? $gender : null,
            trim((string)($input['emergency_contact_name'] ?? '')),
            trim((string)($input['emergency_contact_mobile'] ?? '')),
            trim((string)($input['medical_conditions'] ?? '')),
            $photoConsent,
        ]);

        \App\Core\Security::audit($userId, 'member_self_profile_updated', 'users', $userId, ['self_service' => true], $before);
        $pdo->commit();
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        if (str_contains($e->getMessage(), 'Duplicate')) Response::error('This email address is already used by another account.');
        Response::error('Could not update your profile: ' . $e->getMessage(), 500);
    }

    Response::ok(['profile_photo_path' => $avatar ?: null], 'Profile updated successfully.');
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && $action === 'change_password') {
    Csrf::validateFromRequest();

    $currentPassword = (string)($input['current_password'] ?? '');
    $newPassword = (string)($input['new_password'] ?? '');
    $confirmPassword = (string)($input['confirm_password'] ?? '');

    if ($currentPassword === '' || $newPassword === '' || $confirmPassword === '') {
        Response::error('Please fill current password, new password, and confirmation.');
    }

    if ($newPassword !== $confirmPassword) {
        Response::error('New password and confirmation do not match.');
    }

    if (strlen($newPassword) < 8) {
        Response::error('New password must be at least 8 characters.');
    }

    if (!preg_match('/[A-Za-z]/', $newPassword) || !preg_match('/\d/', $newPassword)) {
        Response::error('New password must contain at least one letter and one number.');
    }

    if ($newPassword === $currentPassword) {
        Response::error('New password must be different from the current password.');
    }

    $pdo = Database::connection();
    $stmt = $pdo->prepare('SELECT id, password_hash FROM users WHERE id = ? LIMIT 1');
    $stmt->execute([(int)$user['id']]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$row || !password_verify($currentPassword, (string)$row['password_hash'])) {
        Response::error('Current password is incorrect.', 403);
    }

    $hash = password_hash($newPassword, PASSWORD_DEFAULT);

    $columns = [];
    try {
        $existingColumns = $pdo->query('SHOW COLUMNS FROM users')->fetchAll(PDO::FETCH_COLUMN);
        $columns = is_array($existingColumns) ? $existingColumns : [];
    } catch (Throwable $e) {
        $columns = [];
    }

    if (in_array('failed_login_count', $columns, true) && in_array('locked_until', $columns, true)) {
        $update = $pdo->prepare('UPDATE users SET password_hash = ?, failed_login_count = 0, locked_until = NULL, updated_at = NOW() WHERE id = ?');
        $update->execute([$hash, (int)$user['id']]);
    } else {
        $update = $pdo->prepare('UPDATE users SET password_hash = ?, updated_at = NOW() WHERE id = ?');
        $update->execute([$hash, (int)$user['id']]);
    }

    Response::ok([], 'Password changed successfully.');
}

Response::error('Unsupported account action.', 404);
