<?php

namespace App\Console\Commands;

use App\Models\User;
use App\Models\Organization;
use App\Mail\InactiveProfileWarning1Mail;
use App\Mail\InactiveProfileWarning2Mail;
use App\Mail\InactiveProfileWarningFinalMail;
use App\Mail\UserDeletedMail;
use App\Actions\Jetstream\DeleteUser;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Carbon;

class ProcessInactiveProfiles extends Command
{
    protected $signature = 'profiles:process-inactive';

    protected $description = 'Process inactive profiles - send warnings and delete profiles that exceed inactivity thresholds';

    protected $thresholds = [];
    protected $logFile;

    public function __construct()
    {
        parent::__construct();

        // Convert configured days to seconds for precise comparison
        $this->thresholds = [
            'warning_1' => timebank_config('delete_profile.days_after_inactive.warning_1') * 86400,
            'warning_2' => timebank_config('delete_profile.days_after_inactive.warning_2') * 86400,
            'warning_final' => timebank_config('delete_profile.days_after_inactive.warning_final') * 86400,
            'run_delete' => timebank_config('delete_profile.days_after_inactive.run_delete') * 86400,
        ];

        $this->logFile = storage_path('logs/inactive-profiles.log');
    }

    public function handle()
    {
        $this->info('Processing inactive profiles...');
        $this->logMessage('=== Starting inactive profile processing ===');

        $totalWarnings = 0;
        $totalDeletions = 0;

        // Process Users
        $users = User::whereNotNull('inactive_at') // Only process profiles marked as inactive
            ->whereNull('deleted_at') // Exclude already deleted profiles
            ->get();

        foreach ($users as $user) {
            $result = $this->processProfile($user, 'User');
            if ($result === 'warning') $totalWarnings++;
            if ($result === 'deleted') $totalDeletions++;
        }

        // Process Organizations
        $organizations = Organization::whereNotNull('inactive_at') // Only process profiles marked as inactive
            ->whereNull('deleted_at') // Exclude already deleted profiles
            ->get();

        foreach ($organizations as $organization) {
            $result = $this->processProfile($organization, 'Organization');
            if ($result === 'warning') $totalWarnings++;
            if ($result === 'deleted') $totalDeletions++;
        }

        $this->info("Processing complete: {$totalWarnings} warnings sent, {$totalDeletions} profiles deleted");
        $this->logMessage("=== Completed: {$totalWarnings} warnings, {$totalDeletions} deletions ===\n");

        return 0;
    }

    protected function processProfile($profile, $profileType)
    {
        if (!$profile->inactive_at) {
            return null;
        }

        $secondsSinceInactive = now()->diffInSeconds($profile->inactive_at);
        $secondsRemaining = $this->thresholds['run_delete'] - $secondsSinceInactive;

        // Determine action based on thresholds
        if ($secondsSinceInactive >= $this->thresholds['run_delete']) {
            // Delete profile
            return $this->deleteProfile($profile, $profileType, $secondsSinceInactive);
        } elseif ($secondsSinceInactive >= $this->thresholds['warning_final'] && $secondsSinceInactive < $this->thresholds['run_delete']) {
            // Send final warning
            return $this->sendWarning($profile, $profileType, 'final', $secondsRemaining, $secondsSinceInactive);
        } elseif ($secondsSinceInactive >= $this->thresholds['warning_2'] && $secondsSinceInactive < $this->thresholds['warning_final']) {
            // Send warning 2
            return $this->sendWarning($profile, $profileType, 'warning_2', $secondsRemaining, $secondsSinceInactive);
        } elseif ($secondsSinceInactive >= $this->thresholds['warning_1'] && $secondsSinceInactive < $this->thresholds['warning_2']) {
            // Send warning 1
            return $this->sendWarning($profile, $profileType, 'warning_1', $secondsRemaining, $secondsSinceInactive);
        }

        return null;
    }

    protected function sendWarning($profile, $profileType, $warningLevel, $secondsRemaining, $secondsSinceInactive)
    {
        $accountsData = $this->getAccountsData($profile);
        $totalBalance = $this->getTotalBalance($profile);
        $timeRemaining = $this->formatTimeRemaining($secondsRemaining);
        $daysSinceInactive = round($secondsSinceInactive / 86400, 2);

        $mailClass = match($warningLevel) {
            'warning_1' => InactiveProfileWarning1Mail::class,
            'warning_2' => InactiveProfileWarning2Mail::class,
            'final' => InactiveProfileWarningFinalMail::class,
        };

        // Get recipients
        $recipients = $this->getRecipients($profile, $profileType);

        // Send email to all recipients
        foreach ($recipients as $recipient) {
            Mail::to($recipient['email'])
                ->queue(new $mailClass(
                    $profile,
                    $profileType,
                    $timeRemaining,
                    $secondsRemaining / 86400, // days remaining
                    $accountsData,
                    $totalBalance,
                    $daysSinceInactive
                ));
        }

        $this->logMessage("[{$profileType}] {$warningLevel} sent to {$profile->name} (ID: {$profile->id}) - Inactive for {$daysSinceInactive} days, {$timeRemaining} remaining");
        $this->info("[{$profileType}] {$warningLevel}: {$profile->name} ({$timeRemaining} remaining)");

        return 'warning';
    }

