<?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');

/*
|--------------------------------------------------------------------------
| تنظیمات دیتابیس
|--------------------------------------------------------------------------
| رمز فعلی دیتابیس خودت را فقط در DB_PASS قرار بده.
*/
$DB_HOST = 'localhost';
$DB_NAME = 'pnartli1_doorkar';
$DB_USER = 'pnartli1_doorkar';
$DB_PASS = 'V[B5S(1gO,OIqPvz';

function responseJson(
    bool $success,
    string $message,
    array $data = [],
    int $statusCode = 200
): void {
    http_response_code($statusCode);

    $response = [
        'success' => $success,
        'message' => $message
    ];

    if (!empty($data)) {
        $response = array_merge($response, $data);
    }

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

function safeLog(string $event, array $context = []): void
{
    $safeContext = [
        'action' => $context['action'] ?? 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__ . '/profile_api.log',
        $line,
        FILE_APPEND | LOCK_EX
    );
}

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

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

    $input = json_decode($rawInput, true);

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

    return $input;
}

function cleanString($value): string
{
    return trim((string)$value);
}

function requirePositiveInt(
    array $input,
    string $key,
    string $message
): int {
    $value = (int)($input[$key] ?? 0);

    if ($value <= 0) {
        responseJson(false, $message, [], 422);
    }

    return $value;
}

function ensureUserExists(PDO $pdo, int $userId): void
{
    $statement = $pdo->prepare(
        'SELECT id FROM users WHERE id = ? LIMIT 1'
    );
    $statement->execute([$userId]);

    if (!$statement->fetchColumn()) {
        responseJson(false, 'کاربر پیدا نشد', [], 404);
    }
}

function ensureFreelancerUser(PDO $pdo, int $userId): void
{
    $statement = $pdo->prepare(
        'SELECT user_type
         FROM users
         WHERE id = ?
         LIMIT 1'
    );
    $statement->execute([$userId]);

    if ($statement->fetchColumn() !== 'freelancer') {
        responseJson(
            false,
            'ثبت نمونه‌کار فقط برای حساب فریلنسر فعال است',
            [],
            403
        );
    }
}

function ensureCityBelongsToProvince(
    PDO $pdo,
    int $provinceId,
    int $cityId
): void {
    $statement = $pdo->prepare(
        'SELECT id
         FROM cities
         WHERE id = ?
           AND province_id = ?
           AND is_active = 1
         LIMIT 1'
    );
    $statement->execute([$cityId, $provinceId]);

    if (!$statement->fetchColumn()) {
        responseJson(
            false,
            'شهر انتخاب‌شده متعلق به استان انتخاب‌شده نیست',
            [],
            422
        );
    }
}

function getNationalityCountryCode(
    PDO $pdo,
    int $nationalityId
): string {
    $statement = $pdo->prepare(
        'SELECT country_code
         FROM nationalities
         WHERE id = ?
           AND is_active = 1
         LIMIT 1'
    );
    $statement->execute([$nationalityId]);

    $countryCode = $statement->fetchColumn();

    if ($countryCode === false) {
        responseJson(false, 'ملیت انتخاب‌شده معتبر نیست', [], 422);
    }

    return (string)$countryCode;
}

function isValidDate(string $date): bool
{
    if ($date === '') {
        return false;
    }

    $dateObject = DateTime::createFromFormat('Y-m-d', $date);

    if ($dateObject === false) {
        return false;
    }

    $errors = DateTime::getLastErrors();

    if (
        is_array($errors) &&
        ($errors['warning_count'] > 0 || $errors['error_count'] > 0)
    ) {
        return false;
    }

    return $dateObject->format('Y-m-d') === $date;
}

function isFutureDate(string $date): bool
{
    return new DateTime($date) > new DateTime('today');
}

function isValidIranianNationalCode(string $nationalCode): bool
{
    if (!preg_match('/^\d{10}$/', $nationalCode)) {
        return false;
    }

    if (preg_match('/^(\d)\1{9}$/', $nationalCode)) {
        return false;
    }

    $checkDigit = (int)$nationalCode[9];
    $sum = 0;

    for ($index = 0; $index < 9; $index++) {
        $sum += ((int)$nationalCode[$index]) * (10 - $index);
    }

    $remainder = $sum % 11;

    return $remainder < 2
        ? $checkDigit === $remainder
        : $checkDigit === (11 - $remainder);
}

function normalizePhone(string $phone): string
{
    return str_replace([' ', '-', '(', ')'], '', $phone);
}


function getAuthorizationHeader(): string
{
    $header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';

    if ($header === '' && function_exists('getallheaders')) {
        $headers = getallheaders();
        $header = $headers['Authorization']
            ?? $headers['authorization']
            ?? '';
    }

    return trim((string)$header);
}

function requireAuthenticatedUser(PDO $pdo): int
{
    $authorization = getAuthorizationHeader();

    if (!preg_match('/^Bearer\s+([A-Fa-f0-9]{64})$/', $authorization, $matches)) {
        responseJson(
            false,
            'نشست ورود معتبر نیست؛ یک بار از حساب خارج شو و دوباره وارد شو',
            [],
            401
        );
    }

    $tokenHash = hash('sha256', $matches[1]);

    $statement = $pdo->prepare(
        'SELECT id
         FROM users
         WHERE api_token_hash = ?
         LIMIT 1'
    );
    $statement->execute([$tokenHash]);

    $userId = (int)($statement->fetchColumn() ?: 0);

    if ($userId <= 0) {
        responseJson(
            false,
            'نشست ورود منقضی شده است؛ دوباره وارد حساب شو',
            [],
            401
        );
    }

    return $userId;
}

function isMultipartRequest(): bool
{
    $contentType = $_SERVER['CONTENT_TYPE'] ?? '';
    return stripos($contentType, 'multipart/form-data') !== false;
}

