<?php
require_once "../config/database.php";
require_once "../includes/auth.php";
require_once "../includes/csrf.php";
require_once "../includes/rbac.php";

header("Content-Type: application/json; charset=utf-8");
requireApiAuth();

$rawInput = file_get_contents("php://input");
$parsedInput = null;
if ($rawInput !== false && $rawInput !== "") {
    $decoded = json_decode($rawInput, true);
    if (is_array($decoded)) {
        $parsedInput = $decoded;
    }
}
if (($_SERVER["REQUEST_METHOD"] ?? "") === "POST" && !empty($_POST)) {
    $parsedInput = $_POST;
}

if ($_SERVER["REQUEST_METHOD"] !== "GET") {
    $authRoleId = (int)($_SESSION["user"]["role_id"] ?? 0);
    $canManage = hasPermission("manage_users");
    $isModeratorLimited = ($authRoleId === 5);
    $requestAction = trim((string)(($parsedInput["action"] ?? "create")));
    $requestedRoleId = (int)($parsedInput["role_id"] ?? 0);
    $isAgencyCreateWorker = (
        $authRoleId === 3
        && ($_SERVER["REQUEST_METHOD"] === "POST")
        && $requestAction === "create"
        && $requestedRoleId === 2
    );

    if (!$canManage && !$isModeratorLimited && !$isAgencyCreateWorker) {
        http_response_code(403);
        echo json_encode(["success" => false, "error" => "forbidden"]);
        exit;
    }
}

if ($_SERVER["REQUEST_METHOD"] === "GET") {
    $currentRoleId = (int)($_SESSION["user"]["role_id"] ?? 0);

    // Manage permissions page requires full visibility for admin/moderator.
    if ($currentRoleId === 1 || $currentRoleId === 5) {
        $stmt = $pdo->prepare("
            SELECT u.id, u.email, u.role_id, r.name AS role_name
            FROM users u
            LEFT JOIN roles r ON r.id = u.role_id
            ORDER BY u.email ASC
        ");
        $stmt->execute();
        echo json_encode(["success" => true, "data" => $stmt->fetchAll(PDO::FETCH_ASSOC)]);
        exit;
    }

    $allowedRolesByRole = [
        2 => [4],     // worker -> companies
        3 => [2, 4],  // agency -> workers + companies
        4 => [2]      // company -> workers
    ];

    $allowedRoles = $allowedRolesByRole[$currentRoleId] ?? [];
    if (!$allowedRoles) {
        echo json_encode(["success" => true, "data" => []]);
        exit;
    }

    $placeholders = implode(",", array_fill(0, count($allowedRoles), "?"));
    $sql = "
        SELECT u.id, u.email, u.role_id, r.name AS role_name
        FROM users u
        LEFT JOIN roles r ON r.id = u.role_id
        WHERE u.id <> ? AND u.role_id IN ($placeholders)
        ORDER BY u.email ASC
    ";

    $params = array_merge([(int)$_SESSION["user"]["id"]], $allowedRoles);
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);

    echo json_encode(["success" => true, "data" => $stmt->fetchAll(PDO::FETCH_ASSOC)]);
    exit;
}

$data = is_array($parsedInput) ? $parsedInput : [];
if (!is_array($data)) $data = [];
if (isset($data["skill_ids"]) && !is_array($data["skill_ids"])) {
    $decodedSkillIds = json_decode((string)$data["skill_ids"], true);
    if (is_array($decodedSkillIds)) {
        $data["skill_ids"] = $decodedSkillIds;
    }
}

if (!requireCsrfFromPayload($data)) {
    http_response_code(419);
    echo json_encode(["success" => false, "error" => "csrf_failed"]);
    exit;
}

