#!/usr/bin/env bash
set -euo pipefail

ROOT="${1:-registration_starter}"
mkdir -p "$ROOT/app" "$ROOT/public/admin" "$ROOT/sql"

cat > "$ROOT/sql/schema.sql" <<'EOF'
CREATE DATABASE IF NOT EXISTS registration_app
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

USE registration_app;

CREATE TABLE users (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  username VARCHAR(50) NOT NULL,
  email VARCHAR(255) NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  is_active TINYINT(1) NOT NULL DEFAULT 1,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  UNIQUE KEY uq_users_username (username),
  UNIQUE KEY uq_users_email (email)
) ENGINE=InnoDB;

CREATE TABLE groups (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  group_name VARCHAR(100) NOT NULL,
  group_slug VARCHAR(100) NOT NULL,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  UNIQUE KEY uq_groups_slug (group_slug)
) ENGINE=InnoDB;

CREATE TABLE applications (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  app_name VARCHAR(100) NOT NULL,
  app_slug VARCHAR(100) NOT NULL,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  UNIQUE KEY uq_applications_slug (app_slug)
) ENGINE=InnoDB;

CREATE TABLE user_group (
  user_id BIGINT UNSIGNED NOT NULL,
  group_id BIGINT UNSIGNED NOT NULL,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (user_id, group_id),
  CONSTRAINT fk_user_group_user
    FOREIGN KEY (user_id) REFERENCES users(id)
    ON DELETE CASCADE,
  CONSTRAINT fk_user_group_group
    FOREIGN KEY (group_id) REFERENCES groups(id)
    ON DELETE CASCADE
) ENGINE=InnoDB;

CREATE TABLE group_application (
  group_id BIGINT UNSIGNED NOT NULL,
  application_id BIGINT UNSIGNED NOT NULL,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (group_id, application_id),
  CONSTRAINT fk_group_application_group
    FOREIGN KEY (group_id) REFERENCES groups(id)
    ON DELETE CASCADE,
  CONSTRAINT fk_group_application_application
    FOREIGN KEY (application_id) REFERENCES applications(id)
    ON DELETE CASCADE
) ENGINE=InnoDB;
EOF

cat > "$ROOT/app/config.php" <<'EOF'
<?php
declare(strict_types=1);

return [
    'db' => [
        'host' => '127.0.0.1',
        'name' => 'registration_app',
        'user' => 'root',
        'pass' => '',
        'charset' => 'utf8mb4',
    ],
    'session_name' => 'regapp_session',
];
EOF

cat > "$ROOT/app/db.php" <<'EOF'
<?php
declare(strict_types=1);

function db(array $config): PDO
{
    $dsn = sprintf('mysql:host=%s;dbname=%s;charset=%s', $config['host'], $config['name'], $config['charset']);
    return new PDO($dsn, $config['user'], $config['pass'], [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,
    ]);
}
EOF

cat > "$ROOT/app/bootstrap.php" <<'EOF'
<?php
declare(strict_types=1);

$config = require __DIR__ . '/config.php';
session_name($config['session_name']);
session_start();
require __DIR__ . '/db.php';
require __DIR__ . '/helpers.php';
require __DIR__ . '/auth.php';
require __DIR__ . '/middleware.php';
$pdo = db($config['db']);
EOF

cat > "$ROOT/app/helpers.php" <<'EOF'
<?php
declare(strict_types=1);

function e(string $value): string { return htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); }
function redirect(string $path): never { header("Location: {$path}"); exit; }
EOF

cat > "$ROOT/app/auth.php" <<'EOF'
<?php
declare(strict_types=1);

