<?php
namespace App\Commands;

use App\Models\RewarderShopModel;
use App\Models\RewarderShopUserModel;
use App\Models\RoleModel;
use App\Models\UserModel;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;

class CreateShopkeeperUsers extends BaseCommand
{
    protected $group = 'Rewarder';
    protected $name = 'rewarder:create-shopkeepers';
    protected $description = 'Create a Shopkeeper user for each shop (if missing) and link as OWNER.';
    protected $usage = 'rewarder:create-shopkeepers [--password 123456] [--domain rewarder.local] [--dry-run] [--force]';

    public function run(array $params)
    {
        $password = (string) (CLI::getOption('password') ?? '123456');
        $domain = (string) (CLI::getOption('domain') ?? 'rewarder.local');
        $dryRun = CLI::getOption('dry-run') !== null;
        $force = CLI::getOption('force') !== null;

        if ($password === '') {
            CLI::error('Option --password cannot be empty.');
            return;
        }

        $now = date('Y-m-d H:i:s');

        $roleModel = new RoleModel();
        $shopkeeperRole = $roleModel->where('title', 'Shopkeeper')->first();
        if (!$shopkeeperRole) {
            if ($dryRun) {
                CLI::write("DRY RUN: Would create role 'Shopkeeper'.", 'yellow');
                $shopkeeperRole = (object) ['id' => null];
            } else {
                $roleId = $roleModel->create(['title' => 'Shopkeeper']);
                $shopkeeperRole = (object) ['id' => $roleId];
                CLI::write("Created role 'Shopkeeper' (id={$roleId}).", 'green');
            }
        }

        $shops = (new RewarderShopModel())->orderBy('id', 'asc')->findAll();
        $shopUserModel = new RewarderShopUserModel();
        $userModel = new UserModel();

        $createdUsers = 0;
        $createdLinks = 0;
        $skipped = 0;

        $uploadsDir = FCPATH . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'users';
        if (!$dryRun) {
            if (!is_dir($uploadsDir)) {
                mkdir($uploadsDir, 0777, true);
            }
            $indexFile = $uploadsDir . DIRECTORY_SEPARATOR . 'index.html';
            if (!is_file($indexFile)) {
                file_put_contents($indexFile, '');
            }
        }

        foreach ($shops as $shop) {
            $hasOwner = $shopUserModel->where(['shop_id' => $shop->id, 'role' => 'OWNER'])->countAllResults() > 0;
            if ($hasOwner && !$force) {
                $skipped++;
                continue;
            }

            $baseUsername = $this->safeUsername('shop_' . $shop->id . '_' . ($shop->slug ?: 'shop'));
            $username = $this->ensureUniqueUsername($userModel, $baseUsername);
            $email = $this->ensureUniqueEmail($userModel, $this->safeEmailLocalPart($shop->slug ?: ('shop-' . $shop->id)) . '+' . $shop->id . '@' . $domain);

            $userData = [
                'role' => (int) $shopkeeperRole->id,
                'name' => trim($shop->name . ' Shopkeeper'),
                'username' => $username,
                'email' => $email,
                'phone' => (string) ($shop->phone ?? ''),
                'address' => (string) ($shop->address ?? ''),
                'status' => 1,
                'reset_token' => '',
                'password' => hash('sha256', $password),
                'img_type' => 'png',
                'created_at' => $now,
                'updated_at' => $now,
            ];

            if ($dryRun) {
                CLI::write("DRY RUN: Would create user '{$username}' and link to shop #{$shop->id} as OWNER.", 'yellow');
                $createdUsers++;
                $createdLinks++;
                continue;
            }

            $userId = (int) $userModel->create($userData);
            $createdUsers++;

            $defaultImage = $uploadsDir . DIRECTORY_SEPARATOR . 'default.png';
            $targetImage = $uploadsDir . DIRECTORY_SEPARATOR . $userId . '.png';
            if (is_file($defaultImage) && !is_file($targetImage)) {
                @copy($defaultImage, $targetImage);
            }

            $shopUserModel->create([
                'shop_id' => (int) $shop->id,
                'user_id' => $userId,
                'role' => 'OWNER',
                'created_at' => $now,
            ]);
            $createdLinks++;

            CLI::write("Created shopkeeper user '{$username}' for shop #{$shop->id}.", 'green');
        }

        CLI::write('---');
        CLI::write('Shops scanned: ' . count($shops));
        CLI::write('Users created: ' . $createdUsers);
        CLI::write('Owner links created: ' . $createdLinks);
        CLI::write('Shops skipped: ' . $skipped);
        if (!$dryRun) {
            CLI::write("Default password for created users: {$password}", 'yellow');
        }
    }

    private function safeUsername(string $s): string
    {
        $s = strtolower($s);
        $s = preg_replace('/[^a-z0-9_]+/i', '_', $s);
        $s = trim((string) $s, '_');
        return $s ?: 'shopkeeper';
    }

    private function safeEmailLocalPart(string $s): string
    {
        $s = strtolower($s);
        $s = preg_replace('/[^a-z0-9]+/i', '-', $s);
        $s = trim((string) $s, '-');
        return $s ?: 'shopkeeper';
    }

    private function ensureUniqueUsername(UserModel $userModel, string $base): string
    {
        $candidate = $base;
        $i = 1;
        while ($userModel->where('username', $candidate)->countAllResults() > 0) {
            $candidate = $base . '_' . $i;
            $i++;
        }
        return $candidate;
    }

    private function ensureUniqueEmail(UserModel $userModel, string $email): string
    {
        $candidate = $email;
        $i = 1;
        while ($userModel->where('email', $candidate)->countAllResults() > 0) {
            $candidate = preg_replace('/@/', '+' . $i . '@', $email, 1) ?? ($email . $i);
            $i++;
        }
        return $candidate;
    }
}

