<?php
declare(strict_types=1);

/* ---------------- Безпечні заголовки ---------------- */
header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: same-origin');

/* ---------------- Часовий пояс ---------------- */
date_default_timezone_set('Europe/Kyiv');

/* ---------------- Безпечні cookie до старту сесії ---------------- */
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
session_set_cookie_params([
    'lifetime' => 0,
    'path'     => '/',
    'domain'   => '',           // за потреби вкажіть свій домен
    'secure'   => $secure,
    'httponly' => true,
    'samesite' => 'Lax',
]);

session_start();
require_once __DIR__ . '/includes/db_connect.php';

/* ============================================================
   Хелпери для інфраструктури
   ============================================================ */
function column_exists(mysqli $conn, string $table, string $column): bool {
    $sql = "SELECT 1
            FROM information_schema.COLUMNS
            WHERE TABLE_SCHEMA = DATABASE()
              AND TABLE_NAME = ?
              AND COLUMN_NAME = ?
            LIMIT 1";
    $st = $conn->prepare($sql);
    if (!$st) { error_log("login.php: column_exists prepare failed: ".$conn->error); return false; }
    $st->bind_param('ss', $table, $column);
    $st->execute();
    $st->store_result();
    $ok = $st->num_rows > 0;
    $st->close();
    return $ok;
}
function ensure_column(mysqli $conn, string $table, string $column, string $definition): void {
    if (!column_exists($conn, $table, $column)) {
        $t = $conn->real_escape_string($table);
        $c = $conn->real_escape_string($column);
        $sql = "ALTER TABLE `{$t}` ADD COLUMN `{$c}` {$definition}";
        if (!$conn->query($sql)) {
            error_log("login.php: ensure_column failed for {$table}.{$column}: ".$conn->error);
        }
    }
}
/* У твоєму дампі ці колонки вже є, але хай буде "страховка" */
ensure_column($conn, 'users', 'last_login_at', 'DATETIME NULL DEFAULT NULL');
ensure_column($conn, 'users', 'last_login_ip', 'VARBINARY(16) NULL DEFAULT NULL'); // є в дампі

/* Якщо вже увійшов — на головну */
if (!empty($_SESSION['user_id'])) {
    header('Location: index.php');
    exit;
}

/* ---------------- Простий rate limit на спроби логіну ---------------- */
$MAX_ATTEMPTS = 5;   // у вікні $WINDOW_MIN хв
$WINDOW_MIN   = 15;
$LOCK_MIN     = 10;

$now_ts = time();
if (!isset($_SESSION['login_attempts']) || !is_array($_SESSION['login_attempts'])) {
    $_SESSION['login_attempts'] = [];
}
/* прибираємо застарілі спроби */
$_SESSION['login_attempts'] = array_values(array_filter(
    $_SESSION['login_attempts'],
    static fn(int $ts): bool => ($now_ts - $ts) < ($WINDOW_MIN * 60)
));

$locked_until = (int)($_SESSION['login_locked_until'] ?? 0);
$is_locked = $locked_until > $now_ts;

$generic_error = "Невірні дані для входу.";

/* постійний хеш для таймінг-захисту (bcrypt від 'dummy_password') */
const DUMMY_PW_HASH = '$2y$10$8V6H6o2p7D3aQ1vS8mZbZuhp9qZ0wVv3h2QX9jvC7d4c2Qzv4f3y2';

/* Визначення "реальної" IP-адреси користувача (IPv4/IPv6) */
function client_ip(): string {
    $candidates = [
        $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '',
        $_SERVER['HTTP_CLIENT_IP'] ?? '',
        $_SERVER['REMOTE_ADDR'] ?? '',
    ];
    foreach ($candidates as $raw) {
        if (!$raw) continue;
        // XFF може містити список
        foreach (explode(',', $raw) as $p) {
            $ip = trim($p);
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
                return $ip;
            }
        }
    }
    return '0.0.0.0';
}

