<?php
declare(strict_types=1);
require_once "db.php";
session_start();

if ($_SERVER["REQUEST_METHOD"] !== "POST") {
    header("Location: register.php");
    exit;
}

/* ---------------------------
   Helper: simpan OLD & FLASH
---------------------------- */
function store_old_from_post(array $overrides = []): void {
    $safe = array_intersect_key($_POST, [
        'full_name'    => 1,
        'staff_number' => 1,
        'ic_number'    => 1,
        'email'        => 1,
        'job_title'    => 1,
        'home_phone'   => 1,
        'phone'        => 1,
        'race'         => 1,
        'district_id'  => 1,   // UI sahaja; server akan override ikut locations
        'location'     => 1,
        'exco_auto'    => 1,
        'exco_select'  => 1,
        'waris_name'   => 1,
        'waris_phone'  => 1,
        'address'      => 1,
        'postcode'     => 1,
    ]);
    $_SESSION['old'] = array_map('trim', array_merge($safe, $overrides));
}
function flash_and_back(string $message, string $focus = '', array $highlight = [], ?string $code = null, array $oldOverrides = []): void {
    $_SESSION['flash'] = [
        'type'      => 'error',
        'message'   => $message,
        'focus'     => $focus,
        'highlight' => $highlight,
        'code'      => $code,
    ];
    if (!empty($oldOverrides)) store_old_from_post($oldOverrides); else store_old_from_post();
    header("Location: register.php");
    exit;
}

/* -----------------------------------------
   Helper: resolve Work Location -> district
------------------------------------------ */
function resolve_location_or_fail(mysqli $conn, string $location_name): array {
    $location_name = trim($location_name);
    if ($location_name === '') {
        flash_and_back('Invalid work location selected.', 'location', ['location']);
    }
    $stmt = $conn->prepare("SELECT id, name, district_id FROM locations WHERE name=? AND active=1 LIMIT 1");
    $stmt->bind_param("s", $location_name);
    $stmt->execute();
    $res = $stmt->get_result()->fetch_assoc();
    $stmt->close();

    if (!$res) {
        flash_and_back('Invalid work location selected.', 'location', ['location']);
    }
    $did = (int)$res['district_id'];
    if ($did <= 0) {
        flash_and_back('Selected location is not mapped to any district.', 'location', ['location']);
    }
    return [
        'location_id'   => (int)$res['id'],
        'location_name' => (string)$res['name'],
        'district_id'   => $did,
    ];
}

/* ---------------------------
   0) Trim & collect inputs
---------------------------- */
$full_name          = trim($_POST["full_name"] ?? '');
$staff_number       = trim($_POST["staff_number"] ?? '');
$ic_number_raw      = trim($_POST["ic_number"] ?? '');
$email              = trim($_POST["email"] ?? '');
$job_title          = trim($_POST["job_title"] ?? '');
$home_phone         = trim($_POST["home_phone"] ?? '');
$phone_raw          = trim($_POST["phone"] ?? '');
$race               = trim($_POST["race"] ?? '');
$district_id_input  = (int)($_POST["district_id"] ?? 0); // UI only; will be overridden
$location_name_in   = trim($_POST["location"] ?? '');

// EXCO UI values
$exco_auto_input    = trim($_POST["exco_auto"] ?? '');
$exco_select_in     = trim($_POST["exco_select"] ?? '');
$exco_member_id_in  = (int)($_POST["exco_member_id"] ?? 0); // legacy UI (tak digunakan)
$exco_select_id_in  = (int)($_POST["exco_select_id"] ?? 0);

$password           = $_POST["password"] ?? '';
$confirm_password   = $_POST["confirm_password"] ?? '';
$address            = trim($_POST["address"] ?? '');
$postcode           = trim($_POST["postcode"] ?? '');
$waris_name         = trim($_POST["waris_name"] ?? '');
$waris_phone        = trim($_POST["waris_phone"] ?? '');

