<?php

namespace Modules\PCP\Controllers;

use Gestoreasy\Core\Http\Request;
use Gestoreasy\Core\Http\Response;
use Gestoreasy\Core\Tenant\ConnectionManager;
use Modules\PCP\Services\ProductionOrderService;
use PDO;

class ProductionOrdersController {
    public function list(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $pdo = ConnectionManager::forTenant();
            
            $page = max(1, (int)($req->query['page'] ?? 1));
            $per = min(100, max(1, (int)($req->query['per_page'] ?? 20)));
            $offset = ($page - 1) * $per;

            $where = ['tenant_id = ?'];
            $params = [$tenantId];

            if (!empty($req->query['status'])) {
                $where[] = 'status = ?';
                $params[] = $req->query['status'];
            }

            if (!empty($req->query['product_id'])) {
                $where[] = 'product_id = ?';
                $params[] = $req->query['product_id'];
            }

            $whereSql = implode(' AND ', $where);

            $sql = "SELECT o.*, p.codigo as produto_codigo, p.nome as produto_nome
                    FROM production_orders o
                    INNER JOIN products p ON o.product_id = p.id
                    WHERE {$whereSql}
                    ORDER BY o.created_at DESC
                    LIMIT ? OFFSET ?";
            $stmt = $pdo->prepare($sql);
            $stmt->execute(array_merge($params, [$per, $offset]));
            $ordens = $stmt->fetchAll(PDO::FETCH_ASSOC);

            // Total
            $countSql = "SELECT COUNT(*) FROM production_orders WHERE {$whereSql}";
            $countStmt = $pdo->prepare($countSql);
            $countStmt->execute($params);
            $total = (int)$countStmt->fetchColumn();

            return Response::json([
                'data' => $ordens,
                'pagination' => [
                    'page' => $page,
                    'per_page' => $per,
                    'total' => $total,
                    'total_pages' => (int)ceil($total / $per)
                ]
            ]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    public function get(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $pdo = ConnectionManager::forTenant();
            $id = (int)($req->get('params')[0] ?? 0);

            $stmt = $pdo->prepare('
                SELECT o.*, p.codigo as produto_codigo, p.nome as produto_nome
                FROM production_orders o
                INNER JOIN products p ON o.product_id = p.id
                WHERE o.id = ? AND o.tenant_id = ?
            ');
            $stmt->execute([$id, $tenantId]);
            $ordem = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$ordem) {
                return new Response(404, ['error' => ['code' => 'not_found', 'message' => 'Ordem não encontrada']]);
            }

            // Buscar apontamentos
            $stmt = $pdo->prepare('
                SELECT * FROM production_apontamentos
                WHERE order_id = ? AND tenant_id = ?
                ORDER BY created_at ASC
            ');
            $stmt->execute([$id, $tenantId]);
            $ordem['apontamentos'] = $stmt->fetchAll(PDO::FETCH_ASSOC);

            // Buscar consumo de materiais
            $stmt = $pdo->prepare('
                SELECT mc.*, p.codigo as material_codigo, p.nome as material_nome
                FROM production_material_consumption mc
                INNER JOIN products p ON mc.material_product_id = p.id
                WHERE mc.order_id = ? AND mc.tenant_id = ?
            ');
            $stmt->execute([$id, $tenantId]);
            $ordem['materiais'] = $stmt->fetchAll(PDO::FETCH_ASSOC);

            // Buscar reservas
            $service = new ProductionOrderService($tenantId);
            $ordem['reservas'] = $service->listarReservas($id);

            return Response::json(['data' => $ordem]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    public function create(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $body = is_array($req->body) ? $req->body : [];

            $service = new ProductionOrderService($tenantId);
            $orderId = $service->criarOrdem($body);

            return Response::json(['data' => ['id' => $orderId]], 201);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    public function update(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $pdo = ConnectionManager::forTenant();
            $id = (int)($req->get('params')[0] ?? 0);
            $body = is_array($req->body) ? $req->body : [];

            $allowedFields = ['quantidade_solicitada', 'data_inicio_prevista', 'data_fim_prevista', 'prioridade', 'observacoes'];
            $updates = [];
            $params = [];

            foreach ($allowedFields as $field) {
                if (isset($body[$field])) {
                    $updates[] = "{$field} = ?";
                    $params[] = $body[$field];
                }
            }

            if (empty($updates)) {
                return new Response(422, ['error' => ['code' => 'validation_error', 'message' => 'Nenhum campo para atualizar']]);
            }

            $params[] = $id;
            $params[] = $tenantId;

            $sql = 'UPDATE production_orders SET ' . implode(', ', $updates) . ' WHERE id = ? AND tenant_id = ?';
            $stmt = $pdo->prepare($sql);
            $stmt->execute($params);

            return Response::json(['data' => ['success' => true]]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    public function delete(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $id = (int)($req->get('params')[0] ?? 0);

            $service = new ProductionOrderService($tenantId);
            $service->cancelarOrdem($id);

            // Deletar ordem
            $pdo = ConnectionManager::forTenant();
            $stmt = $pdo->prepare('DELETE FROM production_orders WHERE id = ? AND tenant_id = ?');
            $stmt->execute([$id, $tenantId]);

            return Response::json(['data' => ['success' => true]]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    public function cancelar(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $id = (int)($req->get('params')[0] ?? 0);

            $service = new ProductionOrderService($tenantId);
            $service->cancelarOrdem($id);

            return Response::json(['data' => ['success' => true]]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    public function aprovar(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $id = (int)($req->get('params')[0] ?? 0);

            $service = new ProductionOrderService($tenantId);
            $service->aprovarOrdem($id);

            return Response::json(['data' => ['success' => true]]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    public function iniciar(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $id = (int)($req->get('params')[0] ?? 0);

            $service = new ProductionOrderService($tenantId);
            $service->iniciarProducao($id);

            return Response::json(['data' => ['success' => true]]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    public function finalizar(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $id = (int)($req->get('params')[0] ?? 0);
            $body = is_array($req->body) ? $req->body : [];

            $service = new ProductionOrderService($tenantId);
            $service->finalizarProducao($id, $body);

            return Response::json(['data' => ['success' => true]]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    public function apontar(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $id = (int)($req->get('params')[0] ?? 0);
            $body = is_array($req->body) ? $req->body : [];

            $service = new ProductionOrderService($tenantId);
            $service->apontarProducao($id, $body);

            return Response::json(['data' => ['success' => true]]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Lista reservas de uma ordem
     */
    public function listReservas(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $id = (int)($req->get('params')[0] ?? 0);

            $service = new ProductionOrderService($tenantId);
            $reservas = $service->listarReservas($id);

            return Response::json(['data' => $reservas]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Libera reserva
     */
    public function liberarReserva(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $reservaId = (int)($req->get('params')[0] ?? 0);
            $body = is_array($req->body) ? $req->body : [];

            $service = new ProductionOrderService($tenantId);
            $service->liberarReserva($reservaId, $body['quantidade'] ?? null);

            return Response::json(['data' => ['success' => true]]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Lista alertas de estoque
     */
    public function listAlertas(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $page = max(1, (int)($req->query['page'] ?? 1));
            $per = min(100, max(1, (int)($req->query['per_page'] ?? 20)));
            $offset = ($page - 1) * $per;

            $filters = [
                'limit' => $per,
                'offset' => $offset
            ];

            if (!empty($req->query['status'])) {
                $filters['status'] = $req->query['status'];
            }

            if (!empty($req->query['severidade'])) {
                $filters['severidade'] = $req->query['severidade'];
            }

            if (!empty($req->query['production_order_id'])) {
                $filters['production_order_id'] = (int)$req->query['production_order_id'];
            }

            $service = new ProductionOrderService($tenantId);
            $alertas = $service->listarAlertas($filters);

            // Total
            $totalFilters = array_merge($filters, ['limit' => 10000, 'offset' => 0]);
            $totalAlertas = $service->listarAlertas($totalFilters);
            $total = count($totalAlertas);

            return Response::json([
                'data' => $alertas,
                'pagination' => [
                    'page' => $page,
                    'per_page' => $per,
                    'total' => $total,
                    'total_pages' => (int)ceil($total / $per)
                ]
            ]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }
}

