<?php
session_start();
require_once "db.php";

if (!isset($_SESSION['user'])) {
    header("Location: index.php"); exit;
}

/* ===== CSRF ===== */
if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf_token'] ?? '')) {
    header("Location: profile.php?error=Invalid CSRF token."); exit;
}

$user          = $_SESSION['user'];
$staff_number  = $user['staff_number'] ?? '';
$currentUserId = (int)($user['id'] ?? 0);

/* ===== Helpers ===== */
function column_exists(mysqli $conn, string $table, string $column): bool {
    $sql = "SELECT COUNT(*) AS c
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param('ss', $table, $column);
    $stmt->execute();
    $res = $stmt->get_result()->fetch_assoc();
    $stmt->close();
    return (int)($res['c'] ?? 0) > 0;
}
function table_exists(mysqli $conn, string $table): bool {
    $sql = "SELECT COUNT(*) AS c
            FROM INFORMATION_SCHEMA.TABLES
            WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param('s', $table);
    $stmt->execute();
    $res = $stmt->get_result()->fetch_assoc();
    $stmt->close();
    return (int)($res['c'] ?? 0) > 0;
}
/* Detect active column name ('is_active' | 'active' | null) */
function active_col(mysqli $conn, string $table): ?string {
    if (!table_exists($conn,$table)) return null;
    if (column_exists($conn,$table,'is_active')) return 'is_active';
    if (column_exists($conn,$table,'active'))    return 'active';
    return null;
}
function normalize_msisdn(string $s): string {
    $s = trim($s);
    if ($s === '') return '';
    $hasPlus = ($s[0] === '+');
    $digits  = preg_replace('/\D+/', '', $s);
    // +60xxxxxxxxx -> 0xxxxxxxxx (local)
    if ($hasPlus && strpos($digits, '60') === 0) {
        $digits = '0' . substr($digits, 2);
    }
    return $digits;
}
function clamp_str(string $s, int $max): string {
    $s = trim($s);
    return mb_substr($s, 0, $max, 'UTF-8');
}

/* ===== Read & sanitize inputs (user-editable only) ===== */
$full_name   = clamp_str($_POST['full_name'] ?? '', 100);
$email       = clamp_str($_POST['email'] ?? '', 100);
$phone_raw   = $_POST['phone'] ?? '';
$home_raw    = $_POST['home_phone'] ?? '';
$race        = clamp_str($_POST['race'] ?? '', 30);
$job_title   = clamp_str($_POST['job_title'] ?? '', 100);
$address     = clamp_str($_POST['address'] ?? '', 255);
$postcode    = clamp_str($_POST['postcode'] ?? '', 10);
$waris_name  = clamp_str($_POST['waris_name'] ?? '', 150);
$waris_phone_raw = $_POST['waris_phone'] ?? '';

$phone       = normalize_msisdn($phone_raw);
$home_phone  = normalize_msisdn($home_raw);
$waris_phone = $waris_phone_raw !== '' ? normalize_msisdn($waris_phone_raw) : '';

/* ===== Detect model (hierarki baharu vs legacy) ===== */
$has_tbl_districts = table_exists($conn,'districts');
$has_tbl_worklocs  = table_exists($conn,'work_locations');
$has_district_id   = column_exists($conn,'members','district_id');
$has_workloc_id    = column_exists($conn,'members','work_location_id');
$usingHierarchy    = ($has_tbl_districts && $has_district_id) || ($has_tbl_worklocs && $has_workloc_id);

/* ===== Fetch current member (untuk guard & authoritative location) ===== */
$memberId = 0;
$currentLocation = '';
$currentDistrictId = 0;
$currentWorklocId  = 0;

$sqlCur = "SELECT id, location"
        . ($has_district_id ? ", district_id" : "")
        . ($has_workloc_id  ? ", work_location_id" : "")
        . " FROM members WHERE staff_number = ? LIMIT 1";
