<?php

declare(strict_types=1);

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
date_default_timezone_set('Asia/Tehran');

/*
|--------------------------------------------------------------------------
| تنظیمات
|--------------------------------------------------------------------------
| فقط رمز فعلی دیتابیس و کلید فعلی پیامک را جایگزین کن.
*/
$host = 'localhost';
$db   = 'pnartli1_doorkar';
$user = 'pnartli1_doorkar';
$pass = 'V[B5S(1gO,OIqPvz';

define('LIMO_API_URL', 'https://api.limosms.com/api/sendpatternmessage');
define('LIMO_API_KEY', '7a5d1b13-abe0-4117-b06b-a05a7289e214');
define('LIMO_PATTERN_ID', 2641);
define('OTP_EXPIRE_SECONDS', 120);

function safeLog(string $event, array $context = []): void
{
    $safeContext = [
        'action' => $context['action'] ?? null,
        'mobile' => $context['mobile'] ?? null,
        'user_id' => $context['user_id'] ?? null,
        'result' => $context['result'] ?? null
    ];

    $line = '[' . date('Y-m-d H:i:s') . '] ' .
        $event . ' => ' .
        json_encode(
            $safeContext,
            JSON_UNESCAPED_UNICODE |
            JSON_UNESCAPED_SLASHES
        ) . PHP_EOL;

    file_put_contents(
        __DIR__ . '/php_debug.log',
        $line,
        FILE_APPEND | LOCK_EX
    );
}

function responseJson(
    array $response,
    int $statusCode = 200
): void {
    http_response_code($statusCode);

    echo json_encode(
        $response,
        JSON_UNESCAPED_UNICODE |
        JSON_UNESCAPED_SLASHES |
        JSON_INVALID_UTF8_SUBSTITUTE
    );
    exit;
}

function readJsonInput(): array
{
    $rawInput = file_get_contents('php://input');

    if ($rawInput === false || trim($rawInput) === '') {
        responseJson([
            'success' => false,
            'message' => 'ورودی درخواست خالی است'
        ], 400);
    }

    $input = json_decode($rawInput, true);

    if (!is_array($input)) {
        responseJson([
            'success' => false,
            'message' => 'ورودی JSON معتبر نیست'
        ], 400);
    }

    return $input;
}

function cleanMobile($mobile): string
{
    return trim((string)$mobile);
}

function generateOtp(): string
{
    return str_pad(
        (string)random_int(1000, 9999),
        4,
        '0',
        STR_PAD_LEFT
    );
}

function issueApiToken(mysqli $conn, int $userId): string
{
    $plainToken = bin2hex(random_bytes(32));
    $tokenHash = hash('sha256', $plainToken);

    $statement = $conn->prepare(
        'UPDATE users
         SET api_token_hash = ?,
             api_token_updated_at = NOW()
         WHERE id = ?'
    );
    $statement->bind_param('si', $tokenHash, $userId);
    $statement->execute();

    return $plainToken;
}

function sendOtpWithLimo(string $mobile, string $otp): array
{
    $payload = json_encode([
        'OtpId' => LIMO_PATTERN_ID,
        'ReplaceToken' => [$otp],
        'MobileNumber' => $mobile
    ], JSON_UNESCAPED_UNICODE);

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, LIMO_API_URL);
    curl_setopt($curl, CURLOPT_TIMEOUT, 30);
    curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'ApiKey: ' . LIMO_API_KEY
    ]);

    $result = curl_exec($curl);
    $httpCode = (int)curl_getinfo($curl, CURLINFO_HTTP_CODE);
    $curlError = curl_error($curl);
    curl_close($curl);

    safeLog('LIMO_RESULT', [
        'mobile' => $mobile,
        'result' => $curlError !== ''
            ? 'curl_error'
            : 'http_' . $httpCode
    ]);

    if ($curlError !== '') {
        return [
            'success' => false,
            'message' => 'خطا در اتصال به پنل پیامکی'
        ];
    }

    $decoded = json_decode((string)$result, true);

    if (!is_array($decoded)) {
        return [
            'success' => false,
            'message' => 'پاسخ پنل پیامکی معتبر نیست'
        ];
    }

    $success = $decoded['Success']
        ?? $decoded['success']
        ?? false;

    $message = (string)(
        $decoded['Message']
        ?? $decoded['message']
        ?? 'بدون پیام'
    );

    $isSuccessful = $success === true ||
        $success === 1 ||
        $success === 'true';

    return [
        'success' => $isSuccessful,
        'message' => $message
    ];
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    responseJson([
        'success' => false,
        'message' => 'فقط درخواست POST مجاز است'
    ], 405);
}