function current_user(PDO $pdo): ?array {
    if (empty($_SESSION['user_id'])) return null;
    static $cache = null;
    if ($cache !== null) return $cache;
    $stmt = $pdo->prepare('SELECT id, username, email, is_active, created_at FROM users WHERE id = :id LIMIT 1');
    $stmt->execute([':id' => $_SESSION['user_id']]);
    return $cache = ($stmt->fetch() ?: null);
}
function login_user(int $userId): void { session_regenerate_id(true); $_SESSION['user_id'] = $userId; }
function logout_user(): void {
    $_SESSION = [];
    if (ini_get('session.use_cookies')) {
        $params = session_get_cookie_params();
        setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
    }
    session_destroy();
}
function user_in_group(PDO $pdo, int $userId, string $groupSlug): bool {
    $stmt = $pdo->prepare('SELECT 1 FROM user_group ug JOIN groups g ON g.id = ug.group_id WHERE ug.user_id = :user_id AND g.group_slug = :group_slug LIMIT 1');
    $stmt->execute([':user_id' => $userId, ':group_slug' => $groupSlug]);
    return (bool)$stmt->fetchColumn();
}
function user_can_access_app(PDO $pdo, int $userId, string $appSlug): bool {
    $stmt = $pdo->prepare('SELECT 1 FROM user_group ug JOIN group_application ga ON ga.group_id = ug.group_id JOIN applications a ON a.id = ga.application_id WHERE ug.user_id = :user_id AND a.app_slug = :app_slug LIMIT 1');
    $stmt->execute([':user_id' => $userId, ':app_slug' => $appSlug]);
    return (bool)$stmt->fetchColumn();
}
EOF

cat > "$ROOT/app/middleware.php" <<'EOF'
<?php
declare(strict_types=1);

function require_login(PDO $pdo): array {
    $user = current_user($pdo);
    if (!$user) redirect('/login.php');
    if ((int)$user['is_active'] !== 1) { logout_user(); redirect('/login.php'); }
    return $user;
}
function require_access(PDO $pdo, string $appSlug): array {
    $user = require_login($pdo);
    if (!user_can_access_app($pdo, (int)$user['id'], $appSlug)) { http_response_code(403); echo 'Access denied'; exit; }
    return $user;
}
function require_admin(PDO $pdo): array {
    $user = require_login($pdo);
    if (!user_in_group($pdo, (int)$user['id'], 'admin')) { http_response_code(403); echo 'Admin access required'; exit; }
    return $user;
}
EOF

cat > "$ROOT/public/index.php" <<'EOF'
<?php
require __DIR__ . '/../app/bootstrap.php';
$user = current_user($pdo);
?>
<!doctype html><html><body>
<?php if ($user): ?>
<p>Welcome, <?= e($user['username']) ?>.</p>
<p><a href="/dashboard.php">Dashboard</a> | <a href="/logout.php">Logout</a></p>
<?php else: ?>
<p><a href="/register.php">Register</a> | <a href="/login.php">Login</a></p>
<?php endif; ?>
</body></html>
EOF

cat > "$ROOT/public/register.php" <<'EOF'
<?php
require __DIR__ . '/../app/bootstrap.php';
$error = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username'] ?? '');
    $email = trim($_POST['email'] ?? '');
    $password = (string)($_POST['password'] ?? '');
    $confirm = (string)($_POST['confirm_password'] ?? '');
    if ($username === '' || $email === '' || $password === '') $error = 'All fields are required.';
    elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) $error = 'Invalid email address.';
    elseif ($password !== $confirm) $error = 'Passwords do not match.';
    elseif (strlen($password) < 8) $error = 'Password must be at least 8 characters.';
    else {
        $check = $pdo->prepare('SELECT id FROM users WHERE username = :username OR email = :email LIMIT 1');
        $check->execute([':username' => $username, ':email' => $email]);
        if ($check->fetch()) $error = 'Username or email already exists.';
        else {
            $stmt = $pdo->prepare('INSERT INTO users (username, email, password_hash) VALUES (:username, :email, :password_hash)');
            $stmt->execute([':username' => $username, ':email' => $email, ':password_hash' => password_hash($password, PASSWORD_DEFAULT)]);
            $userId = (int)$pdo->lastInsertId();
            $group = $pdo->prepare('SELECT id FROM groups WHERE group_slug = :slug LIMIT 1');
            $group->execute([':slug' => 'member']);
            $groupId = (int)$group->fetchColumn();
            if ($groupId > 0) {
                $join = $pdo->prepare('INSERT IGNORE INTO user_group (user_id, group_id) VALUES (:user_id, :group_id)');
                $join->execute([':user_id' => $userId, ':group_id' => $groupId]);
            }
            login_user($userId);
            redirect('/dashboard.php');
        }
    }
}
?>
<!doctype html><html><body>
<h1>Register</h1>
<?php if ($error): ?><p style="color:red;"><?= e($error) ?></p><?php endif; ?>
<form method="post">
<input name="username" placeholder="Username" required>
<input name="email" type="email" placeholder="Email" required>
<input name="password" type="password" placeholder="Password" required>
<input name="confirm_password" type="password" placeholder="Confirm Password" required>
<button type="submit">Create account</button>
</form>
</body></html>
EOF

