<?php

namespace Modules\ProductCompat\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Modules\ProductCompat\Entities\PcChangeReport;

class ChangeReportController extends Controller
{
    /**
     * Detailed change report: per product — old / new / removed / missing data.
     */
    public function index(Request $request)
    {
        if (! auth()->user()->can('productcompat.review')) {
            abort(403, 'Unauthorized action.');
        }

        $business_id = $request->session()->get('user.business_id');

        // Runs with metadata (type + product count + latest time) so the filter
        // can group them by kind and show a readable label instead of a raw id.
        $runsMeta = PcChangeReport::where('business_id', $business_id)
            ->selectRaw('run_id, action, COUNT(*) as cnt, MAX(created_at) as last_at')
            ->groupBy('run_id', 'action')
            ->orderByDesc('last_at')
            ->get();

        // Per-type counts for the grouping tabs (parse / enrich / ai_enrich / ai_apply).
        $actionCounts = PcChangeReport::where('business_id', $business_id)
            ->selectRaw('action, COUNT(*) as cnt')
            ->groupBy('action')
            ->pluck('cnt', 'action');

        $query = PcChangeReport::with('product')
            ->where('business_id', $business_id)
            ->orderByDesc('id');

        if ($request->filled('run_id')) {
            $query->where('run_id', $request->input('run_id'));
        }
        if ($request->filled('action')) {
            $query->where('action', $request->input('action'));
        }

        $reports = $query->paginate(50)->appends($request->query());

        return view('productcompat::report.index', compact('reports', 'runsMeta', 'actionCounts'));
    }

    /**
     * CSV export of the (optionally run-filtered) change report.
     */
    public function export(Request $request): StreamedResponse
    {
        if (! auth()->user()->can('productcompat.review')) {
            abort(403, 'Unauthorized action.');
        }

        $business_id = $request->session()->get('user.business_id');

        $query = PcChangeReport::with('product')
            ->where('business_id', $business_id)
            ->orderByDesc('id');
        if ($request->filled('run_id')) {
            $query->where('run_id', $request->input('run_id'));
        }
        if ($request->filled('action')) {
            $query->where('action', $request->input('action'));
        }

        $filename = 'product_compat_change_report_' . now()->format('Ymd_His') . '.csv';

        return response()->streamDownload(function () use ($query) {
            $out = fopen('php://output', 'w');
            fputcsv($out, ['Run', 'Product SKU', 'Product', 'Old data', 'New data', 'Removed (wrong) data', 'Missing data', 'Date']);

            $query->chunk(500, function ($rows) use ($out) {
                foreach ($rows as $r) {
                    fputcsv($out, [
                        $r->run_id,
                        $r->product->sku ?? '',
                        $r->product->name ?? ('#' . $r->product_id),
                        $this->flatten($r->old_data),
                        $this->flattenNew($r->new_data),
                        $this->flatten(array_map(fn ($x) => is_array($x) ? ($x['value'] ?? '') : $x, (array) $r->removed_data)),
                        implode(', ', (array) $r->missing_data),
                        optional($r->created_at)->toDateTimeString(),
                    ]);
                }
            });
            fclose($out);
        }, $filename, ['Content-Type' => 'text/csv']);
    }

    protected function flatten($data): string
    {
        if (empty($data)) {
            return '';
        }
        $parts = [];
        foreach ((array) $data as $k => $v) {
            $parts[] = is_string($k) ? ($k . '=' . (is_array($v) ? json_encode($v) : $v)) : (is_array($v) ? json_encode($v) : $v);
        }

        return implode(' | ', $parts);
    }

    protected function flattenNew($new): string
    {
        $new = (array) $new;
        $parts = [];
        if (! empty($new['part_numbers'])) {
            $parts[] = 'PN: ' . implode(', ', array_map(fn ($p) => $p['value'] . '[' . $p['type'] . ']', $new['part_numbers']));
        }
        if (! empty($new['device_models'])) {
            $parts[] = 'Fits: ' . implode(', ', array_map(fn ($d) => $d['label'], $new['device_models']));
        }
        if (! empty($new['barcodes'])) {
            $parts[] = 'Barcodes: ' . implode(', ', $new['barcodes']);
        }

        return implode(' | ', $parts);
    }
}
