<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Ad;
use App\Models\Setting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class AdController extends Controller
{
    public function index()
    {
        $ads = Ad::orderByDesc('created_at')->get();

        $settings = [
            'vad_enabled'        => Setting::get('vad_enabled', '0'),
            'vad_freq_episodes'  => Setting::get('vad_freq_episodes', 2),
            'vad_freq_minutes'   => Setting::get('vad_freq_minutes', 5),
            'vad_upsell_percent' => Setting::get('vad_upsell_percent', 20),
            'banner_ads_enabled' => Setting::get('banner_ads_enabled', '0'),
        ];

        $stats = [
            'total_impressions' => $ads->sum('impressions'),
            'total_clicks'      => $ads->sum('clicks'),
            'avg_ctr'           => $ads->sum('impressions') > 0
                ? round($ads->sum('clicks') / $ads->sum('impressions') * 100, 2) : 0,
            'active_count'      => $ads->where('is_active', true)->count(),
        ];

        return view('admin.ads.index', compact('ads', 'settings', 'stats'));
    }

    public function store(Request $request)
    {
        $data = $this->validateAd($request);

        if ($request->hasFile('media_file')) {
            $data['file_path'] = $this->storeMedia($request->file('media_file'));
        }

        unset($data['media_file']);
        Ad::create($data);

        return back()->with('success', 'Reklam eklendi.');
    }

    public function edit(Ad $ad)
    {
        return view('admin.ads.edit', compact('ad'));
    }

    public function update(Request $request, Ad $ad)
    {
        $data = $this->validateAd($request, $ad);

        if ($request->hasFile('media_file')) {
            $newPath = $this->storeMedia($request->file('media_file'));
            if ($ad->file_path) Storage::disk('public')->delete($ad->file_path);
            $data['file_path'] = $newPath;
        }

        unset($data['media_file']);
        $ad->update($data);

        return redirect()->route('admin.ads.index')->with('success', 'Reklam güncellendi.');
    }

    public function destroy(Ad $ad)
    {
        if ($ad->file_path) Storage::disk('public')->delete($ad->file_path);
        $ad->delete();

        return back()->with('success', 'Reklam silindi.');
    }

    public function toggle(Ad $ad)
    {
        $ad->update(['is_active' => !$ad->is_active]);
        return back()->with('success', $ad->is_active ? 'Reklam aktifleştirildi.' : 'Reklam durduruldu.');
    }

    public function saveSettings(Request $request)
    {
        Setting::set('vad_enabled',        $request->boolean('vad_enabled') ? '1' : '0', 'ads');
        Setting::set('vad_freq_episodes',  max(1, (int) $request->input('vad_freq_episodes', 2)), 'ads');
        Setting::set('vad_freq_minutes',   max(1, (int) $request->input('vad_freq_minutes', 5)), 'ads');
        Setting::set('vad_upsell_percent', min(100, max(0, (int) $request->input('vad_upsell_percent', 20))), 'ads');
        Setting::set('banner_ads_enabled', $request->boolean('banner_ads_enabled') ? '1' : '0', 'ads');

        return back()->with('success', 'Reklam ayarları kaydedildi.');
    }

    private function validateAd(Request $request, ?Ad $existing = null): array
    {
        $type = $request->input('type', 'video');

        // Sunucu upload limitini aşan dosya: PHP boş/bozuk upload gönderir.
        // Sessizce medyasız reklam kaydetmek yerine net hata ver.
        $this->guardUploadError($request);

        // Yüklenmiş dosya da dış URL de yoksa reklam gösterilemez (media_url null olur).
        // Düzenlemede mevcut dosya varsa yeniden yükleme zorunlu değil.
        $hasExisting = $existing?->file_path || $existing?->external_url;
        $needsMedia  = !$request->hasFile('media_file') && !$hasExisting;

        $data = $request->validate([
            'name'         => 'required|string|max:120',
            'type'         => 'required|in:video,banner',
            'placement'    => 'required|in:preroll,home_mid,home_bottom',
            'media_file'   => [
                'nullable', 'file',
                $type === 'video' ? 'mimes:mp4,m4v' : 'mimes:jpg,jpeg,png,webp,gif',
                $type === 'video' ? 'max:102400' : 'max:20480', // video 100MB, görsel/gif 20MB
            ],
            'external_url' => [$needsMedia ? 'required' : 'nullable', 'nullable', 'url', 'max:2000'],
            'click_url'    => 'nullable|url|max:2000',
            'skip_after'   => 'required|integer|min:0|max:60',
            'weight'       => 'required|integer|min:1|max:100',
            'is_active'    => 'boolean',
            'starts_at'    => 'nullable|date',
            'ends_at'      => 'nullable|date|after:starts_at',
        ], [
            'external_url.required' => 'Bir medya dosyası yükleyin veya dış URL girin. '
                . 'Dosya seçtiyseniz sunucu yükleme limitini aşmış olabilir (maks. '
                . ini_get('upload_max_filesize') . ').',
            'media_file.mimes'      => $type === 'video'
                ? 'Video dosyası MP4 formatında olmalı.'
                : 'Görsel JPG, PNG, WebP veya GIF formatında olmalı.',
            'media_file.max'        => 'Dosya çok büyük.',
        ]);

        // Checkbox işaretli değilse request'te hiç gelmez — açıkça boolean'a çevir
        $data['is_active'] = $request->boolean('is_active');

        return $data;
    }

    /** PHP upload hatalarını (limit aşımı, kısmi yükleme) net mesajla yüzeye çıkar. */
    private function guardUploadError(Request $request): void
    {
        $file = $request->file('media_file');
        if (!$file || $file->isValid()) {
            return;
        }

        $msg = match ($file->getError()) {
            UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE =>
                'Dosya sunucunun yükleme limitini aşıyor (maks. ' . ini_get('upload_max_filesize')
                . '). Daha küçük bir dosya seçin veya hosting limitini yükseltin.',
            UPLOAD_ERR_PARTIAL  => 'Dosya yalnızca kısmen yüklendi, lütfen tekrar deneyin.',
            UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE =>
                'Sunucu dosyayı geçici klasöre yazamadı. Hosting sağlayıcınıza bildirin.',
            default => 'Dosya yüklenemedi (hata kodu: ' . $file->getError() . ').',
        };

        throw \Illuminate\Validation\ValidationException::withMessages(['media_file' => $msg]);
    }

    /** Dosyayı public diske yaz ve tam yazıldığını doğrula. */
    private function storeMedia(\Illuminate\Http\UploadedFile $file): string
    {
        // NOT: klasör adı bilerek nötr ('ads' değil) — adblocker /media/ads/ yolunu
        // ERR_BLOCKED_BY_CLIENT ile engelliyor. 'content' engellenmez.
        $expected = $file->getSize();
        $path     = $file->store('content', 'public');

        if (!$path || !Storage::disk('public')->exists($path)) {
            throw \Illuminate\Validation\ValidationException::withMessages([
                'media_file' => 'Dosya sunucuya kaydedilemedi. storage/app/public klasörünün yazma izni olduğundan emin olun.',
            ]);
        }

        // Kısmi yazma (disk dolu / kesilen upload) sessizce bozuk reklam bırakmasın
        $written = Storage::disk('public')->size($path);
        if ($expected > 0 && $written !== $expected) {
            Storage::disk('public')->delete($path);
            throw \Illuminate\Validation\ValidationException::withMessages([
                'media_file' => "Dosya eksik yüklendi ({$written}/{$expected} byte). Tekrar deneyin.",
            ]);
        }

        return $path;
    }
}