cat > "$ROOT/public/login.php" <<'EOF'
<?php
require __DIR__ . '/../app/bootstrap.php';
$error = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $login = trim($_POST['login'] ?? '');
    $password = (string)($_POST['password'] ?? '');
    $stmt = $pdo->prepare('SELECT id, password_hash, is_active FROM users WHERE username = :login OR email = :login LIMIT 1');
    $stmt->execute([':login' => $login]);
    $user = $stmt->fetch();
    if (!$user || (int)$user['is_active'] !== 1 || !password_verify($password, $user['password_hash'])) $error = 'Invalid login credentials.';
    else {
        if (password_needs_rehash($user['password_hash'], PASSWORD_DEFAULT)) {
            $rehash = $pdo->prepare('UPDATE users SET password_hash = :hash WHERE id = :id');
            $rehash->execute([':hash' => password_hash($password, PASSWORD_DEFAULT), ':id' => $user['id']]);
        }
        login_user((int)$user['id']);
        redirect('/dashboard.php');
    }
}
?>
<!doctype html><html><body>
<h1>Login</h1>
<?php if ($error): ?><p style="color:red;"><?= e($error) ?></p><?php endif; ?>
<form method="post">
<input name="login" placeholder="Username or email" required>
<input name="password" type="password" placeholder="Password" required>
<button type="submit">Login</button>
</form>
</body></html>
EOF

cat > "$ROOT/public/logout.php" <<'EOF'
<?php
require __DIR__ . '/../app/bootstrap.php';
logout_user();
redirect('/index.php');
EOF

cat > "$ROOT/public/dashboard.php" <<'EOF'
<?php
require __DIR__ . '/../app/bootstrap.php';
$user = require_login($pdo);
?>
<!doctype html><html><body>
<h1>Dashboard</h1>
<p>Hello, <?= e($user['username']) ?>.</p>
<p><a href="/admin/users.php">Admin Users</a> | <a href="/logout.php">Logout</a></p>
</body></html>
EOF

cat > "$ROOT/public/admin/users.php" <<'EOF'
<?php
require __DIR__ . '/../../app/bootstrap.php';
require_admin($pdo);
$users = $pdo->query('SELECT id, username, email, is_active, created_at FROM users ORDER BY id DESC')->fetchAll();
?>
<!doctype html><html><body>
<h1>Users</h1>
<ul>
<?php foreach ($users as $user): ?>
<li><?= e($user['username']) ?> (<?= e($user['email']) ?>)</li>
<?php endforeach; ?>
</ul>
</body></html>
EOF

cat > "$ROOT/public/admin/groups.php" <<'EOF'
<?php require __DIR__ . '/../../app/bootstrap.php'; require_admin($pdo); echo 'Groups admin placeholder';
EOF

cat > "$ROOT/public/admin/applications.php" <<'EOF'
<?php require __DIR__ . '/../../app/bootstrap.php'; require_admin($pdo); echo 'Applications admin placeholder';
EOF

cat > "$ROOT/README.md" <<'EOF'
# Registration Starter

Import `sql/schema.sql`, configure `app/config.php`, then serve `public/` as the web root.
EOF

echo "Created $ROOT"

