<?php

namespace App\Http\Controllers\Concerns;

use App\Models\SpecDocument;
use App\Models\SpecDocumentSection;
use App\SpecDocumentBlueprint;
use DateTimeInterface;
use Mtc\MercuryDataModels\Tenant;

/**
 * Keeps spec document section fields that are backed by a tenant column (target launch
 * date, pre-launch stats) in sync with the tenant record: values are read from the
 * tenant when serving a document and written back to it when a section is saved.
 */
trait SyncsSpecDocumentTenantFields
{
    protected function specDocumentBlueprint(): SpecDocumentBlueprint
    {
        return app(SpecDocumentBlueprint::class);
    }

    /**
     * Merge tenant-linked values into every section's in-memory data for the response.
     */
    protected function hydrateTenantFields(SpecDocument $document): void
    {
        $tenant = Tenant::query()->find($document->tenant_id);

        $document->sections->each(fn (SpecDocumentSection $section) => $this->hydrateSection($section, $tenant));
    }

    protected function hydrateSection(SpecDocumentSection $section, ?Tenant $tenant): void
    {
        $map = $this->specDocumentBlueprint()->tenantFields($section->type);
        if ($tenant === null || empty($map)) {
            return;
        }

        $data = is_array($section->data) ? $section->data : [];
        foreach ($map as $key => $column) {
            $value = $tenant->{$column};
            $data[$key] = $value instanceof DateTimeInterface ? $value->format('Y-m-d') : $value;
        }

        $section->data = $data;
    }

    /**
     * Persist tenant-linked values onto the tenant and return the section data with those
     * keys removed (the tenant is the source of truth for them).
     *
     * @param array<string, mixed>|null $data
     * @return array<string, mixed>|null
     */
    protected function persistTenantFields(SpecDocument $document, SpecDocumentSection $section, ?array $data): ?array
    {
        $map = $this->specDocumentBlueprint()->tenantFields($section->type);
        if (empty($map) || !is_array($data)) {
            return $data;
        }

        $tenant = Tenant::query()->find($document->tenant_id);
        if ($tenant !== null) {
            $updates = [];
            foreach ($map as $key => $column) {
                if (array_key_exists($key, $data)) {
                    $updates[$column] = $data[$key] === '' ? null : $data[$key];
                }
            }
            if (!empty($updates)) {
                $tenant->update($updates);
            }
        }

        return collect($data)->except(array_keys($map))->all();
    }
}