$cur = $conn->prepare($sqlCur);
$cur->bind_param('s', $staff_number);
$cur->execute();
$cr = $cur->get_result();
if ($cr && $row = $cr->fetch_assoc()) {
    $memberId         = (int)$row['id'];
    $currentLocation  = (string)($row['location'] ?? '');
    $currentDistrictId= (int)($row['district_id'] ?? 0);
    $currentWorklocId = (int)($row['work_location_id'] ?? 0);
}
$cur->close();
if ($memberId <= 0) {
    header("Location: profile.php?error=Member record not found."); exit;
}

/* ===== Build authoritative $location (user cannot change district/work location) ===== */
$authoritativeLocation = $currentLocation; // default fallback

if ($usingHierarchy) {
    // Jika ada work_location_id → guna nama work location; kalau tak ada, guna nama district
    if ($has_tbl_worklocs && $has_workloc_id && $currentWorklocId > 0) {
        $s = $conn->prepare("SELECT name FROM work_locations WHERE id=? LIMIT 1");
        if ($s) {
            $s->bind_param('i', $currentWorklocId);
            $s->execute();
            $authoritativeLocation = (string)($s->get_result()->fetch_assoc()['name'] ?? $currentLocation);
            $s->close();
        }
    } elseif ($has_tbl_districts && $has_district_id && $currentDistrictId > 0) {
        $s = $conn->prepare("SELECT name FROM districts WHERE id=? LIMIT 1");
        if ($s) {
            $s->bind_param('i', $currentDistrictId);
            $s->execute();
            $authoritativeLocation = (string)($s->get_result()->fetch_assoc()['name'] ?? $currentLocation);
            $s->close();
        }
    }
}

/* ===== Basic validations ===== */
$required = ['full_name','email','phone','race','address','postcode','job_title'];
// Dalam legacy mode, 'location' masih diperlukan dari user
if (!$usingHierarchy) $required[] = 'location';
$missing = [];
foreach ($required as $k) {
    $v = $$k;
    if ($v === '') $missing[] = $k;
}
if ($missing) {
    header("Location: profile.php?error=Please fill in all required fields."); exit;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    header("Location: profile.php?error=Invalid email format."); exit;
}
$allowedRaces = ['Malay','Chinese','Indian','Bumiputera','Others'];
if (!in_array($race, $allowedRaces, true)) {
    header("Location: profile.php?error=Invalid race selection."); exit;
}
if (!preg_match('/^\d{5}$/', $postcode)) {
    header("Location: profile.php?error=Invalid postcode. Use 5 digits."); exit;
}

/* ===== Location validation =====
 * - Hierarki baharu: abaikan POST & pakai $authoritativeLocation (tiada validasi ke 'locations')
 * - Legacy: validasi terhadap jadual 'locations' (hanya active ATAU nilai semasa)
 */
if ($usingHierarchy) {
    $location = $authoritativeLocation; // paksa nilai
} else {
    $location = clamp_str($_POST['location'] ?? '', 100);
    $locActive = active_col($conn,'locations'); // 'active' atau 'is_active' atau null
    if (table_exists($conn,'locations')) {
        $okLocation = false;
        if ($locActive) {
            $q = $conn->prepare("SELECT $locActive AS a FROM locations WHERE name=? LIMIT 1");
            $q->bind_param('s', $location);
            $q->execute();
            $rs = $q->get_result();
            if ($rs && ($r = $rs->fetch_assoc())) {
                $okLocation = ((int)$r['a'] === 1) || ($location === $currentLocation);
            } else {
                // Not found in master → hanya benarkan jika sama dgn nilai yang sudah disimpan
                $okLocation = ($location === $currentLocation);
            }
            $q->close();
        } else {
            // Tiada active flag → hanya perlu wujud; kalau tiada, benarkan jika sama dgn nilai semasa
            $q = $conn->prepare("SELECT 1 FROM locations WHERE name=? LIMIT 1");
            $q->bind_param('s', $location);
            $q->execute(); $q->store_result();
            $okLocation = ($q->num_rows === 1) || ($location === $currentLocation);
            $q->close();
        }
        if (!$okLocation) {
            header("Location: profile.php?error=Invalid location."); exit;
        }
    }
}

