<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Client;
use App\Models\GeneratedReport;
use App\Models\ReportTemplate;
use App\Services\Mail\ReportMailer;
use App\Services\Reports\ReportGenerator;
use App\Services\Reports\ReportTemplateDefaults;
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Throwable;

class ReportController extends Controller
{
    public function __construct(private readonly ReportTemplateDefaults $templateDefaults)
    {
    }

    public function index(Request $request): View
    {
        $page_title = 'Raporlar';
        $page_description = 'Manuel ve otomatik rapor yönetimi';

        $reports = $this->reportQuery($request)->paginate(20)->withQueryString();
        $clients = Client::orderBy('company_name')->get();

        return view('admin.reports.index', compact('page_title', 'page_description', 'reports', 'clients'));
    }

    public function create(): View
    {
        $page_title = 'Rapor Oluştur';
        $page_description = 'Müşteri, şablon, kanal ve tarih seçerek manuel rapor üret';
        $clients = Client::orderBy('company_name')->get();
        $templates = ReportTemplate::active()->orderBy('sort_order')->orderBy('name')->get();

        return view('admin.reports.create', compact('page_title', 'page_description', 'clients', 'templates'));
    }

    public function generate(Request $request, ReportGenerator $generator): RedirectResponse
    {
        $data = $request->validate([
            'client_id' => ['required', 'exists:clients,id'],
            'report_template_id' => ['nullable', 'exists:report_templates,id'],
            'report_type' => ['required', 'in:daily,weekly,monthly,custom'],
            'date_from' => ['required', 'date'],
            'date_to' => ['required', 'date', 'after_or_equal:date_from'],
            'channels' => ['nullable', 'array'],
            'channels.*' => ['in:google_ads,meta_ads,search_console,ga4'],
        ]);

        $client = Client::findOrFail((int) $data['client_id']);
        $template = ! empty($data['report_template_id']) ? ReportTemplate::find((int) $data['report_template_id']) : null;
        $channels = $data['channels'] ?? ($template?->channels ?: ['google_ads', 'meta_ads', 'search_console', 'ga4']);

        $report = $generator->createManualReport(
            $client,
            $data['report_type'],
            Carbon::parse($data['date_from']),
            Carbon::parse($data['date_to']),
            $this->templateDefaults->normalizeChannels($channels),
            auth()->id(),
            $template?->id
        );

        if ($report->status === 'failed') {
            return redirect()->route('admin.reports.show', $report)->with('error', 'Rapor üretiminde hata oluştu: ' . $report->error_message);
        }

        return redirect()->route('admin.reports.show', $report)->with('success', 'Rapor oluşturuldu. Seçili şablona göre dosyalar hazırlandı.');
    }

    public function archive(Request $request): View
    {
        $page_title = 'Rapor Arşivi';
        $page_description = 'Üretilen HTML, PDF, Excel/CSV ve mail geçmişi';
        $reports = $this->reportQuery($request)->paginate(20)->withQueryString();
        $clients = Client::orderBy('company_name')->get();

        return view('admin.reports.archive', compact('page_title', 'page_description', 'reports', 'clients'));
    }

    public function show(GeneratedReport $report): View
    {
        $page_title = 'Rapor Detayı';
        $page_description = $report->client?->company_name . ' / ' . $report->date_from?->format('d.m.Y') . ' - ' . $report->date_to?->format('d.m.Y');
        $report->load(['client', 'template', 'emailLogs' => fn ($query) => $query->latest()->limit(10)]);

        return view('admin.reports.show', compact('page_title', 'page_description', 'report'));
    }

    public function regenerate(GeneratedReport $report, ReportGenerator $generator): RedirectResponse
    {
        $generator->generate($report);

        return redirect()->route('admin.reports.show', $report)->with('success', 'Rapor seçili şablona göre yeniden oluşturuldu.');
    }

    public function send(Request $request, GeneratedReport $report, ReportMailer $mailer): RedirectResponse
    {
        $data = $request->validate([
            'recipients_raw' => ['nullable', 'string'],
            'cc_raw' => ['nullable', 'string'],
            'bcc_raw' => ['nullable', 'string'],
            'subject' => ['nullable', 'string', 'max:255'],
            'note' => ['nullable', 'string', 'max:2000'],
            'include_pdf' => ['nullable', 'boolean'],
            'include_excel' => ['nullable', 'boolean'],
            'include_csv' => ['nullable', 'boolean'],
            'include_html' => ['nullable', 'boolean'],
        ]);

        try {
            $emailLog = $mailer->sendReport($report, [
                'recipients' => $data['recipients_raw'] ?? null,
                'cc' => $data['cc_raw'] ?? null,
                'bcc' => $data['bcc_raw'] ?? null,
                'subject' => $data['subject'] ?? null,
                'note' => $data['note'] ?? null,
                'include_pdf' => $request->boolean('include_pdf'),
                'include_excel' => $request->boolean('include_excel'),
                'include_csv' => $request->boolean('include_csv'),
                'include_html' => $request->boolean('include_html'),
            ]);
        } catch (Throwable $exception) {
            report($exception);

            return back()->with('error', 'Rapor gönderilemedi: ' . $exception->getMessage());
        }

        if ($emailLog->status !== 'sent') {
            return back()->with('error', 'Rapor maili gönderilemedi: ' . $emailLog->error_message);
        }

        return back()->with('success', 'Rapor maili gönderildi.');
    }

    public function download(GeneratedReport $report, string $type): StreamedResponse|RedirectResponse
    {
        $path = match ($type) {
            'pdf' => $report->pdf_path ?: $report->html_path,
            'html' => $report->html_path,
            'excel' => $report->excel_path,
            'csv' => $report->csv_path,
            default => null,
        };

        if (! $path || ! Storage::disk('public')->exists($path)) {
            return back()->with('error', 'İstenen rapor dosyası bulunamadı.');
        }

        return Storage::disk('public')->download($path, basename($path));
    }

    private function reportQuery(Request $request)
    {
        return GeneratedReport::with(['client', 'template'])
            ->when($request->filled('client_id'), fn ($query) => $query->where('client_id', $request->integer('client_id')))
            ->when($request->filled('status'), fn ($query) => $query->where('status', $request->string('status')))
            ->latest();
    }
}