$action = trim((string)($data["action"] ?? "create"));
$userId = (int)($data["user_id"] ?? 0);
$email = trim((string)($data["email"] ?? ""));
$password = (string)($data["password"] ?? "");
$roleId = (int)($data["role_id"] ?? 0);
$firstName = trim((string)($data["first_name"] ?? ""));
$lastName = trim((string)($data["last_name"] ?? ""));
$skills = trim((string)($data["skills"] ?? ""));
$skillIds = $data["skill_ids"] ?? [];
$location = trim((string)($data["location"] ?? ""));
$bio = trim((string)($data["bio"] ?? ""));
$isPartnerAgency = (int)($data["is_partner_agency"] ?? 0);
$companyTaxId = trim((string)($data["company_tax_id"] ?? ""));
$companyAddress = trim((string)($data["company_address"] ?? ""));
$agencyTaxId = trim((string)($data["agency_tax_id"] ?? ""));
$agencyAddress = trim((string)($data["agency_address"] ?? ""));
$languages = trim((string)($data["languages"] ?? ""));
$country = trim((string)($data["country"] ?? ""));
$availability = trim((string)($data["availability"] ?? ""));
$certificates = trim((string)($data["certificates"] ?? ""));
$position = trim((string)($data["position"] ?? ""));
$companyPlanCode = trim((string)($data["company_plan_code"] ?? ""));
$cvUrl = trim((string)($data["cv_url"] ?? ""));
$photoUrl = trim((string)($data["photo_url"] ?? ""));
$youtubeUrl = trim((string)($data["youtube_url"] ?? ""));
$desiredSalaryFromRaw = trim((string)($data["desired_salary_from"] ?? ""));
$desiredSalaryToRaw = trim((string)($data["desired_salary_to"] ?? ""));

function normalizeYoutubeUrl(string $value): string {
    $value = trim($value);
    if ($value === "") return "";

    if (preg_match('/^[A-Za-z0-9_-]{11}$/', $value)) {
        return "https://www.youtube.com/watch?v=" . $value;
    }

    $parts = @parse_url($value);
    if (!is_array($parts)) {
        throw new Exception("invalid_youtube_url");
    }

    $host = strtolower((string)($parts["host"] ?? ""));
    $path = (string)($parts["path"] ?? "");
    $query = (string)($parts["query"] ?? "");

    if ($host === "youtu.be") {
        $id = trim($path, "/");
        if (preg_match('/^[A-Za-z0-9_-]{11}$/', $id)) {
            return "https://www.youtube.com/watch?v=" . $id;
        }
    }

    if (strpos($host, "youtube.com") !== false) {
        parse_str($query, $q);
        if (!empty($q["v"]) && preg_match('/^[A-Za-z0-9_-]{11}$/', (string)$q["v"])) {
            return "https://www.youtube.com/watch?v=" . $q["v"];
        }
        if (preg_match('~/embed/([A-Za-z0-9_-]{11})~', $path, $m)) {
            return "https://www.youtube.com/watch?v=" . $m[1];
        }
        if (preg_match('~/shorts/([A-Za-z0-9_-]{11})~', $path, $m)) {
            return "https://www.youtube.com/watch?v=" . $m[1];
        }
    }

    throw new Exception("invalid_youtube_url");
}

if ($cvUrl !== "" && !filter_var($cvUrl, FILTER_VALIDATE_URL)) {
    throw new Exception("invalid_cv_url");
}
if ($photoUrl !== "" && !filter_var($photoUrl, FILTER_VALIDATE_URL)) {
    throw new Exception("invalid_photo_url");
}
if ($youtubeUrl !== "" && !filter_var($youtubeUrl, FILTER_VALIDATE_URL)) {
    throw new Exception("invalid_youtube_url");
}

