<?php

namespace App\Console\Commands;

use App\Models\EmailRecipient;
use App\Models\Octoparse\OctoparseImportLog;
use App\Models\Octoparse\OctoparseRecord;
use App\Notifications\OctoparseImportReport;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;

class OctoparseSimulateNewEntries extends Command
{
    protected $signature = 'octoparse:simulate-new-entries
                            {--task= : Limit simulation to one task UUID (default: every enabled task)}
                            {--count=8 : Number of fake new records per task}
                            {--email-report= : Comma-separated emails (falls back to config recipients)}
                            {--cleanup : Delete previously simulated records + logs and exit}';

    protected $description = 'Local-only: fabricate fake Octoparse "new entries" so the admin UI + email report can be previewed without calling the Octoparse Cloud API.';

    public function handle(): int
    {
        if (app()->environment('production')) {
            $this->error('octoparse:simulate-new-entries is disabled on production.');
            return self::FAILURE;
        }

        if ($this->option('cleanup')) {
            return $this->runCleanup();
        }

        return $this->runSimulation();
    }

    private function runCleanup(): int
    {
        $deletedRecords = OctoparseRecord::where('external_key', 'like', 'simulated:%')->delete();
        $deletedLogs = OctoparseImportLog::whereJsonContains('metadata->simulated', true)->delete();

        $this->info("Cleanup done.");
        $this->line("- Records removed: {$deletedRecords}");
        $this->line("- Import logs removed: {$deletedLogs}");

        return self::SUCCESS;
    }

    private function runSimulation(): int
    {
        $count = max(1, (int) $this->option('count'));
        $only = $this->option('task');

        $tasks = config('octoparse.tasks', []);
        if (empty($tasks)) {
            $this->warn('No tasks configured under config/octoparse.php. Nothing to simulate.');
            return self::SUCCESS;
        }

        $selected = [];
        foreach ($tasks as $taskId => $taskConfig) {
            if ($only !== null && $only !== '' && $taskId !== $only) {
                continue;
            }
            if (!($taskConfig['enabled'] ?? false)) {
                continue;
            }
            $selected[$taskId] = $taskConfig;
        }

        if (empty($selected)) {
            $this->warn('No enabled tasks matched.');
            return self::SUCCESS;
        }

        $this->info(sprintf('Simulating %d new entries for %d task(s)...', $count, count($selected)));

        $summary = [];
        $sampleNewEntriesByTask = [];
        $logTimestamp = now()->timestamp;

        foreach ($selected as $taskId => $taskConfig) {
            $label = $taskConfig['label'] ?? $taskId;

            $insertedIds = $this->fabricateRecords($taskId, $label, $count, $logTimestamp);

            $log = OctoparseImportLog::create([
                'task_id' => $taskId,
                'status' => OctoparseImportLog::STATUS_SUCCESS,
                'rows_fetched' => $count,
                'rows_inserted' => $count,
                'rows_updated' => 0,
                'rows_failed' => 0,
                'new_record_ids' => $insertedIds,
                'metadata' => [
                    'label' => $label,
                    'unique_key_field' => $taskConfig['unique_key_field'] ?? null,
                    'simulated' => true,
                ],
                'dry_run' => false,
                'triggered_manually' => true,
                'started_at' => Carbon::now()->subSeconds(2),
                'finished_at' => Carbon::now(),
            ]);

            $summary[] = [
                'log_id' => $log->id,
                'task_id' => $taskId,
                'label' => $label,
                'status' => $log->status,
                'rows_fetched' => $log->rows_fetched,
                'rows_inserted' => $log->rows_inserted,
                'rows_updated' => $log->rows_updated,
                'rows_failed' => $log->rows_failed,
                'new_record_ids' => $insertedIds,
                'duration_seconds' => $log->duration_seconds,
            ];

            $sampleIds = array_slice($insertedIds, 0, 10);
            $sampleNewEntriesByTask[$taskId] = OctoparseRecord::whereIn('id', $sampleIds)
                ->get()
                ->map(fn ($record) => $this->describeRecord($record))
                ->all();

            $this->line("  ✓ Task '{$label}' — log #{$log->id}, {$count} records inserted");
        }

        $latestLogId = max(array_column($summary, 'log_id'));

        $this->dispatchEmail($summary, $sampleNewEntriesByTask, $latestLogId);

        $this->printSummaryFooter($latestLogId);

        return self::SUCCESS;
    }

    /**
     * @return array<int,int> inserted record IDs
     */
    private function fabricateRecords(string $taskId, string $label, int $count, int $logTimestamp): array
    {
        $insertedIds = [];

        for ($i = 1; $i <= $count; $i++) {
            $externalKey = 'simulated:' . $taskId . ':' . $logTimestamp . ':' . $i;
            $name = "SIMULATED ENTITY {$i} ({$label})";

            $record = OctoparseRecord::create([
                'task_id' => $taskId,
                'external_key' => $externalKey,
                'external_key_hash' => OctoparseRecord::hashKey($externalKey),
                'payload' => [
                    'NAME_ASCENDING' => $name,
                    'Entity' => $name,
                    'Country' => 'Simulated',
                    'Source' => 'Local simulator',
                    'SimulationId' => "{$logTimestamp}-{$i}",
                ],
                'scraped_at' => Carbon::now()->subMinutes(random_int(5, 60)),
                'imported_at' => Carbon::now(),
            ]);

            $insertedIds[] = $record->id;
        }

        return $insertedIds;
    }

    private function describeRecord(OctoparseRecord $record): string
    {
        $key = trim((string) $record->external_key);
        if ($key !== '') {
            return $key;
        }

        $payload = is_array($record->payload) ? $record->payload : [];
        foreach ($payload as $field => $value) {
            if (is_scalar($value)) {
                $stringValue = trim((string) $value);
                if ($stringValue !== '') {
                    return "{$field}: {$stringValue}";
                }
            }
        }

        return "Record #{$record->id}";
    }

    private function dispatchEmail(array $summary, array $sampleNewEntriesByTask, int $latestLogId): void
    {
        $recipientsCsv = (string) $this->option('email-report');
        if ($recipientsCsv === '') {
            $recipientsCsv = (string) config('octoparse.email_report.recipients', '');
        }

        $recipients = array_values(array_filter(array_map('trim', explode(',', $recipientsCsv))));
        if (empty($recipients)) {
            $this->warn('No email recipients resolved — skipping email dispatch.');
            return;
        }

        try {
            foreach ($recipients as $email) {
                $recipient = new EmailRecipient($email, 'Octoparse Admin');
                $recipient->notify(new OctoparseImportReport(
                    $summary,
                    $sampleNewEntriesByTask,
                    false,
                    false,
                    $latestLogId
                ));
            }
            $this->info('Email report sent to: ' . implode(', ', $recipients));
        } catch (\Throwable $e) {
            $this->error('Failed to send email report: ' . $e->getMessage());
            Log::error('[Octoparse simulator] Failed to send email report: ' . $e->getMessage());
        }
    }

    private function printSummaryFooter(int $latestLogId): void
    {
        $this->line('');
        $this->info('Preview URLs:');
        $this->line('  Logs list:    https://efet-intranet-be.lndo.site/admin/octoparse/logs');
        $this->line('  New entries:  https://efet-intranet-be.lndo.site/admin/octoparse/logs/' . $latestLogId . '/new-entries');
        $this->line('  MailHog:      http://mail.efet-intranet-be.lndo.site');
        $this->line('');
        $this->comment('Tip: re-run with --cleanup to remove all simulated rows.');
    }
}
