<?php

declare(strict_types=1);

namespace Database\Seeders;

use PDO;

/**
 * AdminUserSeeder
 *
 * Seeds the same people shown in the frontend's User Management page
 * so Phase 2's UI has real data to render against. Every account gets
 * a cryptographically random password that is printed to the console
 * ONCE and never written to disk anywhere — whoever runs `php
 * bin/seed.php` is responsible for securely relaying those to each
 * person (or, in production, immediately triggering a forced password
 * reset instead of using the generated one at all).
 */
final class AdminUserSeeder implements SeederInterface
{
    public function run(PDO $pdo): void
    {
        $businessLineIds = $pdo->query('SELECT slug, id FROM business_lines')->fetchAll(PDO::FETCH_KEY_PAIR);
        $roleIds = $pdo->query('SELECT slug, id FROM roles')->fetchAll(PDO::FETCH_KEY_PAIR);
        $departmentIds = $pdo->query('SELECT name, id FROM departments')->fetchAll(PDO::FETCH_KEY_PAIR);
        $teamIds = $pdo->query('SELECT name, id FROM teams')->fetchAll(PDO::FETCH_KEY_PAIR);
        $policy = require dirname(__DIR__, 2) . '/config/security.php';
        $hashAlgo = $policy['password']['hash_algo'];
        $hashOptions = $policy['password']['hash_options'];

        $users = [
            [
                'first_name' => 'Jordan', 'last_name' => 'Cole', 'email' => 'jordan@example.com',
                'phone' => '(555) 555-0100', 'job_title' => 'Operations Admin', 'role' => 'operations_admin',
                'business_lines' => ['demo'], 'department' => 'Sales & Growth', 'team' => 'Sales Team',
            ],
            [
                'first_name' => 'Rita', 'last_name' => 'Sandoval', 'email' => 'rita@example.com',
                'phone' => '(555) 555-0134', 'job_title' => 'Sales Representative', 'role' => 'sales_rep',
                'business_lines' => ['demo'], 'department' => 'Sales & Growth', 'team' => 'Sales Team',
            ],
            [
                'first_name' => 'Elena', 'last_name' => 'Vasquez', 'email' => 'elena@example.com',
                'phone' => '(555) 555-0177', 'job_title' => 'Field Staff', 'role' => 'field_staff',
                'business_lines' => ['demo'], 'department' => 'Homecare Operations', 'team' => 'Caregiver Team A',
            ],
        ];

        $userStmt = $pdo->prepare(
            'INSERT INTO users (role_id, department_id, first_name, last_name, email, phone, job_title,
                                 password_hash, password_changed_at, email_verified_at, status, created_at, updated_at)
             VALUES (:role_id, :department_id, :first_name, :last_name, :email, :phone, :job_title,
                     :password_hash, NOW(), NOW(), :status, NOW(), NOW())
             ON DUPLICATE KEY UPDATE first_name = VALUES(first_name), last_name = VALUES(last_name)'
        );

        $blStmt = $pdo->prepare(
            'INSERT IGNORE INTO user_business_lines (user_id, business_line_id) VALUES (:user_id, :business_line_id)'
        );
        $teamStmt = $pdo->prepare(
            'INSERT IGNORE INTO team_members (team_id, user_id, joined_at) VALUES (:team_id, :user_id, NOW())'
        );
        $historyStmt = $pdo->prepare(
            'INSERT INTO password_histories (user_id, password_hash, created_at) VALUES (:user_id, :hash, NOW())'
        );

        $generatedCredentials = [];

        foreach ($users as $i => $user) {
            $password = self::generateStrongPassword();
            $status = $i === 0 ? 'active' : 'active'; // seeded as active for Phase 1 demo purposes
            $passwordHash = password_hash($password, $hashAlgo, $hashOptions);

            $userStmt->execute([
                'role_id' => $roleIds[$user['role']] ?? null,
                'department_id' => $departmentIds[$user['department']] ?? null,
                'first_name' => $user['first_name'],
                'last_name' => $user['last_name'],
                'email' => $user['email'],
                'phone' => $user['phone'],
                'job_title' => $user['job_title'],
                'password_hash' => $passwordHash,
                'status' => $status,
            ]);

            $userId = (int) $pdo->lastInsertId();

            if ($userId === 0) {
                // ON DUPLICATE KEY UPDATE path doesn't populate lastInsertId
                // reliably across drivers — look the id up explicitly.
                $lookup = $pdo->prepare('SELECT id FROM users WHERE email = :email');
                $lookup->execute(['email' => $user['email']]);
                $userId = (int) $lookup->fetchColumn();
            }

            foreach ($user['business_lines'] as $slug) {
                if (isset($businessLineIds[$slug])) {
                    $blStmt->execute(['user_id' => $userId, 'business_line_id' => $businessLineIds[$slug]]);
                }
            }

            if (isset($teamIds[$user['team']])) {
                $teamStmt->execute(['team_id' => $teamIds[$user['team']], 'user_id' => $userId]);
            }

            $historyStmt->execute(['user_id' => $userId, 'hash' => $passwordHash]);

            $generatedCredentials[] = [$user['email'], $password];
        }

        echo '  seeded ' . count($users) . " user accounts\n";
        echo "\n  ── ONE-TIME GENERATED PASSWORDS (not stored anywhere — copy them now) ──\n";
        foreach ($generatedCredentials as [$email, $password]) {
            echo "  {$email}  →  {$password}\n";
        }
        echo "  ─────────────────────────────────────────────────────────────────────\n\n";
    }

    private static function generateStrongPassword(int $length = 16): string
    {
        $alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!@#$%';
        $password = '';

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

        return $password;
    }
}
