<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreLeadExport;
use App\Http\Requests\UpdateLeadExport;
use App\Http\Resources\LeadExportResource;
use App\LeadExports\LeadExportOpenApiGenerator;
use App\Models\LeadExport;
use App\Models\LeadExportTemplate;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;

/**
 * Site-level CRUD for CRM lead exports. A lead export can be created from a published
 * system LeadExportTemplate, which seeds its mode / field_map / config (the "apply
 * template to a site" flow, mirroring ExportMap / NotificationMap). Also serves the
 * per-export OpenAPI document describing the outbound payload.
 */
class LeadExportController extends Controller
{
    public function index()
    {
        return LeadExport::query()->paginate();
    }

    public function store(StoreLeadExport $request): LeadExportResource
    {
        $template = $this->resolveTemplate($request->input('template_id'));

        $leadExport = LeadExport::query()->create([
            'name' => $request->input('name'),
            'type' => $template->type ?? $request->input('type', 'lead'),
            'template_id' => $template?->id,
            'mode' => $template->mode ?? LeadExport::MODE_MAPPED,
            'format' => $template->format ?? 'json',
            'field_map' => $template->field_map ?? [],
            'config' => $template->config ?? [],
        ]);

        return new LeadExportResource($leadExport);
    }

    public function show(LeadExport $leadExport): LeadExportResource
    {
        return new LeadExportResource($leadExport);
    }

    public function update(UpdateLeadExport $request, LeadExport $leadExport): LeadExportResource
    {
        $leadExport->fill([
            'name' => $request->input('name'),
            'active' => $request->boolean('active'),
            'type' => $request->input('type', $leadExport->type),
            'mode' => $request->input('mode'),
            'format' => $request->input('format', 'json'),
            'url' => $request->input('url'),
            'headers' => $request->input('headers', []),
            'template_id' => $request->input('template_id'),
            'field_map' => $request->input('field_map', []),
            'config' => $request->input('config', []),
        ]);

        // Only overwrite the stored secret when a new one is supplied, so saving the
        // form without re-entering it does not blank the credential.
        if ($request->filled('password')) {
            $leadExport->password = $request->input('password');
        }

        $leadExport->save();

        return new LeadExportResource($leadExport);
    }

    public function destroy(LeadExport $leadExport): Response
    {
        $leadExport->delete();

        return response('ok');
    }

    /**
     * Serve the OpenAPI document describing this export's outbound payload. Resolves
     * regardless of active state so integrators can read the contract before it is
     * switched on.
     */
    public function docs(string $leadExportSlug): JsonResponse
    {
        $leadExport = LeadExport::query()->where('slug', $leadExportSlug)->firstOrFail();

        return response()->json(app(LeadExportOpenApiGenerator::class)->generate($leadExport));
    }

    /**
     * Resolve a published system template by id, or null when none was requested.
     * A requested-but-missing/unpublished template is a 422.
     */
    private function resolveTemplate(?int $templateId): ?LeadExportTemplate
    {
        if (empty($templateId)) {
            return null;
        }

        $template = LeadExportTemplate::query()->published()->find($templateId);

        abort_if($template === null, 422, 'The selected template is not available.');

        return $template;
    }
}
