<?php

namespace Spatie\Mailcoach\Domain\Audience\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Storage;
use Spatie\Mailcoach\Domain\Audience\Models\Subscriber;
use Spatie\Mailcoach\Domain\Audience\Models\SubscriberExport;
use Spatie\Mailcoach\Domain\Shared\Traits\UsesMailcoachModels;
use Spatie\SimpleExcel\SimpleExcelWriter;
use Throwable;

class ExportSubscribersChunkJob implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;
    use UsesMailcoachModels;

    public function __construct(
        private SubscriberExport $subscriberExport,
        private string $path,
        private array $subscriberIds,
        private array $header,
    ) {}

    public function handle(): void
    {
        $tempDisk = Storage::disk(config('mailcoach.tmp_disk'));
        $writer = SimpleExcelWriter::create($tempDisk->path($this->path));

        self::getSubscriberClass()::query()
            ->whereIn('id', $this->subscriberIds)
            ->each(function (Subscriber $subscriber) use ($writer) {
                try {
                    $subscriberData = $subscriber->toExportRow();
                    $defaultAttributes = Arr::except($this->header, 'extra_attributes');

                    $defaultData = Arr::only($subscriberData, $defaultAttributes);
                    $defaultData['extra_attributes'] = json_encode(Arr::except($subscriberData, $defaultAttributes));

                    foreach ($defaultData as $key => $value) {
                        if (is_array($value)) {
                            $defaultData[$key] = implode(',', $value);
                        }
                    }

                    $writer->addRow($defaultData);

                    $this->subscriberExport->increment('exported_subscribers_count');
                } catch (Throwable $exception) {
                    report($exception);

                    $this->subscriberExport->addError($exception->getMessage());
                }
            });

        $writer->close();
    }
}
