<?php
declare(strict_types=1);

require_once __DIR__ . '/../config/bootstrap.php';

require_permission($conn, 'services');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    redirect('../pages/services.php');
}

$returnTo = safe_page_return((string) ($_POST['return_to'] ?? ''), 'services.php');
$serviceId = filter_input(INPUT_POST, 'service_id', FILTER_VALIDATE_INT);
$serviceName = trim((string) ($_POST['service_name'] ?? ''));
$serviceType = trim((string) ($_POST['service_type'] ?? 'main_service'));
$categoryId = filter_input(INPUT_POST, 'category_id', FILTER_VALIDATE_INT);
$mainServiceId = filter_input(INPUT_POST, 'main_service_id', FILTER_VALIDATE_INT);
$groupId = filter_input(INPUT_POST, 'group_id', FILTER_VALIDATE_INT);
$packageVehicleScope = normalize_package_vehicle_scope(trim((string) ($_POST['package_vehicle_scope'] ?? 'member')));
$isQuickService = isset($_POST['is_quick_service']) ? 1 : 0;
$priceRaw = str_replace(',', '', trim((string) ($_POST['price'] ?? '0')));
$description = trim((string) ($_POST['description'] ?? ''));
$isActive = isset($_POST['is_active']) ? 1 : 0;
$packageServiceCounts = (array) ($_POST['package_service_counts'] ?? array());

$oldInput = array(
    'service_name' => $serviceName,
    'service_type' => $serviceType,
    'category_id' => (string) ($categoryId ?: ''),
    'main_service_id' => (string) ($mainServiceId ?: ''),
    'group_id' => (string) ($groupId ?: ''),
    'package_vehicle_scope' => $packageVehicleScope,
    'is_quick_service' => (string) $isQuickService,
    'price' => $priceRaw,
    'description' => $description,
    'is_active' => (string) $isActive,
    'package_service_counts' => $packageServiceCounts,
);

$redirectPath = '../pages/' . $returnTo;

if ($serviceName === '' || !$categoryId) {
    redirect_with_flash($redirectPath, 'error', localized_flash_message('กรุณาระบุชื่อบริการและหมวดหมู่', 'Service name and category are required.'), $oldInput);
}

if (!array_key_exists($serviceType, service_type_options())) {
    redirect_with_flash($redirectPath, 'error', localized_flash_message('ประเภทบริการไม่ถูกต้อง', 'Service type is invalid.'), $oldInput);
}

if (!array_key_exists($packageVehicleScope, package_vehicle_scope_options())) {
    redirect_with_flash($redirectPath, 'error', localized_flash_message('ขอบเขตการใช้รถของแพ็กเกจไม่ถูกต้อง', 'Package vehicle access is invalid.'), $oldInput);
}