$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if ($is_locked) {
        $error = "Забагато невдалих спроб. Спробуйте пізніше.";
    } else {
        $email    = strtolower(trim((string)($_POST['email'] ?? '')));
        $password = (string)($_POST['password'] ?? '');

        if (!filter_var($email, FILTER_VALIDATE_EMAIL) || $password === '') {
            $error = $generic_error;
        } else {
            $user = null;
            $stmt = $conn->prepare("SELECT id, full_name, email, password, active, role FROM users WHERE email = ?");
            if ($stmt) {
                $stmt->bind_param("s", $email);
                $stmt->execute();
                $result = $stmt->get_result();
                if ($result && $result->num_rows === 1) {
                    $user = $result->fetch_assoc();
                }
                $stmt->close();
            } else {
                error_log("login.php: SELECT user prepare failed: ".$conn->error);
                $error = "Тимчасова помилка. Спробуйте ще раз.";
            }

            $hashToVerify = $user['password'] ?? DUMMY_PW_HASH;
            $password_ok  = password_verify($password, $hashToVerify);
            $active_ok    = $user ? ((int)$user['active'] === 1) : false;

            if ($user && $password_ok && $active_ok) {
                session_regenerate_id(true);
                $_SESSION['user_id']   = (int)$user['id'];
                $_SESSION['full_name'] = (string)$user['full_name'];
                $_SESSION['role']      = (string)$user['role'];

                /* Оновлюємо last_login_at/last_login_ip в БД і кладемо час у сесію */
                $ip  = client_ip();
                $now = date('Y-m-d H:i:s');

                // Одна транзакція оновлення (NOW() з боку MySQL гарантує єдиний формат)
                if ($upd = $conn->prepare("UPDATE users SET last_login_at = NOW(), last_login_ip = INET6_ATON(?) WHERE id = ?")) {
                    $uid = (int)$user['id'];
                    $upd->bind_param("si", $ip, $uid);
                    $upd->execute();
                    if ($upd->errno) {
                        error_log("login.php: UPDATE last_login_* error: ".$upd->error);
                    }
                    $upd->close();
                } else {
                    // fallback без IP (раптом немає INET6_ATON або колонки)
                    error_log("login.php: UPDATE with IP prepare failed (".$conn->error."). Fallback to last_login_at only.");
                    if ($upd2 = $conn->prepare("UPDATE users SET last_login_at = ? WHERE id = ?")) {
                        $uid = (int)$user['id'];
                        $upd2->bind_param("si", $now, $uid);
                        $upd2->execute();
                        if ($upd2->errno) error_log("login.php: UPDATE last_login_at fallback error: ".$upd2->error);
                        $upd2->close();
                    }
                }

                // покладемо в сесію теж — якщо на головній читає з сесії
                $_SESSION['last_login_at'] = $now;

                // скинемо ліміт спроб
                $_SESSION['login_attempts'] = [];
                unset($_SESSION['login_locked_until']);

                header('Location: index.php');
                exit;
            }

            // невдала спроба
            $_SESSION['login_attempts'][] = $now_ts;
            if (count($_SESSION['login_attempts']) >= $MAX_ATTEMPTS) {
                $_SESSION['login_locked_until'] = $now_ts + $LOCK_MIN * 60;
            }
            $error = $generic_error;
        }
    }
}