    protected function deleteProfile($profile, $profileType, $secondsSinceInactive)
    {
        $daysSinceInactive = round($secondsSinceInactive / 86400, 2);

        try {
            // Check for negative balances
            $accountsData = $this->getAccountsData($profile);
            foreach ($accountsData as $account) {
                if ($account['balance'] < 0) {
                    $this->logMessage("[{$profileType}] SKIPPED deletion of {$profile->name} (ID: {$profile->id}) - Has negative balance");
                    $this->warn("[{$profileType}] Skipped: {$profile->name} - negative balance");
                    return null;
                }
            }

            // Store profile data before deletion (needed for email)
            $totalBalance = $this->getTotalBalance($profile);
            $profileEmail = $profile->email;
            $profileName = $profile->name;
            $profileFullName = $profile->full_name ?? $profile->name;

            // Get the profile's updated_at timestamp
            $profileTable = $profile->getTable();
            $time = DB::table($profileTable)
                    ->where('id', $profile->id)
                    ->pluck('updated_at')
                    ->first();
            $time = Carbon::parse($time);

            // Execute soft deletion (sets deleted_at, handles balances, but doesn't anonymize)
            // Balance handling: skip donation option, use config elsif logic
            $deleteUser = new DeleteUser();
            $result = $deleteUser->delete($profile, 'delete', null, true); // true = isAutoDeleted

            // Check if soft deletion was successful
            if ($result['status'] === 'success') {
                // Get auto-delete and grace period configuration
                $daysNotLoggedIn = timebank_config('profile_inactive.days_not_logged_in');
                $daysAfterInactive = timebank_config('delete_profile.days_after_inactive.run_delete');
                $totalDays = $daysNotLoggedIn + $daysAfterInactive;
                $gracePeriodDays = timebank_config('delete_profile.grace_period_days', 30);

                // Prepare email data (similar to DeleteUserForm.php)
                $emailData = [
                    'time' => $time->translatedFormat('j F Y, H:i'),
                    'deletedUser' => (object)[
                        'name' => $profileName,
                        'full_name' => $profileFullName,
                        'lang_preference' => $profile->lang_preference ?? config('app.locale', 'en'),
                    ],
                    'mail' => $profileEmail,
                    'balanceHandlingOption' => 'delete', // Auto-delete always uses 'delete' option
                    'totalBalance' => $totalBalance,
                    'donationAccountId' => null,
                    'donationAccountName' => null,
                    'donationOrganizationName' => null,
                    'autoDeleted' => true, // Flag to indicate this was an auto-deletion
                    'daysNotLoggedIn' => $daysNotLoggedIn,
                    'daysAfterInactive' => $daysAfterInactive,
                    'totalDaysToDelete' => $totalDays,
                    'gracePeriodDays' => $gracePeriodDays, // Days to restore profile
                ];

                // Send deletion confirmation email
                Mail::to($profileEmail)->queue(new UserDeletedMail($emailData));

                $this->logMessage("[{$profileType}] SOFT DELETED {$profileName} (ID: {$profile->id}) - Inactive for {$daysSinceInactive} days - Can be restored within {$gracePeriodDays} days - Email sent to {$profileEmail}");
                $this->info("[{$profileType}] Soft deleted: {$profileName} (restorable for {$gracePeriodDays} days)");

                return 'deleted';
            } else {
                $this->logMessage("[{$profileType}] ERROR deleting {$profileName} (ID: {$profile->id}): {$result['message']}");
                $this->error("[{$profileType}] Error deleting {$profileName}: {$result['message']}");
                return null;
            }
        } catch (\Exception $e) {
            $this->logMessage("[{$profileType}] ERROR deleting {$profile->name} (ID: {$profile->id}): {$e->getMessage()}");
            $this->error("[{$profileType}] Error deleting {$profile->name}: {$e->getMessage()}");
            return null;
        }
    }

    protected function getRecipients($profile, $profileType)
    {
        $recipients = [];

        if ($profileType === 'User') {
            $recipients[] = [
                'email' => $profile->email,
                'name' => $profile->name,
            ];
        } elseif ($profileType === 'Organization') {
            // Add organization email
            $recipients[] = [
                'email' => $profile->email,
                'name' => $profile->name,
            ];

            // Add all manager emails
            $managers = $profile->managers()->get();
            foreach ($managers as $manager) {
                $recipients[] = [
                    'email' => $manager->email,
                    'name' => $manager->name,
                ];
            }
        }

        return $recipients;
    }

    protected function getAccountsData($profile)
    {
        $accounts = [];
        $profileAccounts = $profile->accounts()->active()->notRemoved()->get();

        foreach ($profileAccounts as $account) {
            // Clear cache to get fresh balance
            \Cache::forget("account_balance_{$account->id}");

            $accounts[] = [
                'id' => $account->id,
                'name' => $account->name,
                'balance' => $account->balance, // in minutes
                'balanceFormatted' => tbFormat($account->balance),
            ];
        }

        return $accounts;
    }

    protected function getTotalBalance($profile)
    {
        $total = 0;
        $accountsData = $this->getAccountsData($profile);

        foreach ($accountsData as $account) {
            $total += $account['balance'];
        }

        return $total;
    }

    protected function formatTimeRemaining($seconds)
    {
        $days = $seconds / 86400;

        if ($days >= 7) {
            $weeks = round($days / 7);
            return trans_choice('weeks_remaining', $weeks, ['count' => $weeks]);
        } elseif ($days >= 1) {
            $daysRounded = round($days);
            return trans_choice('days_remaining', $daysRounded, ['count' => $daysRounded]);
        } elseif ($seconds >= 3600) {
            $hours = round($seconds / 3600);
            return trans_choice('hours_remaining', $hours, ['count' => $hours]);
        } else {
            $minutes = max(1, round($seconds / 60));
            return trans_choice('minutes_remaining', $minutes, ['count' => $minutes]);
        }
    }

    protected function logMessage($message)
    {
        $timestamp = now()->format('Y-m-d H:i:s');
        $logEntry = "[{$timestamp}] {$message}\n";

        file_put_contents($this->logFile, $logEntry, FILE_APPEND);
        Log::info($message);
    }
}