$conn = new mysqli($host, $user, $pass, $db);

if ($conn->connect_error) {
    safeLog('DB_CONNECT_ERROR', ['result' => 'failed']);
    responseJson([
        'success' => false,
        'message' => 'اتصال به دیتابیس انجام نشد'
    ], 500);
}

$conn->set_charset('utf8mb4');

$input = readJsonInput();
$action = trim((string)($input['action'] ?? ''));

safeLog('REQUEST', [
    'action' => $action,
    'mobile' => $input['mobile'] ?? null,
    'result' => 'received'
]);

if ($action === 'check_user') {
    $mobile = cleanMobile($input['mobile'] ?? '');

    if ($mobile === '') {
        responseJson([
            'success' => false,
            'message' => 'شماره موبایل خالی است'
        ], 422);
    }

    $statement = $conn->prepare(
        'SELECT id, password_hash
         FROM users
         WHERE mobile_number = ?
         LIMIT 1'
    );
    $statement->bind_param('s', $mobile);
    $statement->execute();
    $result = $statement->get_result();

    if ($result->num_rows > 0) {
        $row = $result->fetch_assoc();

        responseJson([
            'success' => true,
            'exists' => true,
            'id' => (int)$row['id'],
            'has_password' => !empty($row['password_hash'])
        ]);
    }

    responseJson([
        'success' => true,
        'exists' => false
    ]);
}

elseif ($action === 'send_otp') {
    $mobile = cleanMobile($input['mobile'] ?? '');

    if ($mobile === '') {
        responseJson([
            'success' => false,
            'message' => 'شماره موبایل خالی است'
        ], 422);
    }

    $userCheck = $conn->prepare(
        'SELECT id
         FROM users
         WHERE mobile_number = ?
         LIMIT 1'
    );
    $userCheck->bind_param('s', $mobile);
    $userCheck->execute();

    if ($userCheck->get_result()->num_rows > 0) {
        responseJson([
            'success' => false,
            'message' => 'این شماره قبلاً ثبت شده است'
        ], 409);
    }

    $otpCheck = $conn->prepare(
        'SELECT id, expires_at, is_verified
         FROM otp_codes
         WHERE mobile_number = ?
         LIMIT 1'
    );
    $otpCheck->bind_param('s', $mobile);
    $otpCheck->execute();
    $otpResult = $otpCheck->get_result();

    if ($otpResult->num_rows > 0) {
        $otpRow = $otpResult->fetch_assoc();
        $expiresTimestamp = strtotime((string)$otpRow['expires_at']);
        $nowTimestamp = time();

        if (
            (int)$otpRow['is_verified'] === 0 &&
            $expiresTimestamp > $nowTimestamp
        ) {
            responseJson([
                'success' => true,
                'already_sent' => true,
                'message' => 'کد فعالسازی قبلاً ارسال شده است',
                'expires_in' => $expiresTimestamp - $nowTimestamp
            ]);
        }
    }

    $otp = generateOtp();
    $expiresAt = date(
        'Y-m-d H:i:s',
        time() + OTP_EXPIRE_SECONDS
    );

    $smsResult = sendOtpWithLimo($mobile, $otp);

    if (!$smsResult['success']) {
        responseJson([
            'success' => false,
            'message' => 'ارسال پیامک ناموفق بود: ' .
                $smsResult['message']
        ], 502);
    }

    $saveOtp = $conn->prepare(
        'INSERT INTO otp_codes (
            mobile_number,
            otp_code,
            expires_at,
            is_verified
        ) VALUES (?, ?, ?, 0)
        ON DUPLICATE KEY UPDATE
            otp_code = VALUES(otp_code),
            expires_at = VALUES(expires_at),
            is_verified = 0'
    );
    $saveOtp->bind_param('sss', $mobile, $otp, $expiresAt);

    if (!$saveOtp->execute()) {
        responseJson([
            'success' => false,
            'message' => 'ذخیره کد فعالسازی انجام نشد'
        ], 500);
    }

    responseJson([
        'success' => true,
        'already_sent' => false,
        'message' => 'کد فعالسازی ارسال شد',
        'expires_in' => OTP_EXPIRE_SECONDS
    ]);
}

