<?php

namespace App\Database\Seeds;

use CodeIgniter\Database\Seeder;

/**
 * Seeds the initial administrator account.
 *
 * Credentials are read from environment variables so nothing sensitive is
 * hard-coded in the repository:
 *
 *   ADMIN_SEED_USERNAME
 *   ADMIN_SEED_EMAIL
 *   ADMIN_SEED_PASSWORD
 *   ADMIN_SEED_FIRST_NAME
 *   ADMIN_SEED_LAST_NAME
 *
 * If ADMIN_SEED_PASSWORD is not set, a strong random password is generated
 * and printed to the console once so it can be captured and stored safely.
 */
class DefaultAdminSeeder extends Seeder
{
    public function run(): void
    {
        $username  = env('ADMIN_SEED_USERNAME', 'admin');
        $email     = env('ADMIN_SEED_EMAIL', 'admin@example.com');
        $firstName = env('ADMIN_SEED_FIRST_NAME', 'System');
        $lastName  = env('ADMIN_SEED_LAST_NAME', 'Administrator');
        $password  = env('ADMIN_SEED_PASSWORD');

        $generated = false;
        if (empty($password)) {
            $password  = $this->generateStrongPassword();
            $generated = true;
        }

        $existing = $this->db->table('users')->where('username', $username)->get()->getRow();
        if ($existing) {
            echo "Admin user already exists, skipping.\n";
            return;
        }

        $role       = $this->db->table('roles')->where('slug', 'administrator')->get()->getRow();
        $branch     = $this->db->table('branches')->where('code', 'HQ')->get()->getRow();
        $department = $this->db->table('departments')->where('name', 'Administration')->get()->getRow();

        $data = [
            'uuid'                 => $this->uuid(),
            'first_name'           => $firstName,
            'last_name'            => $lastName,
            'username'             => $username,
            'email'                => $email,
            'password_hash'        => password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]),
            'password_changed_at'  => date('Y-m-d H:i:s'),
            'must_change_password' => $generated ? 1 : 0,
            'role_id'              => $role->id ?? null,
            'branch_id'            => $branch->id ?? null,
            'department_id'        => $department->id ?? null,
            'status'               => 'active',
            'email_verified_at'    => date('Y-m-d H:i:s'),
            'created_at'           => date('Y-m-d H:i:s'),
            'updated_at'           => date('Y-m-d H:i:s'),
        ];

        $this->db->table('users')->insert($data);

        if ($generated) {
            // Deliberately noisy: this is the only time the plaintext password exists.
            echo "\n==============================================\n";
            echo " Default administrator created\n";
            echo " Username: {$username}\n";
            echo " Password: {$password}\n";
            echo " (must_change_password flag is set — store this now)\n";
            echo "==============================================\n\n";
        } else {
            echo "Default administrator '{$username}' created from ADMIN_SEED_PASSWORD.\n";
        }
    }

    private function uuid(): string
    {
        // Dependency-free UUID v4 generator.
        $data    = random_bytes(16);
        $data[6] = chr((ord($data[6]) & 0x0f) | 0x40);
        $data[8] = chr((ord($data[8]) & 0x3f) | 0x80);

        return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
    }

    private function generateStrongPassword(int $length = 16): string
    {
        $upper   = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
        $lower   = 'abcdefghijkmnopqrstuvwxyz';
        $numbers = '23456789';
        $special = '!@#$%^&*()-_=+';
        $all     = $upper . $lower . $numbers . $special;

        $password  = $upper[random_int(0, strlen($upper) - 1)];
        $password .= $lower[random_int(0, strlen($lower) - 1)];
        $password .= $numbers[random_int(0, strlen($numbers) - 1)];
        $password .= $special[random_int(0, strlen($special) - 1)];

        for ($i = strlen($password); $i < $length; $i++) {
            $password .= $all[random_int(0, strlen($all) - 1)];
        }

        return str_shuffle($password);
    }
}
