<?php
declare(strict_types=1);

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

require_permission($conn, 'employees');

process_post_only_or_redirect('../pages/employees.php');

$employeeId = filter_input(INPUT_POST, 'employee_id', FILTER_VALIDATE_INT);
$filterPositionId = filter_input(INPUT_POST, 'filter_position_id', FILTER_VALIDATE_INT);
$name = trim((string) ($_POST['name'] ?? ''));
$phone = trim((string) ($_POST['phone'] ?? ''));
$username = trim((string) ($_POST['username'] ?? ''));
$password = (string) ($_POST['password'] ?? '');
$positionId = filter_input(INPUT_POST, 'position_id', FILTER_VALIDATE_INT);
$branchScope = (string) ($_POST['branch_scope'] ?? 'assigned');
$defaultStartPage = normalize_auth_default_start_page((string) ($_POST['default_start_page'] ?? ''));
$rawBranchNames = array_map('strval', (array) ($_POST['branch_names'] ?? array()));
$branchNames = normalized_branch_options($rawBranchNames);
$availableBranchNames = service_branches($conn, true);
$branchNames = array_values(array_intersect($branchNames, $availableBranchNames));
$isActive = isset($_POST['is_active']) ? 1 : 0;
$currentUser = auth_current_user($conn);
$listPath = '../pages/employees.php' . ($filterPositionId ? '?filter_position_id=' . $filterPositionId : '');
$formQuery = array('show_form' => 1);
if ($employeeId) {
    $formQuery['employee_id'] = $employeeId;
}
if ($filterPositionId) {
    $formQuery['filter_position_id'] = $filterPositionId;
}
$formPath = '../pages/employees.php?' . http_build_query($formQuery);

if ($name === '' || $username === '' || !$positionId) {
    redirect_with_flash($formPath, 'error', localized_flash_message('กรุณาระบุชื่อพนักงาน ชื่อผู้ใช้ และตำแหน่ง', 'Employee name, username and position are required.'), $_POST);
}

if (!$employeeId && $password === '') {
    redirect_with_flash($formPath, 'error', localized_flash_message('พนักงานใหม่ต้องกำหนดรหัสผ่าน', 'Password is required for new employees.'), $_POST);
}

if (!in_array($branchScope, array('all', 'assigned'), true)) {
    $branchScope = 'assigned';
}

if ($currentUser && $employeeId && (int) $currentUser['employee_id'] === $employeeId && $isActive === 0) {
    redirect_with_flash($formPath, 'error', localized_flash_message('คุณไม่สามารถปิดใช้งานบัญชีของตัวเองได้', 'You cannot deactivate your own account.'), $_POST);
}