function getBasePublicUrl(): string
{
    $isHttps = (
        (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
        (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https')
    );

    $scheme = $isHttps ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
    $scriptName = str_replace('\\', '/', $_SERVER['SCRIPT_NAME'] ?? '');
    $directory = rtrim(dirname($scriptName), '/.');

    return $scheme . '://' . $host . ($directory !== '' ? $directory : '');
}

function toPublicUrl(?string $relativePath): ?string
{
    $relativePath = trim((string)$relativePath);

    if ($relativePath === '') {
        return null;
    }

    if (preg_match('/^https?:\/\//i', $relativePath)) {
        return $relativePath;
    }

    return rtrim(getBasePublicUrl(), '/') . '/' . ltrim($relativePath, '/');
}

function ensureUploadDirectory(string $relativeDirectory): string
{
    $absoluteDirectory = __DIR__ . '/' . trim($relativeDirectory, '/');

    if (!is_dir($absoluteDirectory)) {
        if (!mkdir($absoluteDirectory, 0755, true) && !is_dir($absoluteDirectory)) {
            responseJson(false, 'ساخت پوشه آپلود انجام نشد', [], 500);
        }
    }

    return $absoluteDirectory;
}

function randomUploadName(string $extension): string
{
    return bin2hex(random_bytes(20)) . '.' . strtolower($extension);
}

function saveUploadedImage(
    string $fieldName,
    string $relativeDirectory,
    int $maxBytes = 5242880
): array {
    if (!isset($_FILES[$fieldName])) {
        responseJson(false, 'فایل تصویر ارسال نشده است', [], 422);
    }

    $file = $_FILES[$fieldName];

    if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
        responseJson(false, 'آپلود تصویر کامل نشد', [], 422);
    }

    $size = (int)($file['size'] ?? 0);

    if ($size <= 0 || $size > $maxBytes) {
        responseJson(false, 'حجم تصویر باید کمتر از ۵ مگابایت باشد', [], 422);
    }

    $temporaryPath = (string)($file['tmp_name'] ?? '');

    if (!is_uploaded_file($temporaryPath)) {
        responseJson(false, 'فایل تصویر معتبر نیست', [], 422);
    }

    $imageInfo = @getimagesize($temporaryPath);

    if ($imageInfo === false) {
        responseJson(false, 'فایل انتخاب‌شده تصویر معتبر نیست', [], 422);
    }

    $allowedMimes = [
        'image/jpeg' => 'jpg',
        'image/png' => 'png',
        'image/webp' => 'webp'
    ];

    $mime = (string)($imageInfo['mime'] ?? '');

    if (!isset($allowedMimes[$mime])) {
        responseJson(false, 'فرمت تصویر باید JPG، PNG یا WEBP باشد', [], 422);
    }

    $absoluteDirectory = ensureUploadDirectory($relativeDirectory);
    $fileName = randomUploadName($allowedMimes[$mime]);
    $absolutePath = $absoluteDirectory . '/' . $fileName;

    if (!move_uploaded_file($temporaryPath, $absolutePath)) {
        responseJson(false, 'ذخیره تصویر روی سرور انجام نشد', [], 500);
    }

    return [
        'relative_path' => trim($relativeDirectory, '/') . '/' . $fileName,
        'original_name' => basename((string)($file['name'] ?? $fileName)),
        'mime_type' => $mime,
        'size_bytes' => $size
    ];
}

function saveUploadedAttachment(
    string $fieldName,
    string $relativeDirectory,
    int $maxBytes = 26214400
): ?array {
    if (!isset($_FILES[$fieldName])) {
        return null;
    }

    $file = $_FILES[$fieldName];
    $error = (int)($file['error'] ?? UPLOAD_ERR_NO_FILE);

    if ($error === UPLOAD_ERR_NO_FILE) {
        return null;
    }

    if ($error !== UPLOAD_ERR_OK) {
        responseJson(false, 'آپلود فایل دانلودی کامل نشد', [], 422);
    }

    $size = (int)($file['size'] ?? 0);

    if ($size <= 0 || $size > $maxBytes) {
        responseJson(false, 'حجم فایل دانلودی باید کمتر از ۲۵ مگابایت باشد', [], 422);
    }

    $originalName = basename((string)($file['name'] ?? 'portfolio_file'));
    $extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));

    $allowedExtensions = [
        'pdf', 'zip', 'rar', 'doc', 'docx',
        'xls', 'xlsx', 'ppt', 'pptx', 'txt'
    ];

    if (!in_array($extension, $allowedExtensions, true)) {
        responseJson(
            false,
            'فرمت فایل دانلودی مجاز نیست',
            [],
            422
        );
    }

    $temporaryPath = (string)($file['tmp_name'] ?? '');

    if (!is_uploaded_file($temporaryPath)) {
        responseJson(false, 'فایل دانلودی معتبر نیست', [], 422);
    }

    $blockedExtensions = [
        'php', 'phtml', 'phar', 'cgi', 'pl', 'py',
        'sh', 'exe', 'com', 'bat', 'cmd', 'js', 'html', 'htm'
    ];

    if (in_array($extension, $blockedExtensions, true)) {
        responseJson(false, 'این نوع فایل قابل آپلود نیست', [], 422);
    }

    $absoluteDirectory = ensureUploadDirectory($relativeDirectory);
    $fileName = randomUploadName($extension);
    $absolutePath = $absoluteDirectory . '/' . $fileName;

    if (!move_uploaded_file($temporaryPath, $absolutePath)) {
        responseJson(false, 'ذخیره فایل دانلودی انجام نشد', [], 500);
    }

    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mimeType = (string)$finfo->file($absolutePath);

    return [
        'relative_path' => trim($relativeDirectory, '/') . '/' . $fileName,
        'original_name' => mb_substr($originalName, 0, 180),
        'mime_type' => $mimeType !== '' ? $mimeType : 'application/octet-stream',
        'size_bytes' => $size
    ];
}

