<?php
/*
|--------------------------------------------------------------------------
| config/part_request_flow.php
| Pipeline roles + workflow helpers for the Request Form module.
|
| Roles (per company_id + user_id, module_key='part_request'):
|   requester : create requests only (Stage 1)
|   packing   : see NEW requests, build packing list  -> status 'packed' (Stage 2)
|   stock     : see PACKED requests, hand over/complete -> status 'completed' (Stage 3)
|   manager   : all stages + admin. Company admins are always 'manager'.
|
| Request status flow:
|   open (NEW) -> packed -> completed
|   (legacy 'incomplete' is treated as NEW / needs packing)
|--------------------------------------------------------------------------
*/
require_once __DIR__ . '/module_access.php';

function pr_ensure_schema(PDO $pdo): void
{
    static $done = false;
    if ($done) return;
    try {
        ma_ensure_table($pdo);
        // pipeline_role on the access table
        if (!$pdo->query("SHOW COLUMNS FROM company_module_staff LIKE 'pipeline_role'")->fetch()) {
            $pdo->exec("ALTER TABLE company_module_staff ADD COLUMN pipeline_role VARCHAR(20) NULL");
        }
        // workflow columns on the requests table (only if it exists)
        if ($pdo->query("SHOW TABLES LIKE 'sp_part_requests'")->fetch()) {
            $cols = [
                'machine_model'        => 'VARCHAR(255) NULL',
                'serial_no'            => 'VARCHAR(100) NULL',
                'packed_by_user_id'    => 'INT NULL',
                'packed_at'            => 'DATETIME NULL',
                'packing_note'         => 'VARCHAR(255) NULL',
                'ready_by_user_id'     => 'INT NULL',
                'ready_at'             => 'DATETIME NULL',
                'received_by_user_id'  => 'INT NULL',
                'received_at'          => 'DATETIME NULL',
                'completed_by_user_id' => 'INT NULL',
                'completed_at'         => 'DATETIME NULL',
            ];
            foreach ($cols as $name => $def) {
                if (!$pdo->query("SHOW COLUMNS FROM sp_part_requests LIKE '$name'")->fetch()) {
                    $pdo->exec("ALTER TABLE sp_part_requests ADD COLUMN $name $def");
                }
            }
        }
    } catch (Throwable $e) { /* ignore */ }
    $done = true;
}