$positionStmt = db_prepare($conn, "
    SELECT position_name, permissions
    FROM positions
    WHERE position_id = ? AND is_active = 1
    LIMIT 1
");
$positionStmt->bind_param('i', $positionId);
$positionStmt->execute();
$position = $positionStmt->get_result()->fetch_assoc();
$positionStmt->close();

if (!$position) {
    redirect_with_flash($formPath, 'error', localized_flash_message('ตำแหน่งที่เลือกไม่พร้อมใช้งาน', 'Selected position is not available.'), $_POST);
}

$positionPermissions = auth_user_permissions(array('permissions' => (string) ($position['permissions'] ?? '[]')));
if ($defaultStartPage !== '' && !auth_permissions_allow_start_page($positionPermissions, $defaultStartPage)) {
    redirect_with_flash($formPath, 'error', localized_flash_message('หน้าเริ่มต้นที่เลือกไม่พร้อมใช้งานสำหรับตำแหน่งนี้', 'Selected default start page is not available for this position.'), $_POST);
}

$beforeEmployee = array();
$beforeBranches = array();
if ($employeeId) {
    $employeeSnapshotStmt = db_prepare($conn, "
        SELECT employee_id, name, phone, username, position_id, position, branch_scope, default_start_page, is_active
        FROM employees
        WHERE employee_id = ?
        LIMIT 1
    ");
    $employeeSnapshotStmt->bind_param('i', $employeeId);
    $employeeSnapshotStmt->execute();
    $employeeSnapshot = $employeeSnapshotStmt->get_result()->fetch_assoc();
    $employeeSnapshotStmt->close();

    if (!$employeeSnapshot) {
        redirect_with_flash($listPath, 'error', localized_flash_message('ไม่พบพนักงาน', 'Employee was not found.'));
    }

    $beforeEmployee = array(
        'name' => (string) ($employeeSnapshot['name'] ?? ''),
        'phone' => (string) ($employeeSnapshot['phone'] ?? ''),
        'username' => (string) ($employeeSnapshot['username'] ?? ''),
        'position_id' => (int) ($employeeSnapshot['position_id'] ?? 0),
        'position_name' => (string) ($employeeSnapshot['position'] ?? ''),
        'branch_scope' => (string) ($employeeSnapshot['branch_scope'] ?? ''),
        'default_start_page' => (string) ($employeeSnapshot['default_start_page'] ?? ''),
        'is_active' => (int) ($employeeSnapshot['is_active'] ?? 0),
    );

    $branchSnapshotStmt = db_prepare($conn, "
        SELECT branch_name
        FROM employee_branch_access
        WHERE employee_id = ?
        ORDER BY branch_name ASC
    ");
    $branchSnapshotStmt->bind_param('i', $employeeId);
    $branchSnapshotStmt->execute();
    $branchResult = $branchSnapshotStmt->get_result();
    while ($row = $branchResult->fetch_assoc()) {
        $beforeBranches[] = (string) ($row['branch_name'] ?? '');
    }
    $branchSnapshotStmt->close();
}

$conn->begin_transaction();

try {
    if ($employeeId) {
        if ($password !== '') {
            $passwordHash = password_hash($password, PASSWORD_DEFAULT);
            $stmt = db_prepare($conn, "
                UPDATE employees
                SET name = ?, phone = ?, username = ?, password_hash = ?, position_id = ?, position = ?, branch_scope = ?, default_start_page = NULLIF(?, ''), is_active = ?
                WHERE employee_id = ?
            ");
            $positionName = (string) $position['position_name'];
            $stmt->bind_param('ssssisssii', $name, $phone, $username, $passwordHash, $positionId, $positionName, $branchScope, $defaultStartPage, $isActive, $employeeId);
        } else {
            $stmt = db_prepare($conn, "
                UPDATE employees
                SET name = ?, phone = ?, username = ?, position_id = ?, position = ?, branch_scope = ?, default_start_page = NULLIF(?, ''), is_active = ?
                WHERE employee_id = ?
            ");
            $positionName = (string) $position['position_name'];
            $stmt->bind_param('sssisssii', $name, $phone, $username, $positionId, $positionName, $branchScope, $defaultStartPage, $isActive, $employeeId);
        }

        $stmt->execute();
        $stmt->close();
    } else {
        $passwordHash = password_hash($password, PASSWORD_DEFAULT);
        $stmt = db_prepare($conn, "
            INSERT INTO employees (position_id, name, position, phone, username, password_hash, branch_scope, default_start_page, is_active)
            VALUES (?, ?, ?, ?, ?, ?, ?, NULLIF(?, ''), ?)
        ");
        $positionName = (string) $position['position_name'];
        $stmt->bind_param('isssssssi', $positionId, $name, $positionName, $phone, $username, $passwordHash, $branchScope, $defaultStartPage, $isActive);
        $stmt->execute();
        $employeeId = (int) $conn->insert_id;
        $stmt->close();
    }

    $deleteStmt = db_prepare($conn, "
        DELETE FROM employee_branch_access
        WHERE employee_id = ?
    ");
    $deleteStmt->bind_param('i', $employeeId);
    $deleteStmt->execute();
    $deleteStmt->close();

    if ($branchScope === 'assigned' && !empty($branchNames)) {
        $branchStmt = db_prepare($conn, "
            INSERT INTO employee_branch_access (employee_id, branch_name)
            VALUES (?, ?)
        ");

        foreach ($branchNames as $branchName) {
            $branchStmt->bind_param('is', $employeeId, $branchName);
            $branchStmt->execute();
        }

        $branchStmt->close();
    }

    $afterEmployee = array(
        'name' => $name,
        'phone' => $phone,
        'username' => $username,
        'position_id' => $positionId,
        'position_name' => (string) $position['position_name'],
        'branch_scope' => $branchScope,
        'default_start_page' => $defaultStartPage,
        'is_active' => $isActive,
    );

    if ($employeeId && !empty($beforeEmployee)) {
        $employeeDiff = audit_diff_assoc($beforeEmployee, $afterEmployee);
        $employeeAction = ((int) ($beforeEmployee['is_active'] ?? 1) === 1 && $isActive === 0) ? 'disable' : 'update';

        if (!empty($employeeDiff['after'])) {
            audit_log($conn, array(
                'module_key' => 'employee',
                'action_key' => $employeeAction,
                'entity_type' => 'employee',
                'entity_id' => $employeeId,
                'message' => $employeeAction === 'disable' ? 'Employee account disabled.' : 'Employee account updated.',
                'before' => $employeeDiff['before'],
                'after' => $employeeDiff['after'],
            ));
        }
    } else {
        audit_log($conn, array(
            'module_key' => 'employee',
            'action_key' => 'create',
            'entity_type' => 'employee',
            'entity_id' => $employeeId,
            'message' => 'Employee account created.',
            'after' => $afterEmployee,
        ));
    }

    $branchDiff = audit_membership_diff($beforeBranches, $branchScope === 'assigned' ? $branchNames : array());
    if (!empty($branchDiff['added']) || !empty($branchDiff['removed']) || ($employeeId && (($beforeEmployee['branch_scope'] ?? '') !== $branchScope))) {
        audit_log($conn, array(
            'module_key' => 'employee',
            'action_key' => 'assign',
            'entity_type' => 'employee_branch_access',
            'entity_id' => $employeeId,
            'message' => 'Employee branch access updated.',
            'before' => array(
                'branch_scope' => (string) ($beforeEmployee['branch_scope'] ?? ''),
                'branches' => $beforeBranches,
            ),
            'after' => array(
                'branch_scope' => $branchScope,
                'branches' => $branchScope === 'assigned' ? $branchNames : array(),
            ),
            'meta' => $branchDiff,
        ));
    }

    $conn->commit();
    redirect_with_flash($listPath, 'success', localized_flash_message('บันทึกพนักงานเรียบร้อยแล้ว', 'Employee saved.'));
} catch (Throwable $exception) {
    process_handle_exception_and_redirect(
        $conn,
        $exception,
        'save_employee',
        $formPath,
        localized_flash_message('บันทึกพนักงานไม่สำเร็จ ชื่อผู้ใช้นี้อาจถูกใช้งานแล้ว', 'Employee was not saved. Username may already be in use.'),
        array(
            'employee_id' => (int) ($employeeId ?: 0),
            'position_id' => (int) ($positionId ?: 0),
            'branch_scope' => $branchScope,
            'is_active' => $isActive,
        ),
        $_POST
    );
}