function deleteRelativeUpload(?string $relativePath): void
{
    $relativePath = trim((string)$relativePath);

    if ($relativePath === '' || strpos($relativePath, 'uploads/') !== 0) {
        return;
    }

    $absolutePath = realpath(__DIR__) . '/' . ltrim($relativePath, '/');
    $uploadsRoot = realpath(__DIR__ . '/uploads');

    if ($uploadsRoot === false) {
        return;
    }

    $directory = realpath(dirname($absolutePath));

    if (
        $directory !== false &&
        strpos($directory, $uploadsRoot) === 0 &&
        is_file($absolutePath)
    ) {
        @unlink($absolutePath);
    }
}

function normalizeHttpUrl(string $url): string
{
    $url = trim($url);

    if ($url === '') {
        return '';
    }

    if (!filter_var($url, FILTER_VALIDATE_URL)) {
        responseJson(false, 'لینک نمونه‌کار معتبر نیست', [], 422);
    }

    $scheme = strtolower((string)parse_url($url, PHP_URL_SCHEME));

    if (!in_array($scheme, ['http', 'https'], true)) {
        responseJson(false, 'لینک باید با http یا https شروع شود', [], 422);
    }

    return $url;
}

try {
    $pdo = new PDO(
        'mysql:host=' . $DB_HOST .
        ';dbname=' . $DB_NAME .
        ';charset=utf8mb4',
        $DB_USER,
        $DB_PASS,
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false
        ]
    );
} catch (PDOException $exception) {
    safeLog('DATABASE_CONNECTION_FAILED', ['result' => 'failed']);
    responseJson(false, 'اتصال به دیتابیس انجام نشد', [], 500);
}

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

$input = isMultipartRequest() ? $_POST : readJsonInput();
$action = cleanString($input['action'] ?? '');

if ($action === '') {
    responseJson(false, 'action ارسال نشده است', [], 400);
}

$authenticatedUserId = 0;

$publicReadActions = [
    'get_profile',
    'get_portfolio',
    'get_experience_education'
];

if ($action !== 'health_check') {
    $authenticatedUserId = requireAuthenticatedUser($pdo);

    if (in_array($action, $publicReadActions, true)) {
        $requestedUserId = (int)(
            $input['target_user_id']
            ?? $input['profile_user_id']
            ?? $input['freelancer_user_id']
            ?? $input['user_id']
            ?? 0
        );

        if ($requestedUserId > 0) {
            $input['user_id'] = $requestedUserId;
        } else {
            $input['user_id'] = $authenticatedUserId;
        }
    } else {
        $input['user_id'] = $authenticatedUserId;
    }
}
safeLog('REQUEST_RECEIVED', [
    'action' => $action,
    'user_id' => $authenticatedUserId,
    'result' => 'received'
]);

if ($action === 'health_check') {
    responseJson(true, 'API فعال است', [
        'server_time' => date('Y-m-d H:i:s')
    ]);
}

elseif ($action === 'get_form_options') {
    $nationalities = $pdo->query(
        'SELECT id, name_fa, country_code
         FROM nationalities
         WHERE is_active = 1
         ORDER BY
            CASE WHEN country_code = "IR" THEN 0 ELSE 1 END,
            name_fa'
    )->fetchAll();

    $provinces = $pdo->query(
        'SELECT id, name_fa
         FROM provinces
         WHERE is_active = 1
         ORDER BY name_fa'
    )->fetchAll();

    $skills = $pdo->query(
        'SELECT id, name_fa
         FROM skills
         WHERE is_active = 1
         ORDER BY name_fa
         LIMIT 500'
    )->fetchAll();

    responseJson(true, 'اطلاعات فرم دریافت شد', [
        'nationalities' => $nationalities,
        'provinces' => $provinces,
        'skills' => $skills
    ]);
}

elseif ($action === 'get_cities') {
    $provinceId = requirePositiveInt(
        $input,
        'province_id',
        'شناسه استان معتبر نیست'
    );

    $query = cleanString($input['query'] ?? '');

    $statement = $pdo->prepare(
        'SELECT id, province_id, name_fa
         FROM cities
         WHERE province_id = ?
           AND is_active = 1
           AND name_fa LIKE ?
         ORDER BY name_fa
         LIMIT 200'
    );
    $statement->execute([$provinceId, '%' . $query . '%']);

    responseJson(true, 'شهرها دریافت شدند', [
        'cities' => $statement->fetchAll()
    ]);
}

elseif ($action === 'search_skills') {
    $query = cleanString($input['query'] ?? '');

    $statement = $pdo->prepare(
        'SELECT id, name_fa
         FROM skills
         WHERE is_active = 1
           AND name_fa LIKE ?
         ORDER BY name_fa
         LIMIT 100'
    );
    $statement->execute(['%' . $query . '%']);

    responseJson(true, 'مهارت‌ها دریافت شدند', [
        'skills' => $statement->fetchAll()
    ]);
}