$desiredSalaryFrom = null;
$desiredSalaryTo = null;
if ($desiredSalaryFromRaw !== "") {
    if (!preg_match('/^\d+$/', $desiredSalaryFromRaw)) {
        throw new Exception("invalid_desired_salary_from");
    }
    $desiredSalaryFrom = (int)$desiredSalaryFromRaw;
}
if ($desiredSalaryToRaw !== "") {
    if (!preg_match('/^\d+$/', $desiredSalaryToRaw)) {
        throw new Exception("invalid_desired_salary_to");
    }
    $desiredSalaryTo = (int)$desiredSalaryToRaw;
}
if ($desiredSalaryFrom !== null && $desiredSalaryTo !== null && $desiredSalaryFrom > $desiredSalaryTo) {
    throw new Exception("invalid_desired_salary_range");
}

$pdo->beginTransaction();

try {
    if ($action === "update") {
        if ($userId <= 0 || $userId == (int)$_SESSION["user"]["id"]) {
            throw new Exception("invalid_user");
        }
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new Exception("invalid_email");
        }
        if ($roleId < 1 || $roleId > 5) {
            throw new Exception("invalid_role");
        }

        $actorRoleId = (int)($_SESSION["user"]["role_id"] ?? 0);
        if ($actorRoleId === 5 && ($roleId === 1 || $roleId === 5)) {
            throw new Exception("moderator_cannot_assign_privileged_roles");
        }
        if (!empty($password) && strlen($password) < 6) {
            throw new Exception("password_too_short");
        }

        if (!empty($password)) {
            $upd = $pdo->prepare("UPDATE users SET email = ?, password = SHA2(?, 256), role_id = ?, updated_at = NOW() WHERE id = ?");
            $upd->execute([$email, $password, $roleId, $userId]);
        } else {
            $upd = $pdo->prepare("UPDATE users SET email = ?, role_id = ?, updated_at = NOW() WHERE id = ?");
            $upd->execute([$email, $roleId, $userId]);
        }

        $audit = $pdo->prepare("INSERT INTO audit_log (user_id, action) VALUES (?, ?)");
        $audit->execute([(int)$_SESSION["user"]["id"], "Updated user #{$userId} ({$email}) to role {$roleId}"]);

        $pdo->commit();
        echo json_encode(["success" => true, "message" => "User updated"]);
        exit;
    }

    if ($action === "delete") {
        if ($userId <= 0 || $userId == (int)$_SESSION["user"]["id"]) {
            throw new Exception("invalid_user");
        }

        $actorRoleId = (int)($_SESSION["user"]["role_id"] ?? 0);
        $targetStmt = $pdo->prepare("SELECT role_id FROM users WHERE id = ? LIMIT 1");
        $targetStmt->execute([$userId]);
        $targetRoleId = (int)($targetStmt->fetchColumn() ?: 0);
        if ($targetRoleId <= 0) {
            throw new Exception("user_not_found");
        }
        if ($actorRoleId === 5 && ($targetRoleId === 1 || $targetRoleId === 5)) {
            throw new Exception("moderator_cannot_delete_privileged_users");
        }

        $workerStmt = $pdo->prepare("SELECT id FROM workers WHERE user_id = ? LIMIT 1");
        $workerStmt->execute([$userId]);
        $workerId = (int)($workerStmt->fetchColumn() ?: 0);

        if ($workerId > 0) {
            $pdo->prepare("DELETE FROM worker_added_by WHERE worker_id = ?")->execute([$workerId]);
            $pdo->prepare("DELETE FROM worker_documents WHERE worker_id = ?")->execute([$workerId]);
            $pdo->prepare("DELETE FROM matches WHERE worker_id = ?")->execute([$workerId]);
            $pdo->prepare("DELETE FROM requests WHERE worker_id = ?")->execute([$workerId]);
            $pdo->prepare("DELETE FROM workers WHERE id = ?")->execute([$workerId]);
        }

        $pdo->prepare("DELETE FROM user_profiles WHERE user_id = ?")->execute([$userId]);
        $pdo->prepare("DELETE FROM user_skills WHERE user_id = ?")->execute([$userId]);
        $pdo->prepare("DELETE FROM users WHERE id = ?")->execute([$userId]);

        $audit = $pdo->prepare("INSERT INTO audit_log (user_id, action) VALUES (?, ?)");
        $audit->execute([(int)$_SESSION["user"]["id"], "Deleted user #{$userId}"]);

        $pdo->commit();
        echo json_encode(["success" => true, "message" => "User deleted"]);
        exit;
    }

    // CREATE (default)
    $isWorkerCreate = ($roleId === 2);
    if (!$isWorkerCreate || $email !== "") {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new Exception("invalid_email");
        }
    } else {
        $email = "worker+" . time() . "." . random_int(1000, 9999) . "@local.konzona";
    }

    if (!$isWorkerCreate || $password !== "") {
        if (strlen($password) < 6) {
            throw new Exception("password_too_short");
        }
    } else {
        $password = bin2hex(random_bytes(8));
    }
    if ($roleId < 1 || $roleId > 5) {
        throw new Exception("invalid_role");
    }

    $actorRoleId = (int)($_SESSION["user"]["role_id"] ?? 0);
    if ($actorRoleId === 5 && ($roleId === 1 || $roleId === 5)) {
        throw new Exception("moderator_cannot_assign_privileged_roles");
    }

    $exists = $pdo->prepare("SELECT id FROM users WHERE email = ? LIMIT 1");
    $exists->execute([$email]);
    if ($exists->fetch()) {
        throw new Exception("email_exists");
    }