/* ===== Validate job_title if master exists (and has active rows) ===== */
$jtActive = active_col($conn,'job_titles');
if (table_exists($conn,'job_titles')) {
    $hasActiveRows = false;
    if ($jtActive) {
        $cnt = 0;
        $q = $conn->query("SELECT COUNT(*) AS c FROM job_titles WHERE COALESCE($jtActive,1)=1");
        if ($q && ($r = $q->fetch_assoc())) $cnt = (int)$r['c'];
        $hasActiveRows = ($cnt > 0);
    }
    if ($jtActive && $hasActiveRows) {
        $chk = $conn->prepare("SELECT 1 FROM job_titles WHERE name=? AND COALESCE($jtActive,1)=1 LIMIT 1");
        $chk->bind_param('s', $job_title);
        $chk->execute(); $chk->store_result();
        if ($chk->num_rows === 0) {
            $chk->close();
            header("Location: profile.php?error=Invalid job title. Please contact admin to add it."); exit;
        }
        $chk->close();
    }
}

/* ===== Check duplicate email (unique across members, excluding self) ===== */
$dup = $conn->prepare("SELECT id FROM members WHERE email = ? AND staff_number != ? LIMIT 1");
$dup->bind_param("ss", $email, $staff_number);
$dup->execute(); $dup->store_result();
if ($dup->num_rows > 0) { $dup->close(); header("Location: profile.php?error=Email already used by another account."); exit; }
$dup->close();

/* ===== Dynamic UPDATE (only user-allowed fields) =====
   IMPORTANT: tiada update pada district_id / work_location_id / role / status / exco_* di sini. */
$has_waris_name  = column_exists($conn, 'members', 'waris_name');
$has_waris_phone = column_exists($conn, 'members', 'waris_phone');
$has_home_phone  = column_exists($conn, 'members', 'home_phone');
$has_address     = column_exists($conn, 'members', 'address');
$has_postcode    = column_exists($conn, 'members', 'postcode');
$has_job_title   = column_exists($conn, 'members', 'job_title');

$fields = [
    "full_name = ?",
    "email = ?",
    "phone = ?",
    "race = ?",
    "location = ?"
];
$params = [$full_name, $email, $phone, $race, $location];
$types  = "sssss";

if ($has_home_phone) {  $fields[] = "home_phone = ?"; $params[] = $home_phone; $types .= "s"; }
if ($has_address)    {  $fields[] = "address = ?";     $params[] = $address;    $types .= "s"; }
if ($has_postcode)   {  $fields[] = "postcode = ?";    $params[] = $postcode;   $types .= "s"; }
if ($has_job_title)  {  $fields[] = "job_title = ?";   $params[] = $job_title;  $types .= "s"; }

if ($has_waris_name)  { $fields[] = "waris_name = ?";  $params[] = $waris_name;  $types .= "s"; }
if ($has_waris_phone) { $fields[] = "waris_phone = ?"; $params[] = $waris_phone; $types .= "s"; }

$sql = "UPDATE members SET " . implode(", ", $fields) . " WHERE staff_number = ?";
$params[] = $staff_number; $types .= "s";

$update = $conn->prepare($sql);
if (!$update) {
    header("Location: profile.php?error=Failed to prepare update."); exit;
}
$update->bind_param($types, ...$params);

if ($update->execute()) {
    $update->close();

    /* ===== Audit log (best effort) ===== */
    if (table_exists($conn, 'audit_logs')) {
        // Gunakan schema lazim (admin_id, member_id, action, timestamp)
        $audit = $conn->prepare("INSERT INTO audit_logs (admin_id, member_id, action, timestamp) VALUES (?, ?, 'Updated member profile', NOW())");
        if ($audit) {
            $audit->bind_param('ii', $currentUserId, $memberId);
            $audit->execute();
            $audit->close();
        }
    }

    /* ===== Refresh session display info ===== */
    $_SESSION['user']['name']  = $full_name;
    $_SESSION['user']['email'] = $email;

    header("Location: profile.php?success=Profile updated successfully."); exit;
} else {
    $err = $conn->error;
    $update->close();
    header("Location: profile.php?error=Failed to update profile. ".$err); exit;
}