elseif ($action === 'get_profile') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    ensureUserExists($pdo, $userId);

    $profileStatement = $pdo->prepare(
        'SELECT
            user_profiles.*,
            provinces.name_fa AS province_name,
            cities.name_fa AS city_name,
            nationalities.name_fa AS nationality_name
         FROM user_profiles
         LEFT JOIN provinces
            ON provinces.id = user_profiles.province_id
         LEFT JOIN cities
            ON cities.id = user_profiles.city_id
         LEFT JOIN nationalities
            ON nationalities.id = user_profiles.nationality_id
         WHERE user_profiles.user_id = ?
         LIMIT 1'
    );
    $profileStatement->execute([$userId]);
    $profile = $profileStatement->fetch() ?: null;

    if (is_array($profile)) {
        $profile['profile_image_url'] = toPublicUrl(
            $profile['profile_image_path'] ?? null
        );
    }

    $resumeStatement = $pdo->prepare(
        'SELECT
            id,
            user_id,
            professional_title,
            resume_text,
            resume_completed,
            created_at,
            updated_at
         FROM user_resumes
         WHERE user_id = ?
         LIMIT 1'
    );
    $resumeStatement->execute([$userId]);
    $resume = $resumeStatement->fetch() ?: null;

    $skillsStatement = $pdo->prepare(
        'SELECT
            skills.id,
            skills.name_fa,
            user_skills.sort_order
         FROM user_skills
         INNER JOIN skills
            ON skills.id = user_skills.skill_id
         WHERE user_skills.user_id = ?
           AND skills.is_active = 1
         ORDER BY user_skills.sort_order, skills.name_fa'
    );
    $skillsStatement->execute([$userId]);

    responseJson(true, 'اطلاعات پروفایل دریافت شد', [
        'profile' => $profile,
        'resume' => $resume,
        'selected_skills' => $skillsStatement->fetchAll()
    ]);
}

elseif ($action === 'save_identity') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    ensureUserExists($pdo, $userId);

    $currentStatusStatement = $pdo->prepare(
        'SELECT review_status
         FROM user_profiles
         WHERE user_id = ?
         LIMIT 1'
    );
    $currentStatusStatement->execute([$userId]);
    $currentStatus = $currentStatusStatement->fetchColumn();

    if (in_array($currentStatus, ['pending', 'approved'], true)) {
        $message = $currentStatus === 'approved'
            ? 'مشخصات هویتی تأیید شده و قابل ویرایش نیست'
            : 'مشخصات هویتی در حال بررسی است و قابل ویرایش نیست';

        responseJson(false, $message, [
            'review_status' => $currentStatus,
            'identity_locked' => true
        ], 409);
    }

    $profileKind = cleanString($input['profile_kind'] ?? '');

    if (!in_array($profileKind, ['individual', 'legal'], true)) {
        responseJson(false, 'نوع پروفایل معتبر نیست', [], 422);
    }

    $provinceId = requirePositiveInt(
        $input,
        'province_id',
        'استان را انتخاب کن'
    );

    $cityId = requirePositiveInt(
        $input,
        'city_id',
        'شهر را انتخاب کن'
    );

    ensureCityBelongsToProvince($pdo, $provinceId, $cityId);

    $email = cleanString($input['email'] ?? '');
    $address = cleanString($input['address'] ?? '');

    if (
        $email !== '' &&
        filter_var($email, FILTER_VALIDATE_EMAIL) === false
    ) {
        responseJson(false, 'آدرس ایمیل معتبر نیست', [], 422);
    }

    $fullName = '';
    $gender = '';
    $fatherName = '';
    $birthDate = '';
    $nationalCode = '';
    $nationalityId = 0;

    $companyRegisteredName = '';
    $registrationNumber = '';
    $companyNationalId = '';
    $economicCode = '';
    $contactPhone = '';
    $postalCode = '';

    if ($profileKind === 'individual') {
        $fullName = cleanString($input['full_name'] ?? '');
        $gender = cleanString($input['gender'] ?? '');
        $fatherName = cleanString($input['father_name'] ?? '');
        $birthDate = cleanString($input['birth_date'] ?? '');
        $nationalCode = cleanString($input['national_code'] ?? '');
        $nationalityId = requirePositiveInt(
            $input,
            'nationality_id',
            'ملیت را انتخاب کن'
        );

        if ($fullName === '') {
            responseJson(false, 'نام کامل را وارد کن', [], 422);
        }

        if (!in_array($gender, ['male', 'female', 'other'], true)) {
            responseJson(false, 'جنسیت را انتخاب کن', [], 422);
        }

        if ($fatherName === '') {
            responseJson(false, 'نام پدر را وارد کن', [], 422);
        }

        if (!isValidDate($birthDate) || isFutureDate($birthDate)) {
            responseJson(false, 'تاریخ تولد معتبر نیست', [], 422);
        }

        if ($nationalCode === '') {
            responseJson(
                false,
                'کد ملی یا شناسه هویتی را وارد کن',
                [],
                422
            );
        }

        $countryCode = getNationalityCountryCode(
            $pdo,
            $nationalityId
        );

        if (
            $countryCode === 'IR' &&
            !isValidIranianNationalCode($nationalCode)
        ) {
            responseJson(false, 'کد ملی ایرانی معتبر نیست', [], 422);
        }

        if (
            $countryCode !== 'IR' &&
            (strlen($nationalCode) < 5 || strlen($nationalCode) > 30)
        ) {
            responseJson(
                false,
                'شناسه هویتی باید بین ۵ تا ۳۰ کاراکتر باشد',
                [],
                422
            );
        }
    }

    if ($profileKind === 'legal') {
        $companyRegisteredName = cleanString(
            $input['company_registered_name'] ?? ''
        );
        $registrationNumber = cleanString(
            $input['registration_number'] ?? ''
        );
        $companyNationalId = cleanString(
            $input['company_national_id'] ?? ''
        );
        $economicCode = cleanString(
            $input['economic_code'] ?? ''
        );
        $contactPhone = normalizePhone(
            cleanString($input['contact_phone'] ?? '')
        );
        $postalCode = cleanString($input['postal_code'] ?? '');

        if ($companyRegisteredName === '') {
            responseJson(false, 'نام ثبتی شرکت را وارد کن', [], 422);
        }

        if ($registrationNumber === '') {
            responseJson(false, 'شماره ثبت را وارد کن', [], 422);
        }

        if ($companyNationalId === '') {
            responseJson(false, 'شناسه ملی شرکت را وارد کن', [], 422);
        }

        if ($economicCode === '') {
            responseJson(false, 'کد اقتصادی را وارد کن', [], 422);
        }

        if (!preg_match('/^\+?[0-9]{8,15}$/', $contactPhone)) {
            responseJson(false, 'شماره تماس معتبر نیست', [], 422);
        }

        if (!preg_match('/^[0-9]{10}$/', $postalCode)) {
            responseJson(false, 'کد پستی باید ۱۰ رقم باشد', [], 422);
        }

        if ($address === '') {
            responseJson(false, 'آدرس شرکت را وارد کن', [], 422);
        }
    }

    $saveStatement = $pdo->prepare(
        'INSERT INTO user_profiles (
            user_id,
            profile_kind,
            email,
            province_id,
            city_id,
            address,
            full_name,
            gender,
            father_name,
            birth_date,
            national_code,
            nationality_id,
            company_registered_name,
            registration_number,
            company_national_id,
            economic_code,
            contact_phone,
            postal_code,
            profile_completed,
            review_status,
            submitted_at,
            reviewed_at,
            review_note
        ) VALUES (
            :user_id,
            :profile_kind,
            NULLIF(:email, ""),
            :province_id,
            :city_id,
            NULLIF(:address, ""),
            NULLIF(:full_name, ""),
            NULLIF(:gender, ""),
            NULLIF(:father_name, ""),
            NULLIF(:birth_date, ""),
            NULLIF(:national_code, ""),
            NULLIF(:nationality_id, 0),
            NULLIF(:company_registered_name, ""),
            NULLIF(:registration_number, ""),
            NULLIF(:company_national_id, ""),
            NULLIF(:economic_code, ""),
            NULLIF(:contact_phone, ""),
            NULLIF(:postal_code, ""),
            1,
            "pending",
            NOW(),
            NULL,
            NULL
        )
        ON DUPLICATE KEY UPDATE
            profile_kind = VALUES(profile_kind),
            email = VALUES(email),
            province_id = VALUES(province_id),
            city_id = VALUES(city_id),
            address = VALUES(address),
            full_name = VALUES(full_name),
            gender = VALUES(gender),
            father_name = VALUES(father_name),
            birth_date = VALUES(birth_date),
            national_code = VALUES(national_code),
            nationality_id = VALUES(nationality_id),
            company_registered_name = VALUES(company_registered_name),
            registration_number = VALUES(registration_number),
            company_national_id = VALUES(company_national_id),
            economic_code = VALUES(economic_code),
            contact_phone = VALUES(contact_phone),
            postal_code = VALUES(postal_code),
            profile_completed = 1,
            review_status = "pending",
            submitted_at = NOW(),
            reviewed_at = NULL,
            review_note = NULL'
    );

    try {
        $saveStatement->execute([
            'user_id' => $userId,
            'profile_kind' => $profileKind,
            'email' => $email,
            'province_id' => $provinceId,
            'city_id' => $cityId,
            'address' => $address,
            'full_name' => $fullName,
            'gender' => $gender,
            'father_name' => $fatherName,
            'birth_date' => $birthDate,
            'national_code' => $nationalCode,
            'nationality_id' => $nationalityId,
            'company_registered_name' => $companyRegisteredName,
            'registration_number' => $registrationNumber,
            'company_national_id' => $companyNationalId,
            'economic_code' => $economicCode,
            'contact_phone' => $contactPhone,
            'postal_code' => $postalCode
        ]);
    } catch (PDOException $exception) {
        if ($exception->getCode() === '23000') {
            responseJson(
                false,
                'کد ملی یا شناسه ملی قبلاً ثبت شده است',
                [],
                409
            );
        }

        safeLog('SAVE_IDENTITY_FAILED', [
            'action' => $action,
            'user_id' => $userId,
            'result' => 'failed'
        ]);

        responseJson(
            false,
            'ذخیره مشخصات کاربری انجام نشد',
            [],
            500
        );
    }

    responseJson(true, 'مشخصات ثبت شد و در حال بررسی است', [
        'profile_kind' => $profileKind,
        'review_status' => 'pending',
        'identity_locked' => true,
        'next_step' => 'resume'
    ]);
}