// Acknowledge pengesahan potongan gaji (checkbox)
$acknowledge        = trim((string)($_POST['acknowledge'] ?? '0')) === '1' ? '1' : '0';

/* -----------------------------------------
   0.1) Normalize selected sensitive fields
------------------------------------------ */
$email = strtolower($email);
$staff_number = strtoupper(preg_replace('/\s+/', '', $staff_number));

// IC normalize -> ######-##-####
$ic_digits = preg_replace('/\D/', '', $ic_number_raw);
$ic_number = (strlen($ic_digits) === 12)
    ? substr($ic_digits, 0, 6) . '-' . substr($ic_digits, 6, 2) . '-' . substr($ic_digits, 8, 4)
    : $ic_number_raw;

/* -----------------------------------------
   0.2) Normalize & format MOBILE PHONE (MY)
------------------------------------------ */
$phone_digits = preg_replace('/\D/', '', $phone_raw);
$phone = $phone_raw;
if (strpos($phone_digits, '011') === 0) {
    if (strlen($phone_digits) === 11) {
        $phone = substr($phone_digits,0,3) . '-' . substr($phone_digits,3,4) . '-' . substr($phone_digits,7,4);
    }
} else {
    if (strlen($phone_digits) === 10 && preg_match('/^01\d/', $phone_digits)) {
        $phone = substr($phone_digits,0,3) . '-' . substr($phone_digits,3,7);
    }
}

/* ---------------------------
   1) Basic validations
---------------------------- */
$required_missing =
    !$full_name || !$staff_number || !$ic_number || !$email || !$job_title ||
    !$home_phone || !$phone_raw || !$race || !$location_name_in ||
    !$address || !$postcode || !$password;

if ($required_missing) {
    flash_and_back('Please fill in all required fields.', '', [], 'required', [
        'ic_number'    => $ic_number,
        'email'        => $email,
        'staff_number' => $staff_number,
        'phone'        => $phone,
    ]);
}

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    flash_and_back('Invalid email format.', 'email', ['email'], null, ['email' => $email]);
}

if ($password !== $confirm_password) {
    flash_and_back('Passwords do not match.', 'confirm_password', ['password','confirm_password']);
}

if (!preg_match('/^\d{6}-\d{2}-\d{4}$/', $ic_number)) {
    flash_and_back('IC format must be 123456-78-9012.', 'ic_number', ['ic_number'], null, ['ic_number' => $ic_number]);
}

// PHONE validation
$ok_phone = false;
if (strpos($phone_digits, '011') === 0) {
    $ok_phone = (strlen($phone_digits) === 11) && preg_match('/^011-\d{4}-\d{4}$/', $phone);
} else {
    $ok_phone = (strlen($phone_digits) === 10) && preg_match('/^01\d-\d{7}$/', $phone);
}
if (!$ok_phone) {
    flash_and_back('Invalid mobile number format. Example: 012-3456789 or 011-1234-5678', 'phone', ['phone'], null, [
        'phone' => $phone,
    ]);
}

if (!preg_match('/^[A-Za-z0-9]{5,}$/', $staff_number)) {
    flash_and_back('Staff number must be alphanumeric, min 5 chars.', 'staff_number', ['staff_number'], null, ['staff_number' => $staff_number]);
}

if ($waris_phone !== '' && !preg_match('/^[0-9+\-\s]{7,20}$/', $waris_phone)) {
    flash_and_back('Invalid guardian phone format.', 'waris_phone', ['waris_phone']);
}

/* -------------------------------------------------------
   1.1) Resolve District + Location mapping (server-truth)
   - Abaikan district dari form; derive dari jadual locations
-------------------------------------------------------- */
$loc = resolve_location_or_fail($conn, $location_name_in);
$location_id   = $loc['location_id'];
$location_name = $loc['location_name'];
$district_id   = $loc['district_id'];

// Jika user pilih district di UI yang tak sama, kita override & teruskan
if ($district_id_input && $district_id_input !== $district_id) {
    // Letak dalam OLD untuk makluman UI (optional)
    $_SESSION['old']['district_id'] = $district_id;
}