$categoryStmt = db_prepare($conn, "
    SELECT category_id, category_name
    FROM service_categories
    WHERE category_id = ?
    LIMIT 1
");
$categoryStmt->bind_param('i', $categoryId);
$categoryStmt->execute();
$selectedCategory = $categoryStmt->get_result()->fetch_assoc();
$categoryStmt->close();

if (!$selectedCategory) {
    redirect_with_flash($redirectPath, 'error', localized_flash_message('ไม่พบหมวดหมู่ที่เลือก', 'Selected category is not available.'), $oldInput);
}

$mainServiceIdValue = $mainServiceId ?: 0;
$groupIdValue = $groupId ?: 0;
$selectedMainService = null;

if ($serviceType === 'sub_service') {
    if ($mainServiceIdValue <= 0) {
        redirect_with_flash($redirectPath, 'error', localized_flash_message('บริการย่อยต้องผูกกับบริการหลัก', 'Sub service must be linked to a main service.'), $oldInput);
    }

    $mainServiceStmt = db_prepare($conn, "
        SELECT service_id, category_id
        FROM services
        WHERE service_id = ?
            AND service_type = 'main_service'
        LIMIT 1
    ");
    $mainServiceStmt->bind_param('i', $mainServiceIdValue);
    $mainServiceStmt->execute();
    $selectedMainService = $mainServiceStmt->get_result()->fetch_assoc();
    $mainServiceStmt->close();

    if (!$selectedMainService || (int) ($selectedMainService['category_id'] ?? 0) !== $categoryId) {
        redirect_with_flash($redirectPath, 'error', localized_flash_message('บริการหลักที่เลือกไม่มีอยู่ในหมวดหมู่นี้', 'Selected main service is not available in this category.'), $oldInput);
    }

    if ($groupIdValue > 0) {
        $groupStmt = db_prepare($conn, "
            SELECT group_id, category_id, main_service_id
            FROM service_groups
            WHERE group_id = ?
            LIMIT 1
        ");
        $groupStmt->bind_param('i', $groupIdValue);
        $groupStmt->execute();
        $selectedGroup = $groupStmt->get_result()->fetch_assoc();
        $groupStmt->close();

        if (
            !$selectedGroup
            || (int) ($selectedGroup['category_id'] ?? 0) !== $categoryId
            || (int) ($selectedGroup['main_service_id'] ?? 0) !== $mainServiceIdValue
        ) {
            redirect_with_flash($redirectPath, 'error', localized_flash_message('กลุ่มบริการที่เลือกไม่มีอยู่สำหรับบริการหลักนี้', 'Selected service group is not available for this main service.'), $oldInput);
        }
    }
} else {
    $mainServiceIdValue = 0;
    $groupIdValue = 0;
}

if ($serviceType !== 'package') {
    $packageVehicleScope = 'member';
} else {
    $isQuickService = 0;
}

$price = is_numeric($priceRaw) ? (float) $priceRaw : null;
if ($price === null || $price < 0) {
    redirect_with_flash($redirectPath, 'error', localized_flash_message('ราคาบริการไม่ถูกต้อง', 'Service price is invalid.'), $oldInput);
}

$normalizedPackageCounts = array();
foreach ($packageServiceCounts as $subServiceId => $count) {
    $subServiceId = (int) $subServiceId;
    $includedUses = (int) $count;

    if ($subServiceId > 0 && $includedUses > 0) {
        $normalizedPackageCounts[$subServiceId] = $includedUses;
    }
}

if ($serviceType === 'package' && empty($normalizedPackageCounts)) {
    redirect_with_flash($redirectPath, 'error', localized_flash_message('กรุณาเลือกบริการย่อยอย่างน้อย 1 รายการสำหรับแพ็กเกจ', 'Select at least one sub service for the package.'), $oldInput);
}

$existingService = null;
$beforeServiceSnapshot = array();
if ($serviceId) {
    $existingStmt = db_prepare($conn, "
        SELECT
            s.service_id,
            s.service_type,
            COUNT(DISTINCT od.detail_id) AS usage_count,
            COUNT(DISTINCT child.service_id) AS child_service_count,
            COUNT(DISTINCT sg.group_id) AS group_count,
            COUNT(DISTINCT spi_as_package.package_item_id) AS package_item_count,
            COUNT(DISTINCT spi_as_sub.package_item_id) AS package_reference_count,
            COUNT(DISTINCT cpi.customer_package_item_id) AS customer_package_reference_count
        FROM services s
        LEFT JOIN order_details od ON od.service_id = s.service_id
        LEFT JOIN services child ON child.main_service_id = s.service_id
        LEFT JOIN service_groups sg ON sg.main_service_id = s.service_id
        LEFT JOIN service_package_items spi_as_package ON spi_as_package.package_service_id = s.service_id
        LEFT JOIN service_package_items spi_as_sub ON spi_as_sub.sub_service_id = s.service_id
        LEFT JOIN customer_package_items cpi ON cpi.sub_service_id = s.service_id
        WHERE s.service_id = ?
        GROUP BY s.service_id, s.service_type
        LIMIT 1
    ");
    $existingStmt->bind_param('i', $serviceId);
    $existingStmt->execute();
    $existingService = $existingStmt->get_result()->fetch_assoc();
    $existingStmt->close();

    if (!$existingService) {
        redirect_with_flash('../pages/services.php', 'error', localized_flash_message('ไม่พบบริการ', 'Service was not found.'));
    }

    $serviceSnapshotStmt = db_prepare($conn, "
        SELECT
            service_id,
            service_name,
            service_type,
            category_id,
            main_service_id,
            group_id,
            package_vehicle_scope,
            is_quick_service,
            price,
            description,
            is_active
        FROM services
        WHERE service_id = ?
        LIMIT 1
    ");
    $serviceSnapshotStmt->bind_param('i', $serviceId);
    $serviceSnapshotStmt->execute();
    $serviceSnapshot = $serviceSnapshotStmt->get_result()->fetch_assoc() ?: array();
    $serviceSnapshotStmt->close();
    $beforeServiceSnapshot = array(
        'service_name' => (string) ($serviceSnapshot['service_name'] ?? ''),
        'service_type' => (string) ($serviceSnapshot['service_type'] ?? ''),
        'category_id' => (int) ($serviceSnapshot['category_id'] ?? 0),
        'main_service_id' => (int) ($serviceSnapshot['main_service_id'] ?? 0),
        'group_id' => (int) ($serviceSnapshot['group_id'] ?? 0),
        'package_vehicle_scope' => (string) ($serviceSnapshot['package_vehicle_scope'] ?? ''),
        'is_quick_service' => (int) ($serviceSnapshot['is_quick_service'] ?? 0),
        'price' => (float) ($serviceSnapshot['price'] ?? 0),
        'description' => (string) ($serviceSnapshot['description'] ?? ''),
        'is_active' => (int) ($serviceSnapshot['is_active'] ?? 0),
        'package_items' => service_package_purchase_snapshot($conn, $serviceId),
    );

    if ((string) ($existingService['service_type'] ?? 'sub_service') !== $serviceType) {
        if ((int) ($existingService['usage_count'] ?? 0) > 0) {
            redirect_with_flash($redirectPath, 'error', localized_flash_message('บริการที่มีประวัติการใช้งานแล้วไม่สามารถเปลี่ยนประเภทได้', 'Used services cannot change type.'), $oldInput);
        }

        if (
            (string) ($existingService['service_type'] ?? '') === 'main_service'
            && ((int) ($existingService['child_service_count'] ?? 0) > 0 || (int) ($existingService['group_count'] ?? 0) > 0)
        ) {
            redirect_with_flash($redirectPath, 'error', localized_flash_message('บริการหลักนี้ยังมีบริการย่อยหรือกลุ่มบริการที่ผูกอยู่ จึงไม่สามารถเปลี่ยนประเภทได้', 'This main service still has linked sub services or groups and cannot change type.'), $oldInput);
        }

        if (
            (string) ($existingService['service_type'] ?? '') === 'sub_service'
            && ((int) ($existingService['package_reference_count'] ?? 0) > 0 || (int) ($existingService['customer_package_reference_count'] ?? 0) > 0)
        ) {
            $packageBlockers = service_sub_service_package_blockers($conn, $serviceId ?: 0);
            redirect_with_flash($redirectPath, 'error', service_sub_service_package_blocker_flash($packageBlockers, 'change_type'), $oldInput);
        }
    }
}

$categoryName = (string) ($selectedCategory['category_name'] ?? '');

$conn->begin_transaction();

try {
    if ($serviceId) {
        $stmt = db_prepare($conn, "
            UPDATE services
            SET service_name = ?,
                service_type = ?,
                category = ?,
                category_id = ?,
                main_service_id = NULLIF(?, 0),
                group_id = NULLIF(?, 0),
                package_vehicle_scope = ?,
                is_quick_service = ?,
                price = ?,
                duration_minutes = 0,
                description = ?,
                is_active = ?
            WHERE service_id = ?
        ");
        $stmt->bind_param(
            'sssiiisidsii',
            $serviceName,
            $serviceType,
            $categoryName,
            $categoryId,
            $mainServiceIdValue,
            $groupIdValue,
            $packageVehicleScope,
            $isQuickService,
            $price,
            $description,
            $isActive,
            $serviceId
        );
        $stmt->execute();
        $stmt->close();
    } else {
        $stmt = db_prepare($conn, "
            INSERT INTO services (service_name, service_type, category, category_id, main_service_id, group_id, package_vehicle_scope, is_quick_service, price, duration_minutes, description, is_active)
            VALUES (?, ?, ?, ?, NULLIF(?, 0), NULLIF(?, 0), ?, ?, ?, 0, ?, ?)
        ");
        $stmt->bind_param(
            'sssiiisidsi',
            $serviceName,
            $serviceType,
            $categoryName,
            $categoryId,
            $mainServiceIdValue,
            $groupIdValue,
            $packageVehicleScope,
            $isQuickService,
            $price,
            $description,
            $isActive
        );
        $stmt->execute();
        $serviceId = (int) $conn->insert_id;
        $stmt->close();
    }

    if ($serviceType === 'main_service') {
        $updateGroupsStmt = db_prepare($conn, "
            UPDATE service_groups
            SET category_id = ?
            WHERE main_service_id = ?
        ");
        $updateGroupsStmt->bind_param('ii', $categoryId, $serviceId);
        $updateGroupsStmt->execute();
        $updateGroupsStmt->close();

        $updateChildrenStmt = db_prepare($conn, "
            UPDATE services
            SET category = ?,
                category_id = ?
            WHERE main_service_id = ?
        ");
        $updateChildrenStmt->bind_param('sii', $categoryName, $categoryId, $serviceId);
        $updateChildrenStmt->execute();
        $updateChildrenStmt->close();
    }

    if ($serviceType === 'package') {
        service_save_package_items($conn, $serviceId, $normalizedPackageCounts);
    } else {
        $deletePackageItemsStmt = db_prepare($conn, "
            DELETE FROM service_package_items
            WHERE package_service_id = ?
        ");
        $deletePackageItemsStmt->bind_param('i', $serviceId);
        $deletePackageItemsStmt->execute();
        $deletePackageItemsStmt->close();
    }

    $afterServiceSnapshot = array(
        'service_name' => $serviceName,
        'service_type' => $serviceType,
        'category_id' => $categoryId,
        'main_service_id' => $mainServiceIdValue,
        'group_id' => $groupIdValue,
        'package_vehicle_scope' => $packageVehicleScope,
        'is_quick_service' => $isQuickService,
        'price' => $price,
        'description' => $description,
        'is_active' => $isActive,
        'package_items' => $serviceType === 'package' ? service_package_purchase_snapshot($conn, $serviceId) : array(),
    );
    $serviceDiff = audit_diff_assoc($beforeServiceSnapshot, $afterServiceSnapshot);

    if ($existingService) {
        if (!empty($serviceDiff['after'])) {
            audit_log($conn, array(
                'module_key' => 'service',
                'action_key' => 'update',
                'entity_type' => 'service',
                'entity_id' => $serviceId,
                'message' => 'Service updated.',
                'before' => $serviceDiff['before'],
                'after' => $serviceDiff['after'],
            ));
        }
    } else {
        audit_log($conn, array(
            'module_key' => 'service',
            'action_key' => 'create',
            'entity_type' => 'service',
            'entity_id' => $serviceId,
            'message' => 'Service created.',
            'after' => $afterServiceSnapshot,
        ));
    }

    $conn->commit();

    redirect_with_flash(
        '../pages/' . $returnTo,
        'success',
        $existingService
            ? localized_flash_message('อัปเดตบริการเรียบร้อยแล้ว', 'Service updated.')
            : localized_flash_message('เพิ่มบริการเรียบร้อยแล้ว', 'Service added.')
    );
} catch (Throwable $exception) {
    $conn->rollback();
    redirect_with_flash($redirectPath, 'error', localized_flash_message('บันทึกบริการไม่สำเร็จ', 'Service was not saved.'), $oldInput);
}