elseif ($action === 'save_resume') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    ensureUserExists($pdo, $userId);

    $identityStatusStatement = $pdo->prepare(
        'SELECT review_status
         FROM user_profiles
         WHERE user_id = ?
         LIMIT 1'
    );
    $identityStatusStatement->execute([$userId]);
    $identityStatus = $identityStatusStatement->fetchColumn();

    if (!in_array($identityStatus, ['pending', 'approved'], true)) {
        responseJson(
            false,
            'ابتدا مشخصات کاربری را ثبت و برای بررسی ارسال کن',
            [],
            409
        );
    }

    $professionalTitle = cleanString(
        $input['professional_title'] ?? ''
    );
    $resumeText = cleanString($input['resume_text'] ?? '');
    $skillIdsInput = $input['skill_ids'] ?? [];

    if (
        mb_strlen($professionalTitle) < 3 ||
        mb_strlen($professionalTitle) > 150
    ) {
        responseJson(
            false,
            'عنوان حرفه‌ای باید بین ۳ تا ۱۵۰ کاراکتر باشد',
            [],
            422
        );
    }

    if (mb_strlen($resumeText) < 30) {
        responseJson(
            false,
            'متن رزومه باید حداقل ۳۰ کاراکتر باشد',
            [],
            422
        );
    }

    if (!is_array($skillIdsInput)) {
        responseJson(false, 'فهرست مهارت‌ها معتبر نیست', [], 422);
    }

    $skillIds = [];

    foreach ($skillIdsInput as $skillId) {
        $skillId = (int)$skillId;
        if ($skillId > 0) {
            $skillIds[] = $skillId;
        }
    }

    $skillIds = array_values(array_unique($skillIds));

    if (count($skillIds) === 0) {
        responseJson(false, 'حداقل یک مهارت انتخاب کن', [], 422);
    }

    if (count($skillIds) > 30) {
        responseJson(false, 'حداکثر ۳۰ مهارت قابل انتخاب است', [], 422);
    }

    $placeholders = implode(
        ',',
        array_fill(0, count($skillIds), '?')
    );

    $skillCheckStatement = $pdo->prepare(
        'SELECT id
         FROM skills
         WHERE is_active = 1
           AND id IN (' . $placeholders . ')'
    );
    $skillCheckStatement->execute($skillIds);

    $validSkillIds = array_map(
        'intval',
        $skillCheckStatement->fetchAll(PDO::FETCH_COLUMN)
    );

    sort($validSkillIds);
    $sortedSubmittedIds = $skillIds;
    sort($sortedSubmittedIds);

    if ($validSkillIds !== $sortedSubmittedIds) {
        responseJson(
            false,
            'یک یا چند مهارت انتخاب‌شده معتبر نیست',
            [],
            422
        );
    }

    try {
        $pdo->beginTransaction();

        $resumeStatement = $pdo->prepare(
            'INSERT INTO user_resumes (
                user_id,
                professional_title,
                resume_text,
                resume_completed
            ) VALUES (?, ?, ?, 1)
            ON DUPLICATE KEY UPDATE
                professional_title = VALUES(professional_title),
                resume_text = VALUES(resume_text),
                resume_completed = 1'
        );
        $resumeStatement->execute([
            $userId,
            $professionalTitle,
            $resumeText
        ]);

        $deleteSkillsStatement = $pdo->prepare(
            'DELETE FROM user_skills WHERE user_id = ?'
        );
        $deleteSkillsStatement->execute([$userId]);

        $insertSkillStatement = $pdo->prepare(
            'INSERT INTO user_skills (
                user_id,
                skill_id,
                sort_order
            ) VALUES (?, ?, ?)'
        );

        foreach ($skillIds as $sortOrder => $skillId) {
            $insertSkillStatement->execute([
                $userId,
                $skillId,
                $sortOrder
            ]);
        }

        $pdo->commit();
    } catch (Throwable $throwable) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }

        safeLog('SAVE_RESUME_FAILED', [
            'action' => $action,
            'user_id' => $userId,
            'result' => 'failed'
        ]);

        responseJson(false, 'ذخیره رزومه انجام نشد', [], 500);
    }

    responseJson(
        true,
        'رزومه و مهارت‌ها با موفقیت ذخیره شدند',
        [
            'professional_title' => $professionalTitle,
            'selected_skill_count' => count($skillIds),
            'resume_completed' => true
        ]
    );
}