/* Назва для хедера */
$header_title = 'Вхід';
?>
<!DOCTYPE html>
<html lang="uk">
<head>
    <meta charset="UTF-8">
    <title>Вхід до системи</title>
    <link rel="stylesheet" href="/assets/css/style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        :root{
          --brand-mint:#a3e8d3;
          --brand-mint-2:#92dec7;
          --brand-purple:#432755;
          --brand-purple-2:#3a244d;

          --ink:#1f2937;
          --muted:#4b5563;
          --card:#ffffff;
          --shadow: 0 10px 24px rgba(0,0,0,.08);
          --focus: rgba(67,39,85,.25);
        }

        .login-wrap{
          max-width:1100px;
          margin:16px auto;
          padding:16px;
        }
        .login-card{
          max-width:520px;
          margin:0 auto;
          background: var(--card);
          padding:18px;
          border-radius:16px;
          box-shadow: var(--shadow);
          border: 1px solid rgba(0,0,0,.06);
          text-align:left;
        }
        .login-head{
          text-align:center;
          margin-bottom: 10px;
        }
        .login-head h2{
          margin:0 0 8px 0;
          font-size:24px;
          font-weight:900;
          color: var(--brand-purple);
          letter-spacing:.2px;
        }
        .login-head p{
          margin:0;
          color: var(--muted);
          font-weight:700;
          font-size:14px;
        }

        label{
          display:block;
          margin-top:10px;
          margin-bottom:6px;
          color: var(--brand-purple);
          font-weight:900;
          font-size:14px;
        }

        input{
          width:100%;
          padding:12px 12px;
          margin:0;
          box-sizing:border-box;
          border:1px solid rgba(0,0,0,.14);
          border-radius:12px;
          outline:none;
          background:#fff;
          color: var(--ink);
          transition: border-color .15s ease, box-shadow .15s ease;
          font-size:16px;
        }
        input:focus{
          border-color: rgba(67,39,85,.35);
          box-shadow: 0 0 0 4px var(--focus);
        }

        .pw-wrap{ position:relative; }
        .toggle-pass{
          cursor:pointer;
          font-size: 13px;
          font-weight: 900;
          color: var(--brand-purple);
          padding: 6px 10px;
          border-radius: 9999px;
          background: rgba(163,232,211,.35);
          border: 1px solid rgba(67,39,85,.12);
          position:absolute;
          right:10px;
          top:50%;
          transform: translateY(-50%);
          user-select:none;
          transition: background .15s ease, transform .05s ease;
        }
        .toggle-pass:hover{ background: rgba(163,232,211,.50); }
        .toggle-pass:active{ transform: translateY(-50%) translateY(1px); }

        .helper{
          display:flex;
          justify-content:space-between;
          align-items:center;
          gap:10px;
          margin-top:10px;
          flex-wrap:wrap;
        }
        .muted{
          color: var(--muted);
          font-size: 13px;
          font-weight: 700;
        }

        .login-card button{
          margin-top: 12px;
          width:100%;
          background: var(--brand-purple);
          color:#fff;
          border:none;
          padding:12px 16px;
          border-radius:12px;
          cursor:pointer;
          font-weight:900;
          box-shadow: 0 10px 18px rgba(67,39,85,.16);
          transition: background .15s ease, transform .05s ease, box-shadow .15s ease;
        }
        .login-card button:hover{
          background: var(--brand-purple-2);
          box-shadow: 0 12px 22px rgba(67,39,85,.20);
        }
        .login-card button:active{ transform: translateY(1px); }

        .error{
          color:#b91c1c;
          margin: 10px 0;
          font-weight: 900;
          background: rgba(185,28,28,.08);
          border: 1px solid rgba(185,28,28,.20);
          padding: 10px 12px;
          border-radius: 14px;
        }

        .link-row{
          text-align:center;
          margin-top: 12px;
          color: var(--muted);
          font-weight: 700;
        }
        .link-row a{
          color: var(--brand-purple);
          font-weight: 900;
          text-decoration: underline;
        }
        .link-row a:hover{
          color: var(--brand-purple-2);
        }

        @media (max-width:600px){
          .login-wrap{ padding:12px; }
          .login-card{ padding:16px; border-radius:14px; }
          .toggle-pass{ right:8px; }
        }
    </style>
</head>
<body>

<?php require_once __DIR__ . '/includes/header.php'; ?>

<main class="login-wrap">
  <section class="login-card" aria-label="Вхід до системи">
    <div class="login-head">
      <h2>Вхід до системи</h2>
      <p>Використовуйте email та пароль вашого акаунту</p>
    </div>

    <?php if (!empty($error)): ?>
      <p class="error"><?= htmlspecialchars($error, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?></p>
    <?php elseif (!empty($locked_until) && $locked_until > time()): ?>
      <p class="error">Спроби тимчасово обмежені. Спробуйте пізніше.</p>
    <?php endif; ?>

    <form action="login.php" method="POST" autocomplete="on" novalidate>
      <label for="email">Email</label>
      <input id="email" type="email" name="email" inputmode="email" autocomplete="username" required>

      <label for="password">Пароль</label>
      <div class="pw-wrap">
        <input id="password" type="password" name="password" autocomplete="current-password" required>
        <span class="toggle-pass" id="togglePass" role="button" tabindex="0" aria-label="Показати або приховати пароль">Показати</span>
      </div>

      <div class="helper">
        <span class="muted">Порада: не використовуйте спільні паролі</span>
        <a href="/forgot_password.php" class="muted" style="text-decoration:underline; font-weight:900;">Забув пароль?</a>
      </div>

      <button type="submit">Увійти</button>
    </form>

    <div class="link-row">
      Немає акаунту? <a href="register.php">Зареєструватися</a>
    </div>
  </section>
</main>

<?php require_once __DIR__ . '/includes/footer.php'; ?>

<script>
  // Тогл показу пароля
  (function(){
    const pass = document.getElementById('password');
    const toggle = document.getElementById('togglePass');
    if (!toggle || !pass) return;

    function flip(){
      if (pass.type === 'password') {
        pass.type = 'text';
        toggle.textContent = 'Приховати';
      } else {
        pass.type = 'password';
        toggle.textContent = 'Показати';
      }
    }

    toggle.addEventListener('click', flip);
    toggle.addEventListener('keydown', (e) => {
      if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        flip();
      }
    });
  })();
</script>

</body>
</html>
