<?php

namespace Modules\ProductCompat\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
 * UI for the offline batch-enrichment workflow: generate batch JSON files,
 * download them (hand to an AI assistant), upload the enriched results, and
 * import them — all wrapping the existing productcompat:export-batches /
 * import-enrichment commands so there is one implementation.
 */
class BatchController extends Controller
{
    /** Per-business working directory for batch files. */
    protected function dir(int $businessId): string
    {
        return storage_path('app/pc_batches/' . $businessId);
    }

    protected function gate(): void
    {
        if (! auth()->user()->can('productcompat.queue') && ! auth()->user()->can('productcompat.review')) {
            abort(403, 'Unauthorized action.');
        }
    }

    public function index(Request $request)
    {
        $this->gate();
        $businessId = (int) $request->session()->get('user.business_id');
        $dir = $this->dir($businessId);

        $batches  = $this->list($dir, 'batch_*.json');
        $enriched = $this->list($dir, '*.enriched.json');
        $prompt   = is_file($dir . '/PROMPT.md') ? (string) file_get_contents($dir . '/PROMPT.md') : '';

        return view('productcompat::batches.index', compact('batches', 'enriched', 'prompt'));
    }

    /** Generate batch files (wraps productcompat:export-batches). */
    public function generate(Request $request)
    {
        $this->gate();
        $businessId = (int) $request->session()->get('user.business_id');
        $size = max(1, min((int) $request->input('size', 300), 5000));
        $missing = $request->boolean('missing');

        @ini_set('max_execution_time', '0');
        @ini_set('memory_limit', '1024M');

        $dir = $this->dir($businessId);
        $this->clearDir($dir); // fresh set each generate

        $params = ['--business' => $businessId, '--size' => $size, '--dir' => $dir];
        if ($missing) {
            $params['--missing'] = true;
        }
        Artisan::call('productcompat:export-batches', $params);

        $count = count($this->list($dir, 'batch_*.json'));

        return redirect()->route('productcompat.batches')
            ->with('status', ['success' => 1, 'msg' => "Generated {$count} batch file(s). Download them, enrich, then upload the results below."]);
    }

    /** Download a single file (batch, prompt or enriched) from the business dir. */
    public function download(Request $request)
    {
        $this->gate();
        $businessId = (int) $request->session()->get('user.business_id');
        $name = basename((string) $request->query('file'));
        $path = $this->dir($businessId) . '/' . $name;

        if (! preg_match('/^(batch_\d+\.json|PROMPT\.md|.+\.enriched\.json)$/', $name) || ! is_file($path)) {
            abort(404);
        }

        return response()->download($path);
    }

    /** Zip and download every batch file + the prompt. */
    public function downloadAll(Request $request): BinaryFileResponse
    {
        $this->gate();
        $businessId = (int) $request->session()->get('user.business_id');
        $dir = $this->dir($businessId);

        $files = array_merge(glob($dir . '/batch_*.json') ?: [], array_filter([$dir . '/PROMPT.md', $dir . '/README.txt'], 'is_file'));
        abort_if(empty($files), 404, 'No batch files — generate them first.');

        $zipPath = $dir . '/pc_batches_' . $businessId . '.zip';
        @unlink($zipPath);
        $zip = new \ZipArchive();
        if ($zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
            abort(500, 'Could not create the zip.');
        }
        foreach ($files as $f) {
            $zip->addFile($f, basename($f));
        }
        $zip->close();

        return response()->download($zipPath)->deleteFileAfterSend(true);
    }

    /** Upload enriched JSON file(s) and import them (wraps import-enrichment). */
    public function import(Request $request)
    {
        $this->gate();
        $businessId = (int) $request->session()->get('user.business_id');
        $dir = $this->dir($businessId);
        if (! is_dir($dir)) {
            @mkdir($dir, 0755, true);
        }

        $saved = 0;
        foreach ((array) $request->file('files', []) as $file) {
            if (! $file || $file->getClientOriginalExtension() !== 'json') {
                continue;
            }
            // Normalise the name so import-enrichment's dir mode (*.enriched.json) picks it up.
            $base = preg_replace('/\.enriched\.json$|\.json$/i', '', $file->getClientOriginalName());
            $file->move($dir, $base . '.enriched.json');
            $saved++;
        }

        if ($saved === 0) {
            return redirect()->route('productcompat.batches')
                ->with('status', ['success' => 0, 'msg' => 'No .json files were uploaded.']);
        }

        @ini_set('max_execution_time', '0');
        @ini_set('memory_limit', '1024M');
        Artisan::call('productcompat:import-enrichment', ['file' => $dir]);
        $out = trim(preg_replace('/\s+/', ' ', Artisan::output()));

        return redirect()->route('productcompat.batches')
            ->with('status', ['success' => 1, 'msg' => "Imported {$saved} file(s). " . mb_substr($out, 0, 300) . ' — review in the Review Queue.']);
    }

    /** Run the final cross-product compatibility matching (wraps the command). */
    public function match(Request $request)
    {
        $this->gate();
        $businessId = (int) $request->session()->get('user.business_id');

        @ini_set('max_execution_time', '0');
        @ini_set('memory_limit', '1024M');
        Artisan::call('productcompat:match-compatibility', ['--business' => $businessId]);
        $out = trim(preg_replace('/\s+/', ' ', Artisan::output()));

        return redirect()->route('productcompat.batches')
            ->with('status', ['success' => 1, 'msg' => 'Compatibility matching done. ' . mb_substr($out, 0, 300) . ' — review the links in the Review Queue.']);
    }

    /** Delete all batch/enriched files for this business. */
    public function clear(Request $request)
    {
        $this->gate();
        $businessId = (int) $request->session()->get('user.business_id');
        $this->clearDir($this->dir($businessId));

        return redirect()->route('productcompat.batches')
            ->with('status', ['success' => 1, 'msg' => 'Batch files cleared.']);
    }

    /** @return array<int,array{name:string,size:string}> */
    protected function list(string $dir, string $pattern): array
    {
        $out = [];
        foreach (glob($dir . '/' . $pattern) ?: [] as $f) {
            $out[] = ['name' => basename($f), 'size' => $this->human((int) filesize($f))];
        }
        usort($out, fn ($a, $b) => strcmp($a['name'], $b['name']));

        return $out;
    }

    protected function clearDir(string $dir): void
    {
        foreach (glob($dir . '/*') ?: [] as $f) {
            @unlink($f);
        }
    }

    protected function human(int $bytes): string
    {
        if ($bytes < 1024) {
            return $bytes . ' B';
        }
        if ($bytes < 1048576) {
            return round($bytes / 1024, 1) . ' KB';
        }

        return round($bytes / 1048576, 1) . ' MB';
    }
}
