<?php

namespace App\Http\Controllers\Admin;

use App\Enums\ContentStatus;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\BulkActionRequest;
use App\Http\Requests\Admin\StoreServiceRequest;
use App\Http\Requests\Admin\UpdateServiceRequest;
use App\Models\Service;
use App\Services\ActivityLogger;
use App\Services\ContentCacheService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Str;
use Illuminate\View\View;

class ServiceController extends Controller
{
    public function index(): View
    {
        Gate::authorize('viewAny', Service::class);

        $query = Service::query()->with('highlights')->ordered();

        if ($search = request('q')) {
            $query->where(fn ($q) => $q->where('title', 'like', "%{$search}%")->orWhere('slug', 'like', "%{$search}%"));
        }

        if ($status = request('status')) {
            $query->where('status', $status);
        }

        return view('admin.services.index', ['services' => $query->get()]);
    }

    public function create(): View
    {
        Gate::authorize('create', Service::class);

        return view('admin.services.form', ['service' => null, 'full' => null]);
    }

    public function store(StoreServiceRequest $request, ActivityLogger $logger): RedirectResponse
    {
        Gate::authorize('create', Service::class);

        $service = DB::transaction(function () use ($request): Service {
            $data = $this->data($request->validated(), $request->input('_action'));
            $data['created_by'] = auth()->id();
            $data['updated_by'] = auth()->id();
            $service = Service::create($data);
            if ($request->input('_action') === 'publish') {
                Gate::authorize('publish', $service);
            }
            $this->syncHighlights($service, $request->input('focus_areas', []));

            return $service;
        });

        app(ContentCacheService::class)->flush();
        $logger->log('service.created', $service, "Service créé: {$service->title}");

        return redirect()->route('admin.services.edit', $service)->with('status', 'Service créé.');
    }

    public function edit(Service $service): View
    {
        Gate::authorize('update', $service);

        $service->load('highlights', 'media');

        return view('admin.services.form', ['service' => $service, 'full' => $service]);
    }

    public function update(UpdateServiceRequest $request, Service $service, ActivityLogger $logger): RedirectResponse
    {
        Gate::authorize('update', $service);

        DB::transaction(function () use ($request, $service): void {
            $service->update($this->data($request->validated(), $request->input('_action')) + ['updated_by' => auth()->id()]);
            if ($request->input('_action') === 'publish') {
                Gate::authorize('publish', $service);
            }
            $this->syncHighlights($service, $request->input('focus_areas', []));
        });

        app(ContentCacheService::class)->flush();
        $logger->log('service.updated', $service, "Service modifié: {$service->title}");

        return back()->with('status', 'Service enregistré.');
    }

    public function publish(Service $service, ActivityLogger $logger): RedirectResponse
    {
        Gate::authorize('publish', $service);

        $service->forceFill([
            'status' => ContentStatus::Published->value,
            'is_active' => true,
            'published_at' => now(),
            'updated_by' => auth()->id(),
        ])->save();

        app(ContentCacheService::class)->flush();
        $logger->log('service.published', $service, "Service publié: {$service->title}");

        return back()->with('status', 'Service publié.');
    }

    public function toggle(Service $service, ActivityLogger $logger): RedirectResponse
    {
        Gate::authorize('update', $service);

        $service->forceFill(['is_active' => ! $service->is_active, 'updated_by' => auth()->id()])->save();
        app(ContentCacheService::class)->flush();
        $logger->log('service.toggled', $service, "Visibilité du service modifiée: {$service->title}");

        return back()->with('status', 'Visibilité modifiée.');
    }

    public function archive(Service $service, ActivityLogger $logger): RedirectResponse
    {
        Gate::authorize('delete', $service);

        $service->forceFill(['status' => ContentStatus::Archived->value, 'is_active' => false])->save();
        app(ContentCacheService::class)->flush();
        $logger->log('service.archived', $service, "Service archivé: {$service->title}");

        return back()->with('status', 'Service archivé.');
    }

    public function duplicate(Service $service, ActivityLogger $logger): RedirectResponse
    {
        Gate::authorize('create', Service::class);

        $copy = DB::transaction(function () use ($service): Service {
            $service->load('highlights');
            $copy = $service->replicate(['slug', 'status', 'published_at']);
            $copy->title = $service->title.' - copie';
            $copy->slug = Str::slug($service->slug.'-copie-'.Str::random(4));
            $copy->status = ContentStatus::Draft->value;
            $copy->is_active = false;
            $copy->published_at = null;
            $copy->created_by = auth()->id();
            $copy->updated_by = auth()->id();
            $copy->save();

            foreach ($service->highlights as $highlight) {
                $copy->highlights()->create($highlight->only(['text', 'sort_order', 'is_active']));
            }

            return $copy;
        });

        $logger->log('service.duplicated', $copy, "Service dupliqué depuis {$service->title}");

        return redirect()->route('admin.services.edit', $copy)->with('status', 'Service dupliqué en brouillon.');
    }

    public function destroy(Service $service, ActivityLogger $logger): RedirectResponse
    {
        Gate::authorize('delete', $service);

        $title = $service->title;
        $service->delete();
        app(ContentCacheService::class)->flush();
        $logger->log('service.deleted', $service, "Service supprimé: {$title}");

        return back()->with('status', 'Service supprimé.');
    }

    public function bulk(BulkActionRequest $request): RedirectResponse
    {
        $services = Service::whereIn('id', $request->input('ids'))->get();

        DB::transaction(function () use ($request, $services): void {
            foreach ($services as $service) {
                Gate::authorize('update', $service);
                match ($request->input('action')) {
                    'archive' => $service->forceFill(['status' => ContentStatus::Archived->value, 'is_active' => false])->save(),
                    'publish' => $service->forceFill(['status' => ContentStatus::Published->value, 'is_active' => true, 'published_at' => now()])->save(),
                    'activate' => $service->forceFill(['is_active' => true])->save(),
                    'deactivate' => $service->forceFill(['is_active' => false])->save(),
                    'toggle-status' => $service->forceFill(['is_active' => ! $service->is_active])->save(),
                    default => null,
                };
            }
        });

        app(ContentCacheService::class)->flush();

        return back()->with('status', $services->count().' service(s) traité(s).');
    }

    private function data(array $data, ?string $action = null): array
    {
        $status = $action === 'publish'
            ? ContentStatus::Published->value
            : ($data['status'] ?? ContentStatus::Draft->value);

        return [
            'title' => $data['title'],
            'slug' => $data['slug'],
            'icon' => $data['icon'] ?? null,
            'intro' => $data['intro'] ?? $data['short_description'] ?? null,
            'short_description' => $data['short_description'] ?? null,
            'description' => $data['description'] ?? null,
            'media_id' => $data['image'] ?? null,
            'image_alt' => $data['image_alt'] ?? null,
            'image_position' => $data['image_position'] ?? 'left',
            'image_caption' => $data['image_caption'] ?? null,
            'sort_order' => $data['sort_order'] ?? 0,
            'status' => $status,
            'is_active' => $action === 'publish' || (bool) ($data['is_active'] ?? false),
            'published_at' => $status === ContentStatus::Published->value ? now() : null,
        ];
    }

    private function syncHighlights(Service $service, array $items): void
    {
        $service->highlights()->delete();

        foreach (array_values(array_filter($items)) as $index => $text) {
            $service->highlights()->create([
                'text' => $text,
                'sort_order' => $index + 1,
                'is_active' => true,
            ]);
        }
    }
}