/* ------------------------------------------------
   1.2) Recompute EXCO (Pencadang) & validate Penyokong
------------------------------------------------- */
$assigned_exco_id = 0;
$exco_auto        = '';
$stmt = $conn->prepare("
    SELECT id, full_name
    FROM members
    WHERE role='exco' AND COALESCE(status,1)=1 AND district_id=?
    ORDER BY id ASC LIMIT 1
");
$stmt->bind_param("i", $district_id);
$stmt->execute();
$res = $stmt->get_result();
if ($row = $res->fetch_assoc()) {
    $assigned_exco_id = (int)$row['id'];
    $exco_auto        = (string)$row['full_name'];
}
$stmt->close();

if ($assigned_exco_id <= 0) {
    flash_and_back('Tiada EXCO (Pencadang) untuk daerah dipilih.', 'district_id', ['district_id']);
}
if ($exco_auto === '') $exco_auto = $exco_auto_input ?: 'N/A';

// Validasi EXCO (Penyokong) global (mesti EXCO aktif, apa-apa district)
if ($exco_select_id_in <= 0) {
    flash_and_back('Please select an EXCO (Penyokong).', 'exco_select', ['exco_select']);
}
$assigned_ajk_id = 0;
$exco_select     = $exco_select_in;
$stmt = $conn->prepare("SELECT full_name FROM members WHERE id=? AND role='exco' AND COALESCE(status,1)=1 LIMIT 1");
$stmt->bind_param("i", $exco_select_id_in);
$stmt->execute();
$stmt->bind_result($supporter_name);
if ($stmt->fetch()) {
    $assigned_ajk_id = (int)$exco_select_id_in;
    $exco_select = $supporter_name ?: $exco_select;
}
$stmt->close();

if ($assigned_ajk_id <= 0) {
    flash_and_back('Selected EXCO (Penyokong) is not valid.', 'exco_select', ['exco_select']);
}

/* --------------------------------------
   2) Duplicate check (exclude temp_register)
--------------------------------------- */
$tables = ['members', 'pending_exco', 'pending_ajk'];
foreach ($tables as $table) {
    $chk = $conn->prepare("SELECT id FROM `$table` WHERE ic_number = ? OR staff_number = ? OR email = ? LIMIT 1");
    if (!$chk) { die("Prepare failed: ".$conn->error); }
    $chk->bind_param("sss", $ic_number, $staff_number, $email);
    $chk->execute();
    $chk->store_result();
    if ($chk->num_rows > 0) {
        $chk->close();
        flash_and_back('Staff number or email already exists.', 'staff_number', ['staff_number','email']);
    }
    $chk->close();
}

/* ----------------------------------------------------------------
   3) Helper: Try upload receipt (optional). Return path or null.
----------------------------------------------------------------- */
function try_upload_receipt_or_null(?string &$receipt_path_rel): void {
    $receipt_path_rel = null;
    if (!isset($_FILES["receipt"])) return;
    $err = $_FILES["receipt"]["error"] ?? UPLOAD_ERR_NO_FILE;
    if ($err === UPLOAD_ERR_NO_FILE) return;
    if ($err !== UPLOAD_ERR_OK) {
        flash_and_back('Failed to upload receipt.', 'receipt', ['receipt']);
    }

    $maxBytes    = 5 * 1024 * 1024; // 5MB
    $allowedExt  = ['pdf','jpg','jpeg','png'];
    $allowedMime = ['application/pdf','image/jpeg','image/png'];

    $origName = (string)($_FILES["receipt"]["name"] ?? '');
    $tmpPath  = (string)($_FILES["receipt"]["tmp_name"] ?? '');
    $size     = (int)   ($_FILES["receipt"]["size"] ?? 0);
    $ext      = strtolower(pathinfo($origName, PATHINFO_EXTENSION));

    if ($size <= 0 || $size > $maxBytes) {
        flash_and_back('File too large (max 5MB).', 'receipt', ['receipt']);
    }
    if (!in_array($ext, $allowedExt, true)) {
        flash_and_back('Invalid file type. Only PDF, JPG, JPEG or PNG.', 'receipt', ['receipt']);
    }
    if (!is_uploaded_file($tmpPath)) {
        error_log("[DIS] upload tmp invalid: $tmpPath");
        flash_and_back('Invalid file content.', 'receipt', ['receipt']);
    }

    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime  = (string)$finfo->file($tmpPath);
    if (!in_array($mime, $allowedMime, true)) {
        error_log("[DIS] mime mismatch ext=$ext mime=$mime");
        flash_and_back('Invalid file content.', 'receipt', ['receipt']);
    }

    $fh = @fopen($tmpPath, 'rb');
    if ($fh) {
        $head = fread($fh, 8);
        fclose($fh);
        if ($ext === 'pdf'  && strpos($head, '%PDF') !== 0)                                { flash_and_back('Invalid file content.', 'receipt', ['receipt']); }
        if (in_array($ext, ['jpg','jpeg'], true) && substr($head,0,3) !== "\xFF\xD8\xFF") { flash_and_back('Invalid file content.', 'receipt', ['receipt']); }
        if ($ext === 'png' && $head !== "\x89PNG\x0D\x0A\x1A\x0A")                         { flash_and_back('Invalid file content.', 'receipt', ['receipt']); }
    }

    $uploadDirFs = __DIR__ . "/uploads";
    if (!is_dir($uploadDirFs)) {
        if (!@mkdir($uploadDirFs, 0755, true)) {
            error_log("[DIS] mkdir failed: $uploadDirFs");
            flash_and_back('Failed to upload receipt.', 'receipt', ['receipt']);
        }
        @file_put_contents($uploadDirFs.'/.htaccess', "Options -Indexes\nphp_flag engine off\nRemoveType .php .phtml .php3 .php4 .php5 .php7 .php8 .phps\n");
    }
    if (!is_writable($uploadDirFs)) {
        error_log("[DIS] not writable: $uploadDirFs");
        flash_and_back('Failed to upload receipt.', 'receipt', ['receipt']);
    }

    $filename  = sprintf('receipt_%s_%s.%s', bin2hex(random_bytes(6)), date('YmdHis'), $ext);
    $destFs  = $uploadDirFs . '/' . $filename;
    $destRel = "uploads/" . $filename;

    if (!@move_uploaded_file($tmpPath, $destFs)) {
        error_log("[DIS] move_uploaded_file failed: tmp=$tmpPath dest=$destFs");
        flash_and_back('Failed to upload receipt.', 'receipt', ['receipt']);
    }

    if (in_array($ext, ['jpg','jpeg','png'], true)) {
        if (@getimagesize($destFs) === false) {
            @unlink($destFs);
            error_log("[DIS] getimagesize failed on: $destFs");
            flash_and_back('Invalid file content.', 'receipt', ['receipt']);
        }
    }

    $receipt_path_rel = $destRel;
}

/* ---------------------------
   4) Hash the password
---------------------------- */
$password_hash = password_hash($password, PASSWORD_BCRYPT);

/* ============================================================
   5) FLOW BARU
      - DRAF (acknowledge != 1): RECEIPT WAJIB.
      - FINAL (acknowledge == 1): Insert pending_exco.
============================================================ */
if ($acknowledge !== '1') {
    // ====== DRAF: Resit WAJIB ======
    $receipt_to_save = null;

    // 1) Cuba upload baru (digalakkan pada submission pertama)
    try_upload_receipt_or_null($receipt_to_save);

    // 2) Jika tiada upload sekarang, cuba ambil resit draf sedia ada (sambung draf)
    if (!$receipt_to_save) {
        $sel = $conn->prepare("SELECT receipt FROM temp_register WHERE email=? OR staff_number=? LIMIT 1");
        $sel->bind_param("ss", $email, $staff_number);
        $sel->execute();
        $sel->bind_result($draft_receipt);
        if ($sel->fetch()) {
            $receipt_to_save = $draft_receipt ?: null;
        }
        $sel->close();
    }

    // 3) Jika masih tiada → wajibkan
    if (!$receipt_to_save) {
        flash_and_back('Receipt is required.', 'receipt', ['receipt'], 'required');
    }

    $conn->begin_transaction();

    // Cari draf sedia ada
    $sel = $conn->prepare("SELECT id FROM temp_register WHERE email=? OR staff_number=? LIMIT 1");
    $sel->bind_param("ss", $email, $staff_number);
    $sel->execute();
    $res = $sel->get_result();
    $existingId = null;
    if ($row = $res->fetch_assoc()) { $existingId = (int)$row['id']; }
    $sel->close();

    if ($existingId) {
        $upd = $conn->prepare("
            UPDATE temp_register SET
              full_name=?, staff_number=?, ic_number=?, email=?, job_title=?,
              home_phone=?, phone=?, race=?, district_id=?, location=?,
              assigned_exco_id=?, assigned_ajk_id=?,
              exco_auto=?, exco_select=?, password_hash=?, address=?, postcode=?,
              waris_name=?, waris_phone=?, receipt=?, ack_form=0, ack_date=NULL
            WHERE id=?");
        $upd->bind_param(
            "ssssssssisiissssssssi",
            $full_name, $staff_number, $ic_number, $email, $job_title,
            $home_phone, $phone, $race, $district_id, $location_name,
            $assigned_exco_id, $assigned_ajk_id,
            $exco_auto, $exco_select, $password_hash, $address, $postcode,
            $waris_name, $waris_phone, $receipt_to_save, $existingId
        );
        if (!$upd->execute()) {
            error_log("UPDATE temp_register failed: ".$upd->error);
            $conn->rollback();
            store_old_from_post([
                'ic_number'=>$ic_number,'email'=>$email,'staff_number'=>$staff_number,'phone'=>$phone,
                'district_id'=>$district_id,'location'=>$location_name,'exco_auto'=>$exco_auto,'exco_select'=>$exco_select,
            ]);
            flash_and_back('Server error (save draft failed). Please try again.');
        }
        $upd->close();
    } else {
        $ins = $conn->prepare("
            INSERT INTO temp_register
              (full_name, staff_number, ic_number, email, job_title, home_phone, phone, race,
               district_id, location, assigned_exco_id, assigned_ajk_id, exco_auto, exco_select,
               password_hash, address, postcode, waris_name, waris_phone, receipt,
               ack_form, ack_date, role, status, created_at)
            VALUES
              (?, ?, ?, ?, ?, ?, ?, ?,
               ?, ?, ?, ?, ?, ?,
               ?, ?, ?, ?, ?, ?,
               0, NULL, 'member', 0, NOW())
        ");
        $ins->bind_param(
            "ssssssssisiissssssss",
            $full_name, $staff_number, $ic_number, $email, $job_title, $home_phone, $phone, $race,
            $district_id, $location_name, $assigned_exco_id, $assigned_ajk_id, $exco_auto, $exco_select,
            $password_hash, $address, $postcode, $waris_name, $waris_phone, $receipt_to_save
        );
        if (!$ins->execute()) {
            error_log("INSERT temp_register failed: ".$ins->error);
            $conn->rollback();
            store_old_from_post([
                'ic_number'=>$ic_number,'email'=>$email,'staff_number'=>$staff_number,'phone'=>$phone,
                'district_id'=>$district_id,'location'=>$location_name,'exco_auto'=>$exco_auto,'exco_select'=>$exco_select,
            ]);
            flash_and_back('Server error (save draft failed). Please try again.');
        }
        $ins->close();
    }

    $conn->commit();

    // Ingatkan sesi untuk sambung
    $_SESSION['draft_email'] = $email;
    $_SESSION['draft_staff'] = $staff_number;

    unset($_SESSION['old']);
    $_SESSION['flash'] = [
        'type'    => 'success',
        'message' => 'Draft saved with receipt. Please review and tick salary deduction acknowledgement to submit.',
    ];

    $conn->close();
    // Pastikan pending_id lama tidak mengganggu aliran draf baru
    unset($_SESSION['pending_id']);
    // Flow: terus ke halaman pengesahan
    header("Location: acknowledge.php");
    exit;
}

/* ============================================================
   5B) FINAL: Pindahkan ke pending_exco (boleh guna resit sedia ada)
============================================================ */
$receipt_path_rel = null;
try_upload_receipt_or_null($receipt_path_rel);

if (!$receipt_path_rel) {
    $st = $conn->prepare("SELECT receipt FROM temp_register WHERE email=? OR staff_number=? LIMIT 1");
    $st->bind_param("ss", $email, $staff_number);
    $st->execute();
    $st->bind_result($draft_receipt);
    if ($st->fetch()) {
        $receipt_path_rel = $draft_receipt ?: null;
    }
    $st->close();

    if (!$receipt_path_rel) {
        // Secara logik patut ada (draf wajib), tapi guard untuk keselamatan.
        flash_and_back('Receipt is required.', 'receipt', ['receipt'], 'required');
    }
}

/* -------- Insert KE pending_exco (ACK = 1) + padam draf -------- */
$sql = "
    INSERT INTO pending_exco
      (full_name, staff_number, ic_number, email, job_title, home_phone, phone, race,
       district_id, location,
       assigned_exco_id, assigned_ajk_id,
       exco_auto, exco_select, password_hash, address, postcode, receipt,
       waris_name, waris_phone,
       ack_form, ack_date, role, status, created_at)
    VALUES
      (?, ?, ?, ?, ?, ?, ?, ?,
       ?, ?,
       ?, ?,
       ?, ?, ?, ?, ?, ?,
       ?, ?,
       1, NOW(), 'member', 0, NOW())
";
$stmt = $conn->prepare($sql);
if (!$stmt) {
    store_old_from_post([
        'ic_number'=>$ic_number,'email'=>$email,'staff_number'=>$staff_number,'phone'=>$phone,
        'district_id'=>$district_id,'location'=>$location_name,'exco_auto'=>$exco_auto,'exco_select'=>$exco_select,
    ]);
    flash_and_back('Server error (prepare failed). Please try again.');
}

$stmt->bind_param(
    "ssssssssisiissssssss",
    $full_name,
    $staff_number,
    $ic_number,
    $email,
    $job_title,
    $home_phone,
    $phone,
    $race,
    $district_id,
    $location_name,
    $assigned_exco_id,
    $assigned_ajk_id,
    $exco_auto,
    $exco_select,
    $password_hash,
    $address,
    $postcode,
    $receipt_path_rel,
    $waris_name,
    $waris_phone
);

if (!$stmt->execute()) {
    error_log("INSERT pending_exco failed: ".$stmt->error);
    store_old_from_post([
        'ic_number'=>$ic_number,'email'=>$email,'staff_number'=>$staff_number,'phone'=>$phone,
        'district_id'=>$district_id,'location'=>$location_name,'exco_auto'=>$exco_auto,'exco_select'=>$exco_select,
    ]);
    flash_and_back('Server error (execute failed). Please try again.');
}

/* ---------------------------
   6) Post-insert flow
---------------------------- */
$newId = $conn->insert_id;
$_SESSION['pending_id'] = $newId;

// Cleanup: padam draf jika wujud
$del = $conn->prepare("DELETE FROM temp_register WHERE email=? OR staff_number=?");
$del->bind_param("ss", $email, $staff_number);
$del->execute();
$del->close();

unset($_SESSION['old']);
$_SESSION['flash'] = [
    'type'    => 'success',
    'message' => 'Registration submitted. Waiting for EXCO approval.',
];

$stmt->close();
$conn->close();
header("Location: slip-permohonan.php?id={$newId}");
exit;