$ins = $pdo->prepare("INSERT INTO users (email, password, role_id) VALUES (?, SHA2(?, 256), ?)");
$ins->execute([$email, $password, $roleId]);
$userId = (int)$pdo->lastInsertId();

$createdWorkerId = 0;
if ($roleId === 2) { // only for worker
    $w = $pdo->prepare("INSERT INTO workers (user_id, first_name, last_name, status, updated_at) VALUES (?, ?, ?, 'slobodan', NOW())");
    $w->execute([$userId, $firstName, $lastName]);
    $createdWorkerId = (int)$pdo->lastInsertId();

    if ($createdWorkerId > 0) {
        $insAddedBy = $pdo->prepare("
            INSERT INTO worker_added_by (worker_id, added_by_user_id, added_by_role_id, added_at)
            VALUES (?, ?, ?, NOW())
            ON DUPLICATE KEY UPDATE
                added_by_user_id = VALUES(added_by_user_id),
                added_by_role_id = VALUES(added_by_role_id),
                added_at = VALUES(added_at)
        ");
        $insAddedBy->execute([
            $createdWorkerId,
            (int)($_SESSION["user"]["id"] ?? 0),
            (int)($_SESSION["user"]["role_id"] ?? 0)
        ]);
    }
}
$isPartnerAgency = (int)($data["is_partner_agency"] ?? 0);
if ($roleId === 3) { // agency profile bootstrap (stored in users table in this project)
    $agencyName = trim($firstName . " " . $lastName);
    if ($agencyName === "") {
        $agencyName = $email;
    }

    $updAgency = $pdo->prepare("
        UPDATE users
        SET agency_name = ?, agency_address = ?, agency_tax_id = ?, agency_is_partner = ?
        WHERE id = ?
    ");
    $finalAgencyAddress = $agencyAddress !== "" ? $agencyAddress : $location;
    $updAgency->execute([$agencyName, $finalAgencyAddress, $agencyTaxId, $isPartnerAgency ? 1 : 0, $userId]);
}
if ($roleId === 4) { // company profile bootstrap (stored in users table in this project)
    $companyName = trim($firstName . " " . $lastName);
    if ($companyName === "") {
        $companyName = $email;
    }

    $updCompany = $pdo->prepare("
        UPDATE users
        SET company_name = ?, company_address = ?, company_tax_id = ?
        WHERE id = ?
    ");
    $finalCompanyAddress = $companyAddress !== "" ? $companyAddress : $location;
    $updCompany->execute([$companyName, $finalCompanyAddress, $companyTaxId, $userId]);
}

    if ($roleId === 4 && $companyPlanCode !== "") {
        $planMap = [
            "COMPANY_BASIC" => ["price" => 100.00, "limit" => 2],
            "COMPANY_PRO" => ["price" => 220.00, "limit" => 5],
            "COMPANY_ENTERPRISE" => ["price" => 450.00, "limit" => 15]
        ];
        if (!isset($planMap[$companyPlanCode])) {
            throw new Exception("invalid_company_plan_code");
        }
        $subIns = $pdo->prepare("
            INSERT INTO company_subscriptions (
                company_id, plan_code, monthly_price, monthly_request_limit, requests_used, status, starts_at, expires_at, created_at, updated_at
            ) VALUES (?, ?, ?, ?, 0, 'pending', NULL, NULL, NOW(), NOW())
        ");
        $subIns->execute([$userId, $companyPlanCode, (float)$planMap[$companyPlanCode]["price"], (int)$planMap[$companyPlanCode]["limit"]]);
    }

    $videoInterviewPath = normalizeYoutubeUrl((string)($data["video_interview"] ?? ""));
    $videoWorkPath = normalizeYoutubeUrl((string)($data["video_work"] ?? ""));
if ($roleId === 2 && $position === "") {
        throw new Exception("position_required");
    }

    $skillsText = $skills;
    if (is_array($skillIds) && count($skillIds) > 0) {
        $skillIds = array_values(array_unique(array_map("intval", $skillIds)));
        $skillIds = array_filter($skillIds, fn($v) => $v > 0);

        if (!empty($skillIds)) {
            $placeholdersSkill = implode(",", array_fill(0, count($skillIds), "?"));
            $skillNamesStmt = $pdo->prepare("SELECT id, name FROM skills WHERE id IN ($placeholdersSkill)");
            $skillNamesStmt->execute($skillIds);
            $skillRows = $skillNamesStmt->fetchAll(PDO::FETCH_ASSOC);

            $validIds = [];
            $skillNames = [];
            foreach ($skillRows as $sr) {
                $validIds[] = (int)$sr["id"];
                $skillNames[] = (string)$sr["name"];
            }

            $skillsText = implode(", ", $skillNames);

            if (!empty($validIds)) {
                $insUs = $pdo->prepare("INSERT IGNORE INTO user_skills (user_id, skill_id) VALUES (?, ?)");
                foreach ($validIds as $sid) {
                    $insUs->execute([$userId, $sid]);
                }
            }
        }
    }

    $p = $pdo->prepare("
        INSERT INTO user_profiles (
            user_id, skills, location, bio, languages, country, availability, certificates,
            cv_url, photo_url, youtube_url, video_interview, video_work, position,
            desired_salary_from, desired_salary_to
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    ");
    $p->execute([
        $userId,
        $skillsText,
        $location,
        $bio,
        $languages,
        $country,
        ($availability !== "" ? $availability : null),
        $certificates,
        ($cvUrl !== "" ? $cvUrl : null),
        ($photoUrl !== "" ? $photoUrl : null),
        ($youtubeUrl !== "" ? $youtubeUrl : null),
        ($videoInterviewPath !== "" ? $videoInterviewPath : null),
        ($videoWorkPath !== "" ? $videoWorkPath : null),
        ($position !== "" ? $position : null),
        $desiredSalaryFrom,
        $desiredSalaryTo
    ]);

    $audit = $pdo->prepare("INSERT INTO audit_log (user_id, action) VALUES (?, ?)");
    $audit->execute([(int)$_SESSION["user"]["id"], "Created user #{$userId} ({$email}) role {$roleId}"]);

    $pdo->commit();

    echo json_encode(["success" => true, "data" => ["user_id" => $userId]]);
} catch (Throwable $e) {
    $pdo->rollBack();
    http_response_code(422);
    echo json_encode(["success" => false, "error" => $e->getMessage()]);
}
?>
