<?php

namespace App;

use App\Contracts\InteractsWithContentSync;
use App\Facades\Settings;
use App\Traits\RetrievesFieldData;
use App\Traits\SavesContent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Mtc\ContentManager\Facades\Media;
use Mtc\ContentManager\Models\Template;
use Mtc\Crm\Models\Form;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\DealershipDepartment;
use Mtc\MercuryDataModels\DealershipHoliday;
use Mtc\MercuryDataModels\Franchise;

class DealershipRepository implements InteractsWithContentSync
{
    use RetrievesFieldData;
    use SavesContent;

    protected static array $dataFields = [
        'template_id',
    ];

    /**
     * Save Page
     *
     * @param Dealership $dealership
     * @param Request $request
     * @return void
     */
    public function saveContent(Dealership $dealership, Request $request)
    {
        $this->dropOrphanedContent($dealership, $this->getFlatContentElementIds($request->input('content')));

        collect($request->input('content'))
            ->each(fn ($element, $index) => $this->saveContentElement($dealership, $element, $index));
    }

    public function hasVersioning(): bool
    {
        return Settings::get('dealership-versioning-enabled') === true
            && TierHelper::isAllowed(tenant('tier'), Tier::STANDARD->value);
    }

    /**
     * Restore a previously archived (soft-deleted) dealership.
     *
     * @param int $id
     * @return bool
     */
    public function restore(int $id): bool
    {
        return Dealership::query()
            ->onlyTrashed()
            ->findOrFail($id)
            ->restore();
    }

    public function importRecord(array $entry): bool
    {
        $departments = $entry['departments'] ?? [];
        $holidays = $entry['holidays'] ?? [];
        $franchiseSlugs = $entry['franchises'] ?? [];
        $mediaUrls = $entry['media_uses'] ?? [];

        $entry['franchise_id'] = !empty($entry['franchise'])
            ? Franchise::query()->where('slug', $entry['franchise'])->first()?->id
            : null;
        $entry['template_id'] = !empty($entry['template'])
            ? Template::query()->where('slug', $entry['template'])->first()?->id
            : null;
        $entry['contact_form_id'] = !empty($entry['contact_form'])
            ? Form::query()->where('name', $entry['contact_form'])->first()?->id
            : null;

        $dealership = Dealership::query()->create(Arr::only($entry, (new Dealership())->getFillable()));

        foreach ($departments as $department) {
            $department['dealership_id'] = $dealership->id;
            DealershipDepartment::query()->create(
                Arr::only($department, (new DealershipDepartment())->getFillable())
            );
        }

        foreach ($holidays as $holiday) {
            DealershipHoliday::query()->create([
                'dealership_id' => $dealership->id,
                'date' => $holiday['date'] ?? null,
                'note' => $holiday['note'] ?? null,
            ]);
        }

        if (!empty($franchiseSlugs)) {
            $franchiseIds = Franchise::query()
                ->whereIn('slug', $franchiseSlugs)
                ->pluck('id')
                ->toArray();
            if (!empty($franchiseIds)) {
                $dealership->franchises()->sync($franchiseIds);
            }
        }

        if (!empty($mediaUrls)) {
            $imageIds = [];
            foreach ($mediaUrls as $url) {
                $imageIds[] = Media::importImageFromUrl($url)->id;
            }
            Media::setUsesForModel($imageIds, $dealership);
        }

        return $dealership->exists;
    }

    public function canBeImported(array $entry): bool
    {
        return !Dealership::query()
            ->where('slug', $entry['slug'])
            ->exists();
    }

    public function exportToRemote(array $selections): array
    {
        return Dealership::query()
            ->with([
                'mediaUses.media',
                'departments',
                'upcomingHolidays',
                'franchise',
                'franchises',
                'template',
                'form',
            ])
            ->whereIn('id', $selections)
            ->get()
            ->map(function (Dealership $dealership) {
                $data = $dealership->toArray();

                $data['franchise'] = $dealership->franchise?->slug;
                $data['template'] = $dealership->template?->slug;
                $data['contact_form'] = $dealership->form?->name;
                unset($data['franchise_id'], $data['template_id'], $data['contact_form_id']);

                $data['franchises'] = $dealership->franchises->pluck('slug')->filter()->values()->toArray();

                $data['departments'] = $dealership->departments
                    ->map(fn (DealershipDepartment $department) => Arr::except(
                        Arr::only($department->toArray(), $department->getFillable()),
                        ['dealership_id']
                    ))
                    ->values()
                    ->toArray();

                $data['holidays'] = $dealership->upcomingHolidays
                    ->map(fn (DealershipHoliday $holiday) => [
                        'date' => $holiday->date,
                        'note' => $holiday->note,
                    ])
                    ->values()
                    ->toArray();

                $data['media_uses'] = $dealership->mediaUses
                    ->map(fn ($mediaUse) => $mediaUse->media?->getOriginalUrlAttribute())
                    ->filter()
                    ->values()
                    ->toArray();

                return $data;
            })
            ->toArray();
    }

    public function checkImportEntryValidity(array $dataEntry, array $allEntries): array
    {
        $errors = [];

        if (empty($dataEntry['slug'])) {
            $errors[] = __('validation.import_slug_missing', ['slug' => $dataEntry['slug']]);
        } elseif (Dealership::query()->where('slug', $dataEntry['slug'])->exists()) {
            $errors[] = __('validation.import_slug_taken', ['slug' => $dataEntry['slug']]);
        }

        return [
            'data' => $dataEntry,
            'errors' => $errors,
        ];
    }

    protected function elementParentColumnName(): string
    {
        return 'dealership_id';
    }

    protected function contentOwnerType(): string
    {
        return 'dealership-version';
    }

    protected function getQuery(): Builder
    {
        return Dealership::query();
    }
}