elseif ($action === 'upload_profile_image') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    ensureUserExists($pdo, $userId);

    $image = saveUploadedImage(
        'profile_image',
        'uploads/profile_images'
    );

    $oldStatement = $pdo->prepare(
        'SELECT profile_image_path
         FROM user_profiles
         WHERE user_id = ?
         LIMIT 1'
    );
    $oldStatement->execute([$userId]);
    $oldPath = $oldStatement->fetchColumn() ?: null;

    $statement = $pdo->prepare(
        'INSERT INTO user_profiles (
            user_id,
            profile_kind,
            profile_image_path,
            profile_completed,
            review_status
        ) VALUES (?, "individual", ?, 0, "draft")
        ON DUPLICATE KEY UPDATE
            profile_image_path = VALUES(profile_image_path)'
    );

    try {
        $statement->execute([
            $userId,
            $image['relative_path']
        ]);
    } catch (Throwable $throwable) {
        deleteRelativeUpload($image['relative_path']);
        responseJson(false, 'ذخیره تصویر پروفایل انجام نشد', [], 500);
    }

    if ($oldPath && $oldPath !== $image['relative_path']) {
        deleteRelativeUpload((string)$oldPath);
    }

    responseJson(true, 'تصویر پروفایل با موفقیت ذخیره شد', [
        'profile_image_url' => toPublicUrl($image['relative_path'])
    ]);
}

elseif ($action === 'get_portfolio') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    ensureUserExists($pdo, $userId);

    $statement = $pdo->prepare(
        'SELECT
            id,
            title,
            description,
            image_path,
            attachment_path,
            attachment_name,
            external_link,
            created_at,
            updated_at
         FROM portfolio_items
         WHERE user_id = ?
         ORDER BY id DESC
         LIMIT 50'
    );
    $statement->execute([$userId]);

    $items = [];

    foreach ($statement->fetchAll() as $row) {
        $row['image_url'] = toPublicUrl($row['image_path'] ?? null);
        $row['attachment_url'] = toPublicUrl(
            $row['attachment_path'] ?? null
        );
        unset($row['image_path'], $row['attachment_path']);
        $items[] = $row;
    }

    responseJson(true, 'نمونه‌کارها دریافت شدند', [
        'portfolio_items' => $items
    ]);
}

