<?php

namespace App\Http\Controllers;

use App\Enums\KategoriJenis;
use App\Models\Kategori;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Inertia\Inertia;
use Inertia\Response;
use Mews\Purifier\Facades\Purifier;

class KategoriController extends Controller
{
    public function index(Request $request): Response
    {
        $kategoris = Kategori::query()
            ->withCount('ads')
            ->when($request->string('search')->toString(), fn ($q, $search) => $q
                ->where('nama_kategori', 'like', "%{$search}%")
                ->orWhere('alias', 'like', "%{$search}%"))
            ->latest()
            ->paginate(15)
            ->withQueryString();

        return Inertia::render('kategoris/Index', [
            'kategoris' => $kategoris,
            'filters' => $request->only(['search']),
            'jenisOptions' => collect(KategoriJenis::cases())->map(fn ($j) => ['value' => $j->value, 'label' => $j->label()]),
            'appUrl' => rtrim(config('app.url'), '/'),
        ]);
    }

    public function create(): Response
    {
        return Inertia::render('kategoris/Create', [
            'jenisOptions' => collect(KategoriJenis::cases())->map(fn ($j) => ['value' => $j->value, 'label' => $j->label()]),
        ]);
    }

    public function edit(Kategori $kategori): Response
    {
        return Inertia::render('kategoris/Edit', [
            'kategori' => $kategori,
            'jenisOptions' => collect(KategoriJenis::cases())->map(fn ($j) => ['value' => $j->value, 'label' => $j->label()]),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'nama_kategori' => ['required', 'string', 'max:255'],
            'judul' => ['nullable', 'string', 'max:255'],
            'deskripsi' => ['nullable', 'string'],
            'alias' => ['nullable', 'string', 'max:255'],
            'jenis' => ['required', 'in:'.implode(',', array_column(KategoriJenis::cases(), 'value'))],
            'status' => ['nullable', 'boolean'],
        ]);

        $data['alias'] = $this->resolveAlias($data['alias'] ?? null, $data['nama_kategori'], $data['jenis']);
        $data['status'] = $data['status'] ?? true;
        $data['deskripsi'] = $this->sanitizeDeskripsi($data['deskripsi'] ?? null);

        Kategori::create($data);

        Inertia::flash('toast', ['type' => 'success', 'message' => __('Kategori berhasil dibuat.')]);

        return to_route('kategoris.index');
    }

    public function update(Request $request, Kategori $kategori): RedirectResponse
    {
        $data = $request->validate([
            'nama_kategori' => ['required', 'string', 'max:255'],
            'judul' => ['nullable', 'string', 'max:255'],
            'deskripsi' => ['nullable', 'string'],
            'alias' => ['nullable', 'string', 'max:255'],
            'jenis' => ['required', 'in:'.implode(',', array_column(KategoriJenis::cases(), 'value'))],
            'status' => ['nullable', 'boolean'],
        ]);

        $data['alias'] = $this->resolveAlias($data['alias'] ?? null, $data['nama_kategori'], $data['jenis'], $kategori);
        $data['status'] = $data['status'] ?? true;
        $data['deskripsi'] = $this->sanitizeDeskripsi($data['deskripsi'] ?? null);

        $kategori->update($data);

        Inertia::flash('toast', ['type' => 'success', 'message' => __('Kategori berhasil diperbarui.')]);

        return to_route('kategoris.index');
    }

    public function destroy(Kategori $kategori): RedirectResponse
    {
        $kategori->delete();

        Inertia::flash('toast', ['type' => 'success', 'message' => __('Kategori berhasil dihapus.')]);

        return to_route('kategoris.index');
    }

    /**
     * Report per kategori: daftar campaign + statistik klik/tayang
     * (total, hari ini, 7 hari terakhir per campaign dari ip_histories).
     */
    public function report(Kategori $kategori): Response
    {
        $today = now()->toDateString();
        $weekAgo = now()->subDays(6)->toDateString();

        // Agregat klik dari ip_histories per ad (1 baris = 1 klik valid).
        $klikPerAd = fn (string $from, string $to) => DB::table('ip_histories')
            ->select('ad_id', DB::raw('count(*) as total'))
            ->whereBetween('tanggal', [$from, $to])
            ->groupBy('ad_id')
            ->pluck('total', 'ad_id');

        $klikToday = $klikPerAd($today, $today);
        $klikWeek = $klikPerAd($weekAgo, $today);

        $ads = $kategori->ads()
            ->with('user:id,name')
            ->orderBy('id')
            ->get()
            ->map(fn ($ad, $i) => [
                'no' => $i + 1,
                'id' => $ad->id,
                'judul' => $ad->judul,
                'url' => $ad->url,
                'user' => $ad->user?->name,
                'status' => $ad->status->value,
                'is_paused' => $ad->is_paused,
                'klik_total' => $ad->klik,
                'klik_hari_ini' => (int) ($klikToday[$ad->id] ?? 0),
                'klik_7_hari' => (int) ($klikWeek[$ad->id] ?? 0),
                'muncul_total' => $ad->muncul,
                'muncul_hari_ini' => $ad->muncul_tanggal?->toDateString() === $today ? $ad->muncul_hari_ini : 0,
            ]);

        return Inertia::render('kategoris/Report', [
            'kategori' => $kategori->only(['id', 'nama_kategori', 'judul', 'alias', 'jenis', 'viewed']),
            'ads' => $ads,
            'totals' => [
                'klik_hari_ini' => $ads->sum('klik_hari_ini'),
                'klik_7_hari' => $ads->sum('klik_7_hari'),
                'klik_total' => $ads->sum('klik_total'),
            ],
        ]);
    }

    /**
     * Sanitasi HTML deskripsi: strip tag berbahaya (script, on*, iframe) via Purifier.
     */
    protected function sanitizeDeskripsi(?string $html): ?string
    {
        if (! $html) {
            return null;
        }

        $clean = Purifier::clean($html);

        return $clean !== '' ? $clean : null;
    }

    /**
     * Resolve alias: jenis Redirect → generate kode unik random (statis per kategori),
     * jenis Landing Page → slug dari input alias atau nama_kategori.
     *
     * @param  string  $jenis  nilai enum KategoriJenis (value)
     */
    protected function resolveAlias(?string $alias, string $namaKategori, string $jenis, ?Kategori $exclude = null): string
    {
        if ($jenis === KategoriJenis::Redirect->value) {
            return $this->generateUniqueAlias($exclude);
        }

        return $alias ? Str::slug($alias) : Str::slug($namaKategori);
    }

    /**
     * Generate kode unik random 8 karakter, pastikan belum dipakai kategori lain.
     */
    protected function generateUniqueAlias(?Kategori $exclude = null): string
    {
        do {
            $code = Str::lower(Str::random(8));
        } while (
            Kategori::where('alias', $code)
                ->when($exclude, fn ($q) => $q->where('id', '!=', $exclude->id))
                ->exists()
        );

        return $code;
    }
}
