<?php

namespace App\Console\Commands;

use App\Models\GroupInvitation;
use App\Models\Person;
use App\Models\Profile;
use App\Models\SpaceMember;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class WeshareAdoptInvitedUsers extends Command
{
    protected $signature = 'weshare:adopt-invited-users {--apply : Actually write changes (default is dry-run)}';

    protected $description = 'Attach already-registered users to spaces where their email was invited (one-time migration helper).';

    public function handle(): int
    {
        $apply = (bool) $this->option('apply');

        $pending = GroupInvitation::query()
            ->where('status', 'pending')
            ->orderBy('created_at', 'desc')
            ->get();

        if ($pending->count() === 0) {
            $this->info('No pending invitations found.');
            return self::SUCCESS;
        }

        $this->line(($apply ? 'APPLY' : 'DRY-RUN') . ': scanning ' . $pending->count() . ' pending invitations…');

        $seen = [];
        $would = 0;
        $did = 0;
        $skipped = 0;

        foreach ($pending as $inv) {
            $email = strtolower(trim((string) $inv->invited_email));
            if ($email === '') {
                $skipped++;
                continue;
            }

            // Only process the latest pending invite per (space,email).
            $dedupeKey = (string) $inv->space_id . '|' . $email;
            if (isset($seen[$dedupeKey])) {
                continue;
            }
            $seen[$dedupeKey] = true;

            $user = User::query()->whereRaw('LOWER(email) = ?', [$email])->first();
            if (! $user) {
                $skipped++;
                continue;
            }

            $profile = Profile::query()->where('user_id', $user->id)->first();
            if (! $profile) {
                $skipped++;
                continue;
            }

            $alreadyMember = SpaceMember::query()
                ->where('space_id', (string) $inv->space_id)
                ->where('user_id', $user->id)
                ->exists();

            $person = Person::query()
                ->where('space_id', (string) $inv->space_id)
                ->where(function ($q) use ($inv, $email) {
                    $q->where('id', (string) $inv->invited_person_id)
                        ->orWhere('email', $email);
                })
                ->first();

            if ($person && $person->auth_user_id !== null && (string) $person->auth_user_id !== (string) $user->id) {
                // Someone else already claimed this invited person.
                $skipped++;
                continue;
            }

            $would++;
            $this->line("• {$email} → adopt into space {$inv->space_id}" . ($alreadyMember ? ' (already member)' : ''));

            if (! $apply) {
                continue;
            }

            DB::transaction(function () use ($inv, $user, $profile, $alreadyMember, $person, $email) {
                if (! $alreadyMember) {
                    SpaceMember::query()->create([
                        'space_id' => (string) $inv->space_id,
                        'user_id' => $user->id,
                        'role' => 'member',
                        'created_at' => now(),
                    ]);
                }

                if ($person) {
                    $person->auth_user_id = $user->id;
                    if (trim((string) $person->email) === '') {
                        $person->email = $email;
                    }
                    $person->save();
                }

                // Mark all pending invitations for this email in this space as accepted.
                GroupInvitation::query()
                    ->where('space_id', (string) $inv->space_id)
                    ->where('invited_email', $email)
                    ->where('status', 'pending')
                    ->update(['status' => 'accepted']);

                $profile->default_space_id = (string) $inv->space_id;
                $profile->save();
            });

            $did++;
        }

        $this->newLine();
        $this->info(($apply ? 'Applied' : 'Would apply') . " {$would} adoption(s).");
        $this->line("Processed: {$would} | Changed: {$did} | Skipped: {$skipped}");

        if (! $apply) {
            $this->line('Run again with `--apply` to write changes.');
        }

        return self::SUCCESS;
    }
}