elseif ($action === 'add_portfolio') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    ensureUserExists($pdo, $userId);
    ensureFreelancerUser($pdo, $userId);

    $countStatement = $pdo->prepare(
        'SELECT COUNT(*)
         FROM portfolio_items
         WHERE user_id = ?'
    );
    $countStatement->execute([$userId]);

    if ((int)$countStatement->fetchColumn() >= 50) {
        responseJson(false, 'حداکثر ۵۰ نمونه‌کار قابل ثبت است', [], 409);
    }

    $title = cleanString($input['title'] ?? '');
    $description = cleanString($input['description'] ?? '');
    $externalLink = normalizeHttpUrl(
        cleanString($input['external_link'] ?? '')
    );

    if (mb_strlen($title) < 3 || mb_strlen($title) > 150) {
        responseJson(
            false,
            'عنوان نمونه‌کار باید بین ۳ تا ۱۵۰ کاراکتر باشد',
            [],
            422
        );
    }

    if (mb_strlen($description) < 10 || mb_strlen($description) > 2000) {
        responseJson(
            false,
            'توضیحات نمونه‌کار باید بین ۱۰ تا ۲۰۰۰ کاراکتر باشد',
            [],
            422
        );
    }

    $image = saveUploadedImage(
        'portfolio_image',
        'uploads/portfolio/images'
    );

    $attachment = saveUploadedAttachment(
        'attachment',
        'uploads/portfolio/files'
    );

    $statement = $pdo->prepare(
        'INSERT INTO portfolio_items (
            user_id,
            title,
            description,
            image_path,
            attachment_path,
            attachment_name,
            attachment_mime,
            attachment_size,
            external_link
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)'
    );

    try {
        $statement->execute([
            $userId,
            $title,
            $description,
            $image['relative_path'],
            $attachment['relative_path'] ?? null,
            $attachment['original_name'] ?? null,
            $attachment['mime_type'] ?? null,
            $attachment['size_bytes'] ?? null,
            $externalLink !== '' ? $externalLink : null
        ]);
    } catch (Throwable $throwable) {
        deleteRelativeUpload($image['relative_path']);
        deleteRelativeUpload($attachment['relative_path'] ?? null);
        responseJson(false, 'ذخیره نمونه‌کار انجام نشد', [], 500);
    }

    responseJson(true, 'نمونه‌کار با موفقیت ذخیره شد', [
        'portfolio_id' => (int)$pdo->lastInsertId()
    ]);
}

elseif ($action === 'delete_portfolio') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    $portfolioId = requirePositiveInt(
        $input,
        'portfolio_id',
        'شناسه نمونه‌کار معتبر نیست'
    );

    ensureFreelancerUser($pdo, $userId);

    $selectStatement = $pdo->prepare(
        'SELECT image_path, attachment_path
         FROM portfolio_items
         WHERE id = ? AND user_id = ?
         LIMIT 1'
    );
    $selectStatement->execute([$portfolioId, $userId]);
    $portfolio = $selectStatement->fetch();

    if (!$portfolio) {
        responseJson(false, 'نمونه‌کار پیدا نشد', [], 404);
    }

    $deleteStatement = $pdo->prepare(
        'DELETE FROM portfolio_items
         WHERE id = ? AND user_id = ?'
    );
    $deleteStatement->execute([$portfolioId, $userId]);

    deleteRelativeUpload($portfolio['image_path'] ?? null);
    deleteRelativeUpload($portfolio['attachment_path'] ?? null);

    responseJson(true, 'نمونه‌کار حذف شد');
}


elseif ($action === 'get_experience_education') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    ensureUserExists($pdo, $userId);

    $workStatement = $pdo->prepare(
        'SELECT
            id,
            job_title,
            company_name,
            start_period,
            end_period,
            is_current,
            description,
            created_at,
            updated_at
         FROM user_work_experiences
         WHERE user_id = ?
         ORDER BY sort_order ASC, id DESC
         LIMIT 50'
    );
    $workStatement->execute([$userId]);

    $educationStatement = $pdo->prepare(
        'SELECT
            id,
            degree_title,
            institution_name,
            field_of_study,
            start_year,
            end_year,
            description,
            created_at,
            updated_at
         FROM user_educations
         WHERE user_id = ?
         ORDER BY sort_order ASC, id DESC
         LIMIT 50'
    );
    $educationStatement->execute([$userId]);

    responseJson(true, 'سوابق کاری و تحصیلات دریافت شدند', [
        'work_experiences' => $workStatement->fetchAll(),
        'educations' => $educationStatement->fetchAll()
    ]);
}

elseif ($action === 'add_work_experience') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    ensureUserExists($pdo, $userId);
    ensureFreelancerUser($pdo, $userId);

    $countStatement = $pdo->prepare(
        'SELECT COUNT(*)
         FROM user_work_experiences
         WHERE user_id = ?'
    );
    $countStatement->execute([$userId]);

    if ((int)$countStatement->fetchColumn() >= 50) {
        responseJson(false, 'حداکثر ۵۰ سابقه کاری قابل ثبت است', [], 409);
    }

    $jobTitle = cleanString($input['job_title'] ?? '');
    $companyName = cleanString($input['company_name'] ?? '');
    $startPeriod = cleanString($input['start_period'] ?? '');
    $endPeriod = cleanString($input['end_period'] ?? '');
    $isCurrent = (int)($input['is_current'] ?? 0) === 1 ? 1 : 0;
    $description = cleanString($input['description'] ?? '');

    if (mb_strlen($jobTitle) < 3 || mb_strlen($jobTitle) > 150) {
        responseJson(false, 'عنوان شغلی باید بین ۳ تا ۱۵۰ کاراکتر باشد', [], 422);
    }

    if (mb_strlen($companyName) < 2 || mb_strlen($companyName) > 150) {
        responseJson(false, 'نام شرکت یا کارفرما باید بین ۲ تا ۱۵۰ کاراکتر باشد', [], 422);
    }

    if (mb_strlen($startPeriod) < 3 || mb_strlen($startPeriod) > 80) {
        responseJson(false, 'زمان شروع سابقه کاری معتبر نیست', [], 422);
    }

    if ($isCurrent === 0 && (mb_strlen($endPeriod) < 3 || mb_strlen($endPeriod) > 80)) {
        responseJson(false, 'زمان پایان سابقه کاری معتبر نیست', [], 422);
    }

    if (mb_strlen($description) < 10 || mb_strlen($description) > 1000) {
        responseJson(false, 'توضیحات سابقه کاری باید بین ۱۰ تا ۱۰۰۰ کاراکتر باشد', [], 422);
    }

    $orderStatement = $pdo->prepare(
        'SELECT COALESCE(MAX(sort_order), 0) + 1
         FROM user_work_experiences
         WHERE user_id = ?'
    );
    $orderStatement->execute([$userId]);
    $sortOrder = (int)$orderStatement->fetchColumn();

    $statement = $pdo->prepare(
        'INSERT INTO user_work_experiences (
            user_id,
            job_title,
            company_name,
            start_period,
            end_period,
            is_current,
            description,
            sort_order
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
    );

    $statement->execute([
        $userId,
        $jobTitle,
        $companyName,
        $startPeriod,
        $isCurrent === 1 ? 'اکنون' : $endPeriod,
        $isCurrent,
        $description,
        $sortOrder
    ]);

    responseJson(true, 'سابقه کاری ذخیره شد', [
        'work_experience_id' => (int)$pdo->lastInsertId()
    ]);
}