/* Current pipeline role: 'manager' | 'stock' | 'packing' | 'requester' | 'none'. */
function pr_role(PDO $pdo, int $companyId, int $userId, ?string $role): string
{
    if (($role ?? '') === 'company_admin') return 'manager';
    try {
        pr_ensure_schema($pdo);
        $st = $pdo->prepare("SELECT pipeline_role, access_level, can_edit FROM company_module_staff
                             WHERE company_id=? AND user_id=? AND module_key='part_request' LIMIT 1");
        $st->execute([$companyId, $userId]);
        $r = $st->fetch(PDO::FETCH_ASSOC);
        if (!$r) return 'none';
        $pr = $r['pipeline_role'] ?? '';
        if (in_array($pr, ['requester','packing','stock','manager'], true)) return $pr;
        // legacy fallback from access_level
        $lvl = $r['access_level'] ?? '';
        if ($lvl === 'manage' || (int)($r['can_edit'] ?? 0) === 1) return 'manager';
        if (in_array($lvl, ['view','edit'], true)) return 'requester';
        return 'none';
    } catch (Throwable $e) { return 'none'; }
}

function pr_can_create(string $prole): bool { return in_array($prole, ['requester','packing','stock','manager'], true); }
function pr_can_pack(string $prole): bool   { return in_array($prole, ['packing','manager'], true); }
function pr_can_stock(string $prole): bool  { return in_array($prole, ['stock','manager'], true); }
function pr_can_queue(string $prole): bool  { return in_array($prole, ['packing','stock','manager'], true); }

/* Human label for a role. */
function pr_role_label(string $prole): string
{
    switch ($prole) {
        case 'manager':   return 'Manager (all stages)';
        case 'stock':     return 'Stock — deduct & complete';
        case 'packing':   return 'Packing — make packing list';
        case 'requester': return 'Requester — create only';
        default:          return 'No access';
    }
}

/* Set a staff member's pipeline role. '' / 'none' removes access. */
function pr_set_role(PDO $pdo, int $companyId, int $userId, string $prole): void
{
    pr_ensure_schema($pdo);
    if (!in_array($prole, ['requester','packing','stock','manager'], true)) {
        $pdo->prepare("DELETE FROM company_module_staff WHERE company_id=? AND user_id=? AND module_key='part_request'")
            ->execute([$companyId, $userId]);
        return;
    }
    $canEdit     = in_array($prole, ['packing','stock','manager'], true) ? 1 : 0;
    $accessLevel = ($prole === 'manager') ? 'manage' : (($prole === 'requester') ? 'view' : 'edit');
    $pdo->prepare("
        INSERT INTO company_module_staff (company_id, user_id, module_key, can_edit, access_level, pipeline_role)
        VALUES (?, ?, 'part_request', ?, ?, ?)
        ON DUPLICATE KEY UPDATE can_edit=VALUES(can_edit), access_level=VALUES(access_level), pipeline_role=VALUES(pipeline_role)
    ")->execute([$companyId, $userId, $canEdit, $accessLevel, $prole]);
}

/* Map of user_id => pipeline role for this company (assigned staff only). */
function pr_role_map(PDO $pdo, int $companyId): array
{
    try {
        pr_ensure_schema($pdo);
        $st = $pdo->prepare("SELECT user_id, pipeline_role, access_level, can_edit FROM company_module_staff
                             WHERE company_id=? AND module_key='part_request'");
        $st->execute([$companyId]);
        $out = [];
        foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $r) {
            $pr = $r['pipeline_role'] ?? '';
            if (!in_array($pr, ['requester','packing','stock','manager'], true)) {
                $lvl = $r['access_level'] ?? '';
                if ($lvl === 'manage' || (int)($r['can_edit'] ?? 0) === 1) $pr = 'manager';
                elseif (in_array($lvl, ['view','edit'], true)) $pr = 'requester';
                else $pr = 'none';
            }
            if ($pr !== 'none') $out[(int)$r['user_id']] = $pr;
        }
        return $out;
    } catch (Throwable $e) { return []; }
}

/* Which pipeline stage a status belongs to: 'new' | 'packed' | 'completed'. */
function pr_stage(?string $status): string
{
    $s = strtolower((string)$status);
    if ($s === 'completed') return 'completed';
    if ($s === 'ready')     return 'ready';   // stock done, waiting for creator to pick up
    if ($s === 'packed')    return 'packed';
    return 'new'; // open, incomplete, blank, anything else
}

/* Badge/label for a status. Returns [label, fg, bg]. */
function pr_status_badge(?string $status): array
{
    switch (pr_stage($status)) {
        case 'completed': return ['Completed', '#166534', '#dcfce7'];
        case 'ready':     return ['Ready to pick up', '#15803d', '#bbf7d0'];
        case 'packed':    return ['Packed → Stock', '#9a3412', '#ffedd5'];
        default:          return ['New request', '#1e40af', '#dbeafe'];
    }
}

/* Company-wide pending counts per stage. */
function pr_pending_counts(PDO $pdo, int $companyId): array
{
    try {
        $st = $pdo->prepare("SELECT status, COUNT(*) c FROM sp_part_requests WHERE company_id=? GROUP BY status");
        $st->execute([$companyId]);
        $new = 0; $packed = 0;
        foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $r) {
            $stg = pr_stage($r['status']);
            if ($stg === 'new')    $new    += (int)$r['c'];
            elseif ($stg === 'packed') $packed += (int)$r['c'];
        }
        return ['new' => $new, 'packed' => $packed];
    } catch (Throwable $e) {
        return ['new' => 0, 'packed' => 0];
    }
}

/* How many of THIS user's own requests are ready to pick up (for the creator badge). */
function pr_ready_for_creator(PDO $pdo, int $companyId, int $userId): int
{
    try {
        $q = $pdo->prepare("SELECT COUNT(*) FROM sp_part_requests WHERE company_id=? AND issued_by_user_id=? AND status='ready'");
        $q->execute([$companyId, $userId]);
        return (int)$q->fetchColumn();
    } catch (Throwable $e) { return 0; }
}

/* Notification badge count for a given role (items waiting at THEIR stage). */
function pr_badge_count(PDO $pdo, int $companyId, string $prole): int
{
    $c = pr_pending_counts($pdo, $companyId);
    if ($prole === 'packing') return $c['new'];
    if ($prole === 'stock')   return $c['packed'];
    if ($prole === 'manager') return $c['new'] + $c['packed'];
    return 0;
}