<?php
declare(strict_types=1);

namespace App\Controllers\Web;

use App\Middleware\AuthSession;
use App\Middleware\TenantScope;
use App\Models\Asset;
use App\Models\AssetType;
use App\Models\AssetTypeField;
use App\Models\Attachment;
use App\Models\Site;
use Core\Controller;
use Core\Session;
use Core\Tool;

final class AssetsController extends Controller
{
    public function middleware(): array
    {
        return [AuthSession::class, TenantScope::class];
    }

    private function tenantId(): int
    {
        return (int) ($_SESSION['tenant_id'] ?? 0);
    }

    public function hierarchy(): void
    {
        $this->render('assets/hierarchy', [
            'tree'  => Asset::treeForTenant($this->tenantId()),
            'flash' => Session::flash('assets_msg'),
        ]);
    }

    public function index(): void
    {
        $filters = [
            'site_id'       => $_GET['site_id']       ?? null,
            'asset_type_id' => $_GET['asset_type_id'] ?? null,
            'status'        => $_GET['status']        ?? null,
            'q'             => $_GET['q']             ?? null,
        ];
        $this->render('assets/index', [
            'assets'  => Asset::listForTenant($this->tenantId(), array_filter($filters)),
            'sites'   => Site::optionsForTenant($this->tenantId()),
            'types'   => AssetType::optionsForTenant($this->tenantId()),
            'filters' => $filters,
            'flash'   => Session::flash('assets_msg'),
        ]);
    }

    /**
     * Two-step create: no type selected → picker screen; type selected → full form
     * populated with that type's fields.
     */
    public function create(): void
    {
        $tenantId = $this->tenantId();
        $typeId   = (int) ($_GET['type'] ?? 0);
        if ($typeId <= 0) {
            $this->render('assets/pick-type', [
                'types' => AssetType::optionsForTenant($tenantId),
            ]);
            return;
        }
        $type = AssetType::findInTenant($tenantId, $typeId);
        if (!$type) { Session::flash('assets_msg', 'Type not found.'); redirect('/Assets/create'); }
        $this->render('assets/form', [
            'asset'   => null,
            'type'    => $type,
            'fields'  => AssetTypeField::forType($tenantId, $typeId),
            'sites'   => Site::optionsForTenant($tenantId),
            'parents' => Asset::treeForTenant($tenantId),
            'csrf'    => Tool::generateCsrf(),
        ]);
    }

    public function edit(int $id): void
    {
        $tenantId = $this->tenantId();
        $asset = Asset::findInTenant($tenantId, $id);
        if (!$asset) { Session::flash('assets_msg', 'Asset not found.'); redirect('/Assets'); }
        $typeId = (int) $asset['asset_type_id'];
        $this->render('assets/form', [
            'asset'   => $asset,
            'type'    => AssetType::findInTenant($tenantId, $typeId),
            'fields'  => AssetTypeField::forType($tenantId, $typeId),
            'sites'   => Site::optionsForTenant($tenantId),
            'parents' => array_values(array_filter(Asset::treeForTenant($tenantId), static fn($n) => (int) $n['asset_id'] !== $id)),
            'csrf'    => Tool::generateCsrf(),
        ]);
    }

    public function save(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') redirect('/Assets');
        if (!Tool::checkCsrf($_POST['_csrf'] ?? null)) {
            Session::flash('assets_msg', 'Session expired.'); redirect('/Assets');
        }

        $tenantId = $this->tenantId();
        $userId   = (int) (Session::user()['user_id'] ?? 0);
        $id       = (int) ($_POST['asset_id'] ?? 0);

        if (trim((string) ($_POST['name'] ?? '')) === '' || empty($_POST['asset_type_id'])) {
            Session::flash('assets_msg', 'Name and asset type are required.');
            redirect($id > 0 ? "/Assets/edit/{$id}" : '/Assets/create');
        }

        // Build meta_json from posted "meta[...]" fields, validated against the type's schema.
        $typeId = (int) $_POST['asset_type_id'];
        $schema = AssetTypeField::forType($tenantId, $typeId);
        $meta = [];
        $rawMeta = $_POST['meta'] ?? [];
        foreach ($schema as $f) {
            $key = $f['field_key'];
            if (!array_key_exists($key, $rawMeta)) { continue; }
            $val = $rawMeta[$key];
            if ($val === '' || $val === null) { continue; }
            if ($f['field_type'] === 'number') { $val = is_numeric($val) ? $val + 0 : null; }
            if ($f['field_type'] === 'boolean') { $val = !empty($val) ? true : false; }
            if ($f['field_type'] === 'multiselect' && !is_array($val)) { $val = [$val]; }
            if ($val !== null) { $meta[$key] = $val; }
        }

        $payload = $_POST;
        $payload['meta_json'] = $meta;

        if ($id > 0) {
            $existing = Asset::findInTenant($tenantId, $id);
            if (!$existing) { Session::flash('assets_msg', 'Not found.'); redirect('/Assets'); }
            Asset::update($tenantId, $id, $payload);
            Session::flash('assets_msg', 'Asset updated.');
        } else {
            $id = Asset::create($tenantId, $userId, $payload);
            Session::flash('assets_msg', 'Asset created.');
        }
        redirect("/Assets/show/{$id}");
    }

    public function show(int $id): void
    {
        $tenantId = $this->tenantId();
        $asset = Asset::findInTenant($tenantId, $id);
        if (!$asset) { Session::flash('assets_msg', 'Asset not found.'); redirect('/Assets'); }
        $meta = !empty($asset['meta_json']) ? (json_decode($asset['meta_json'], true) ?: []) : [];
        $this->render('assets/show', [
            'asset'       => $asset,
            'meta'        => $meta,
            'fields'      => AssetTypeField::forType($tenantId, (int) $asset['asset_type_id']),
            'attachments' => Attachment::forOwner($tenantId, 'asset', $id),
            'children'    => Asset::childrenOf($tenantId, $id),
            'ancestors'   => Asset::ancestorsOf($tenantId, $id),
            'ownerType'   => 'asset',
            'ownerId'     => $id,
            'csrf'        => Tool::generateCsrf(),
            'flash'       => Session::flash('assets_msg') ?: Session::flash('attach_msg'),
        ]);
    }

    public function delete(int $id): void
    {
        Asset::softDelete($this->tenantId(), $id);
        Session::flash('assets_msg', 'Asset deleted.');
        redirect('/Assets');
    }
}