elseif ($action === 'delete_work_experience') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    $workExperienceId = requirePositiveInt(
        $input,
        'work_experience_id',
        'شناسه سابقه کاری معتبر نیست'
    );

    ensureFreelancerUser($pdo, $userId);

    $statement = $pdo->prepare(
        'DELETE FROM user_work_experiences
         WHERE id = ? AND user_id = ?'
    );
    $statement->execute([$workExperienceId, $userId]);

    if ($statement->rowCount() === 0) {
        responseJson(false, 'سابقه کاری پیدا نشد', [], 404);
    }

    responseJson(true, 'سابقه کاری حذف شد');
}

elseif ($action === 'add_education') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    ensureUserExists($pdo, $userId);
    ensureFreelancerUser($pdo, $userId);

    $countStatement = $pdo->prepare(
        'SELECT COUNT(*)
         FROM user_educations
         WHERE user_id = ?'
    );
    $countStatement->execute([$userId]);

    if ((int)$countStatement->fetchColumn() >= 50) {
        responseJson(false, 'حداکثر ۵۰ مورد تحصیلی قابل ثبت است', [], 409);
    }

    $degreeTitle = cleanString($input['degree_title'] ?? '');
    $institutionName = cleanString($input['institution_name'] ?? '');
    $fieldOfStudy = cleanString($input['field_of_study'] ?? '');
    $startYear = cleanString($input['start_year'] ?? '');
    $endYear = cleanString($input['end_year'] ?? '');
    $description = cleanString($input['description'] ?? '');

    if (mb_strlen($degreeTitle) < 3 || mb_strlen($degreeTitle) > 150) {
        responseJson(false, 'عنوان مدرک یا دوره باید بین ۳ تا ۱۵۰ کاراکتر باشد', [], 422);
    }

    if (mb_strlen($institutionName) < 2 || mb_strlen($institutionName) > 150) {
        responseJson(false, 'نام دانشگاه یا آموزشگاه باید بین ۲ تا ۱۵۰ کاراکتر باشد', [], 422);
    }

    if ($fieldOfStudy !== '' && mb_strlen($fieldOfStudy) > 150) {
        responseJson(false, 'رشته یا گرایش بیش از حد طولانی است', [], 422);
    }

    if ($startYear !== '' && !preg_match('/^[0-9]{4}$/', $startYear)) {
        responseJson(false, 'سال شروع معتبر نیست', [], 422);
    }

    if ($endYear !== '' && !preg_match('/^[0-9]{4}$/', $endYear)) {
        responseJson(false, 'سال پایان معتبر نیست', [], 422);
    }

    if ($description !== '' && mb_strlen($description) > 1000) {
        responseJson(false, 'توضیحات تحصیلات بیش از حد طولانی است', [], 422);
    }

    $orderStatement = $pdo->prepare(
        'SELECT COALESCE(MAX(sort_order), 0) + 1
         FROM user_educations
         WHERE user_id = ?'
    );
    $orderStatement->execute([$userId]);
    $sortOrder = (int)$orderStatement->fetchColumn();

    $statement = $pdo->prepare(
        'INSERT INTO user_educations (
            user_id,
            degree_title,
            institution_name,
            field_of_study,
            start_year,
            end_year,
            description,
            sort_order
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
    );

    $statement->execute([
        $userId,
        $degreeTitle,
        $institutionName,
        $fieldOfStudy !== '' ? $fieldOfStudy : null,
        $startYear !== '' ? $startYear : null,
        $endYear !== '' ? $endYear : null,
        $description !== '' ? $description : null,
        $sortOrder
    ]);

    responseJson(true, 'تحصیلات ذخیره شد', [
        'education_id' => (int)$pdo->lastInsertId()
    ]);
}

elseif ($action === 'delete_education') {
    $userId = requirePositiveInt(
        $input,
        'user_id',
        'شناسه کاربر معتبر نیست'
    );

    $educationId = requirePositiveInt(
        $input,
        'education_id',
        'شناسه تحصیلات معتبر نیست'
    );

    ensureFreelancerUser($pdo, $userId);

    $statement = $pdo->prepare(
        'DELETE FROM user_educations
         WHERE id = ? AND user_id = ?'
    );
    $statement->execute([$educationId, $userId]);

    if ($statement->rowCount() === 0) {
        responseJson(false, 'تحصیلات پیدا نشد', [], 404);
    }

    responseJson(true, 'تحصیلات حذف شد');
}


else {
    responseJson(false, 'action نامعتبر است', [], 400);
}