elseif ($action === 'verify_otp') {
    $mobile = cleanMobile($input['mobile'] ?? '');
    $code = trim((string)($input['code'] ?? ''));

    if ($mobile === '' || $code === '') {
        responseJson([
            'success' => false,
            'message' => 'شماره موبایل یا کد خالی است'
        ], 422);
    }

    $statement = $conn->prepare(
        'SELECT id, otp_code, expires_at
         FROM otp_codes
         WHERE mobile_number = ?
         LIMIT 1'
    );
    $statement->bind_param('s', $mobile);
    $statement->execute();
    $result = $statement->get_result();

    if ($result->num_rows === 0) {
        responseJson([
            'success' => false,
            'message' => 'برای این شماره کدی ثبت نشده است'
        ], 404);
    }

    $row = $result->fetch_assoc();

    if (strtotime((string)$row['expires_at']) < time()) {
        responseJson([
            'success' => false,
            'message' => 'زمان کد فعالسازی تمام شده است'
        ], 410);
    }

    if (!hash_equals((string)$row['otp_code'], $code)) {
        responseJson([
            'success' => false,
            'message' => 'کد فعالسازی اشتباه است'
        ], 422);
    }

    $update = $conn->prepare(
        'UPDATE otp_codes
         SET is_verified = 1
         WHERE id = ?'
    );
    $otpId = (int)$row['id'];
    $update->bind_param('i', $otpId);
    $update->execute();

    responseJson([
        'success' => true,
        'message' => 'کد فعالسازی درست است'
    ]);
}

elseif ($action === 'complete_register') {
    $mobile = cleanMobile($input['mobile'] ?? '');
    $password = trim((string)($input['password'] ?? ''));
    $userType = trim((string)($input['user_type'] ?? ''));

    if ($mobile === '' || $password === '' || $userType === '') {
        responseJson([
            'success' => false,
            'message' => 'اطلاعات ثبت‌نام کامل نیست'
        ], 422);
    }

    if (strlen($password) < 6) {
        responseJson([
            'success' => false,
            'message' => 'کلمه عبور باید حداقل ۶ کاراکتر باشد'
        ], 422);
    }

    if (!in_array($userType, ['freelancer', 'employer'], true)) {
        responseJson([
            'success' => false,
            'message' => 'نوع کاربری معتبر نیست'
        ], 422);
    }

    $userCheck = $conn->prepare(
        'SELECT id
         FROM users
         WHERE mobile_number = ?
         LIMIT 1'
    );
    $userCheck->bind_param('s', $mobile);
    $userCheck->execute();

    if ($userCheck->get_result()->num_rows > 0) {
        responseJson([
            'success' => false,
            'message' => 'این شماره قبلاً ثبت شده است'
        ], 409);
    }

    $otpCheck = $conn->prepare(
        'SELECT id, is_verified, expires_at
         FROM otp_codes
         WHERE mobile_number = ?
         LIMIT 1'
    );
    $otpCheck->bind_param('s', $mobile);
    $otpCheck->execute();
    $otpResult = $otpCheck->get_result();

    if ($otpResult->num_rows === 0) {
        responseJson([
            'success' => false,
            'message' => 'ابتدا کد فعالسازی را تایید کن'
        ], 409);
    }

    $otpRow = $otpResult->fetch_assoc();

    if ((int)$otpRow['is_verified'] !== 1) {
        responseJson([
            'success' => false,
            'message' => 'کد فعالسازی هنوز تایید نشده است'
        ], 409);
    }

    if (strtotime((string)$otpRow['expires_at']) < time()) {
        responseJson([
            'success' => false,
            'message' => 'زمان کد فعالسازی تمام شده است'
        ], 410);
    }

    $passwordHash = password_hash(
        $password,
        PASSWORD_BCRYPT
    );

    $insert = $conn->prepare(
        'INSERT INTO users (
            mobile_number,
            password_hash,
            user_type
        ) VALUES (?, ?, ?)'
    );
    $insert->bind_param(
        'sss',
        $mobile,
        $passwordHash,
        $userType
    );

    if (!$insert->execute()) {
        responseJson([
            'success' => false,
            'message' => 'ثبت‌نام انجام نشد'
        ], 500);
    }

    $newUserId = (int)$insert->insert_id;
    $apiToken = issueApiToken($conn, $newUserId);

    $deleteOtp = $conn->prepare(
        'DELETE FROM otp_codes
         WHERE mobile_number = ?'
    );
    $deleteOtp->bind_param('s', $mobile);
    $deleteOtp->execute();

    responseJson([
        'success' => true,
        'message' => 'ثبت‌نام با موفقیت تکمیل شد',
        'id' => $newUserId,
        'user_type' => $userType,
        'api_token' => $apiToken
    ]);
}

