<?php

namespace App\Console\Commands;

use App\Models\Role;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;

class SyncSkspUsers extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'sso:sync-sksp {--dry-run : Only preview the changes}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Sync users from SKSP database to local SSO users table';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $dryRun = $this->option('dry-run');

        if (!$dryRun) {
            $this->info('Starting SKSP User Sync...');
        }

        try {
            DB::connection('sksp')->getPdo();
        } catch (\Exception $e) {
            if ($dryRun) {
                $this->output->write(json_encode(['error' => 'Could not connect to SKSP database: ' . $e->getMessage()]));
                return 1;
            }
            $this->error('Could not connect to SKSP database: ' . $e->getMessage());
            return 1;
        }

        // Fetch users from SKSP
        $skspUsers = DB::connection('sksp')->table('users')
            ->select('id', 'name', 'email', 'pass_hash', 'role')
            ->get();

        if (!$dryRun) {
            $this->info("Found {$skspUsers->count()} users in SKSP database.");
        }

        $synced = 0;
        $created = 0;
        $errors = 0;
        $updates = 0;
        $newUsersList = [];

        foreach ($skspUsers as $skspUser) {
            try {
                if (empty($skspUser->email)) {
                    continue;
                }

                // 1. Sync User Identity
                $user = User::where('email', $skspUser->email)->first();
                $isNew = false;
                $isUpdate = false;

                // 2. Prepare Roles (Fetch for both dry-run and sync)
                $roleKeys = [];
                // Map legacy role column if needed, prefixed
                if ($skspUser->role == 1)
                    $roleKeys[] = 'biz_admin';
                if ($skspUser->role == 2)
                    $roleKeys[] = 'biz_manager';

                // Fetch granular roles from sksp.user_roles
                $skspRoles = DB::connection('sksp')->table('user_roles')
                    ->where('user_id', $skspUser->id)
                    ->pluck('role_key')
                    ->toArray();

                foreach ($skspRoles as $rKey) {
                    $roleKeys[] = 'biz_' . $rKey;
                }

                $roleKeys = array_unique($roleKeys);
                $roleNameStr = implode(', ', $roleKeys);

                if (!$user) {
                    $isNew = true;
                    if ($dryRun) {
                        $newUsersList[] = [
                            'name' => $skspUser->name,
                            'email' => $skspUser->email,
                            'role_name' => empty($roleNameStr) ? 'User' : $roleNameStr,
                        ];
                    } else {
                        $user = new User();
                        $user->email = $skspUser->email;
                        $user->password = $skspUser->pass_hash;
                        $user->created_at = now();
                        $user->name = $skspUser->name;
                        $user->email_verified_at = now();
                        $user->save();
                    }
                    $created++;
                } else {
                    $isUpdate = true;
                    if (!$dryRun) {
                        $user->password = $skspUser->pass_hash;
                        $user->name = $skspUser->name;
                        $user->email_verified_at = $user->email_verified_at ?? now();
                        $user->save();
                    }
                    $updates++;
                }

                if (!$dryRun) {
                    // Sync Roles safely
                    // 1. Get IDs of the desired 'biz' roles
                    $newBizRoleIds = [];
                    if (!empty($roleKeys)) {
                        $newBizRoleIds = Role::where('app', 'biz')
                            ->whereIn('key', $roleKeys)
                            ->pluck('id')
                            ->toArray();
                    }

                    // 2. Get IDs of existing roles from OTHER apps (preserve them)
                    $existingOtherRoleIds = $user->roles()
                        ->where('app', '!=', 'biz')
                        ->pluck('roles.id')
                        ->toArray();

                    // 3. Merge and Sync
                    $finalRoleIds = array_unique(array_merge($newBizRoleIds, $existingOtherRoleIds));
                    $user->roles()->sync($finalRoleIds);
                }

                $synced++;

                if (!$dryRun && $synced % 10 == 0) {
                    $this->info("Processed {$synced} users...");
                }

            } catch (\Exception $e) {
                $errors++;
                if (!$dryRun) {
                    $this->error("Failed to sync user {$skspUser->email}: " . $e->getMessage());
                }
            }
        }

        if ($dryRun) {
            $stats = [
                'found' => $skspUsers->count(),
                'new_count' => $created,
                'update_count' => $updates,
                'new_users' => $newUsersList,
            ];
            $this->output->write(json_encode($stats));
            return 0;
        }

        $this->info("Sync completed.");
        $this->info("Synced: {$synced}");
        $this->info("Created: {$created}");
        $this->info("Updated: {$updates}");
        $this->info("Errors: {$errors}");

        return 0;
    }
}
