<?php
declare(strict_types=1);

namespace App\Controllers\Web;

use App\Middleware\AuthSession;
use App\Middleware\TenantScope;
use App\Models\Part;
use App\Models\Role;
use Core\Controller;
use Core\Session;
use Core\Tool;

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

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

    private function canManage(): bool
    {
        $role = Session::user()['role_code'] ?? '';
        return in_array($role, [Role::ADMIN, Role::EXECUTIVE, Role::PROJECT_MANAGER], true);
    }

    public function index(): void
    {
        $tenantId = $this->tenantId();
        $filters = array_filter([
            'q'        => $_GET['q']        ?? null,
            'category' => $_GET['category'] ?? null,
            'low_only' => $_GET['low_only'] ?? null,
        ]);
        $this->render('parts/index', [
            'parts'     => Part::listForTenant($tenantId, $filters),
            'counts'    => Part::countsForTenant($tenantId),
            'filters'   => $filters,
            'canManage' => $this->canManage(),
            'flash'     => Session::flash('parts_msg'),
        ]);
    }

    public function create(): void
    {
        if (!$this->canManage()) redirect('/Parts');
        $this->render('parts/form', [
            'part' => null,
            'csrf' => Tool::generateCsrf(),
        ]);
    }

    public function edit(int $id): void
    {
        if (!$this->canManage()) redirect('/Parts');
        $part = Part::findInTenant($this->tenantId(), $id);
        if (!$part) { Session::flash('parts_msg', 'Part not found.'); redirect('/Parts'); }
        $this->render('parts/form', [
            'part' => $part,
            'csrf' => Tool::generateCsrf(),
        ]);
    }

    public function save(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') redirect('/Parts');
        if (!$this->canManage() || !Tool::checkCsrf($_POST['_csrf'] ?? null)) redirect('/Parts');
        $tenantId = $this->tenantId();
        $id = (int) ($_POST['part_id'] ?? 0);
        if (trim((string) ($_POST['sku']  ?? '')) === '' || trim((string) ($_POST['name'] ?? '')) === '') {
            Session::flash('parts_msg', 'SKU and name are required.');
            redirect($id > 0 ? "/Parts/edit/{$id}" : '/Parts/create');
        }
        if ($id > 0) {
            Part::update($tenantId, $id, $_POST);
            Session::flash('parts_msg', 'Part updated.');
        } else {
            $id = Part::create($tenantId, $_POST);
            Session::flash('parts_msg', 'Part created.');
        }
        redirect('/Parts/show/' . $id);
    }

    public function show(int $id): void
    {
        $tenantId = $this->tenantId();
        $part = Part::findInTenant($tenantId, $id);
        if (!$part) { Session::flash('parts_msg', 'Part not found.'); redirect('/Parts'); }
        $this->render('parts/show', [
            'part'      => $part,
            'movements' => Part::movementsFor($tenantId, $id),
            'canManage' => $this->canManage(),
            'csrf'      => Tool::generateCsrf(),
            'flash'     => Session::flash('parts_msg'),
        ]);
    }

    public function delete(int $id): void
    {
        if (!$this->canManage()) redirect('/Parts');
        Part::softDelete($this->tenantId(), $id);
        Session::flash('parts_msg', 'Part deleted.');
        redirect('/Parts');
    }

    public function receive(int $id): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') redirect("/Parts/show/{$id}");
        if (!$this->canManage() || !Tool::checkCsrf($_POST['_csrf'] ?? null)) redirect("/Parts/show/{$id}");
        $qty = (float) ($_POST['quantity'] ?? 0);
        if ($qty > 0) {
            Part::receive(
                $this->tenantId(),
                $id,
                $qty,
                $_POST['unit_cost'] !== '' ? (float) $_POST['unit_cost'] : null,
                $_POST['reason'] ?: null,
                (int) (Session::user()['user_id'] ?? 0) ?: null
            );
            Session::flash('parts_msg', 'Stock received.');
        }
        redirect("/Parts/show/{$id}");
    }

    public function issue(int $id): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') redirect("/Parts/show/{$id}");
        if (!$this->canManage() || !Tool::checkCsrf($_POST['_csrf'] ?? null)) redirect("/Parts/show/{$id}");
        $qty = (float) ($_POST['quantity'] ?? 0);
        if ($qty > 0) {
            Part::issue(
                $this->tenantId(),
                $id,
                $qty,
                $_POST['reason'] ?: null,
                !empty($_POST['work_order_id']) ? (int) $_POST['work_order_id'] : null,
                (int) (Session::user()['user_id'] ?? 0) ?: null
            );
            Session::flash('parts_msg', 'Stock issued.');
        }
        redirect("/Parts/show/{$id}");
    }

    public function adjust(int $id): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') redirect("/Parts/show/{$id}");
        if (!$this->canManage() || !Tool::checkCsrf($_POST['_csrf'] ?? null)) redirect("/Parts/show/{$id}");
        $delta = (float) ($_POST['delta_qty'] ?? 0);
        if ($delta !== 0.0) {
            Part::adjust(
                $this->tenantId(),
                $id,
                $delta,
                $_POST['reason'] ?: null,
                (int) (Session::user()['user_id'] ?? 0) ?: null
            );
            Session::flash('parts_msg', 'Stock adjusted.');
        }
        redirect("/Parts/show/{$id}");
    }
}