elseif ($action === 'register_user') {
    $mobile = cleanMobile($input['mobile'] ?? '');
    $password = trim((string)($input['password'] ?? ''));

    if ($mobile === '' || $password === '') {
        responseJson([
            'success' => false,
            'message' => 'شماره موبایل و رمز عبور لازم است'
        ], 422);
    }

    $passwordHash = password_hash(
        $password,
        PASSWORD_BCRYPT
    );

    $statement = $conn->prepare(
        'INSERT INTO users (
            mobile_number,
            password_hash
        ) VALUES (?, ?)'
    );
    $statement->bind_param(
        'ss',
        $mobile,
        $passwordHash
    );

    if (!$statement->execute()) {
        responseJson([
            'success' => false,
            'message' => 'ثبت کاربر انجام نشد'
        ], 500);
    }

    $newUserId = (int)$statement->insert_id;
    $apiToken = issueApiToken($conn, $newUserId);

    responseJson([
        'success' => true,
        'id' => $newUserId,
        'api_token' => $apiToken
    ]);
}

elseif ($action === 'set_user_type') {
    $id = (int)($input['id'] ?? 0);
    $type = trim((string)($input['user_type'] ?? ''));

    if (
        $id <= 0 ||
        !in_array($type, ['freelancer', 'employer'], true)
    ) {
        responseJson([
            'success' => false,
            'message' => 'اطلاعات نوع کاربری معتبر نیست'
        ], 422);
    }

    $statement = $conn->prepare(
        'UPDATE users
         SET user_type = ?
         WHERE id = ?'
    );
    $statement->bind_param('si', $type, $id);

    if (!$statement->execute()) {
        responseJson([
            'success' => false,
            'message' => 'نوع کاربری ذخیره نشد'
        ], 500);
    }

    responseJson(['success' => true]);
}

elseif ($action === 'login_user') {
    $mobile = cleanMobile($input['mobile'] ?? '');
    $password = (string)($input['password'] ?? '');

    if ($mobile === '' || $password === '') {
        responseJson([
            'success' => false,
            'message' => 'شماره موبایل و رمز عبور لازم است'
        ], 422);
    }

    $statement = $conn->prepare(
        'SELECT id, password_hash, user_type
         FROM users
         WHERE mobile_number = ?
         LIMIT 1'
    );
    $statement->bind_param('s', $mobile);
    $statement->execute();
    $result = $statement->get_result();

    if ($result->num_rows === 0) {
        responseJson([
            'success' => false,
            'message' => 'کاربر پیدا نشد'
        ], 404);
    }

    $row = $result->fetch_assoc();

    if (
        empty($row['password_hash']) ||
        !password_verify($password, (string)$row['password_hash'])
    ) {
        responseJson([
            'success' => false,
            'message' => 'رمز عبور نادرست است'
        ], 401);
    }

    $userId = (int)$row['id'];
    $apiToken = issueApiToken($conn, $userId);

    responseJson([
        'success' => true,
        'id' => $userId,
        'user_type' => $row['user_type'],
        'api_token' => $apiToken
    ]);
}

else {
    responseJson([
        'success' => false,
        'message' => 'action معتبر نیست'
    ], 400);
}
