<?php

namespace Modules\Workflows\Controllers;

use Gestoreasy\Core\Http\Request;
use Gestoreasy\Core\Http\Response;
use Gestoreasy\Core\Tenant\ConnectionManager;
use Modules\Workflows\Services\WorkflowEngine;
use PDO;

class WorkflowsController {
    /**
     * Lista workflows
     */
    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 = [];
            $params = [];

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

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

            $whereSql = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

            $sql = "SELECT * FROM workflows WHERE tenant_id = ? {$whereSql} ORDER BY id DESC LIMIT ? OFFSET ?";
            $stmt = $pdo->prepare($sql);
            $stmt->execute(array_merge([$tenantId], $params, [$per, $offset]));
            $workflows = $stmt->fetchAll(PDO::FETCH_ASSOC);

            // Total
            $countSql = "SELECT COUNT(*) FROM workflows WHERE tenant_id = ? {$whereSql}";
            $countStmt = $pdo->prepare($countSql);
            $countStmt->execute(array_merge([$tenantId], $params));
            $total = (int)$countStmt->fetchColumn();

            return Response::json([
                'data' => $workflows,
                '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()]]);
        }
    }

    /**
     * Obtém workflow por ID
     */
    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 * FROM workflows WHERE id = ? AND tenant_id = ?');
            $stmt->execute([$id, $tenantId]);
            $workflow = $stmt->fetch(PDO::FETCH_ASSOC);

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

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

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

            $nome = $body['nome'] ?? '';
            $descricao = $body['descricao'] ?? null;
            $categoria = $body['categoria'] ?? null;
            $triggerType = $body['trigger_type'] ?? 'manual';
            $triggerConfig = $body['trigger_config'] ?? null;
            $definition = $body['definition'] ?? [];

            if (!$nome) {
                return new Response(422, ['error' => ['code' => 'validation_error', 'message' => 'Nome é obrigatório']]);
            }

            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            $userId = $userContext?->userId;

            $stmt = $pdo->prepare('
                INSERT INTO workflows 
                (tenant_id, nome, descricao, categoria, trigger_type, trigger_config, definition, created_by)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?)
            ');
            $stmt->execute([
                $tenantId,
                $nome,
                $descricao,
                $categoria,
                $triggerType,
                $triggerConfig ? json_encode($triggerConfig) : null,
                json_encode($definition),
                $userId
            ]);

            $id = (int)$pdo->lastInsertId();

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

    /**
     * Atualiza workflow
     */
    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 : [];

            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            $userId = $userContext?->userId;

            $updates = [];
            $params = [];

            $allowedFields = ['nome', 'descricao', 'categoria', 'trigger_type', 'trigger_config', 'definition', 'status'];
            foreach ($allowedFields as $field) {
                if (isset($body[$field])) {
                    if ($field === 'trigger_config' || $field === 'definition') {
                        $updates[] = "{$field} = ?";
                        $params[] = json_encode($body[$field]);
                    } else {
                        $updates[] = "{$field} = ?";
                        $params[] = $body[$field];
                    }
                }
            }

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

            $updates[] = 'updated_by = ?';
            $params[] = $userId;
            $params[] = $id;
            $params[] = $tenantId;

            $sql = 'UPDATE workflows 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()]]);
        }
    }

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

            $stmt = $pdo->prepare('DELETE FROM workflows WHERE id = ? AND tenant_id = ?');
            $stmt->execute([$id, $tenantId]);

            if ($stmt->rowCount() === 0) {
                return new Response(404, ['error' => ['code' => 'not_found', 'message' => 'Workflow não encontrado']]);
            }

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

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

            $engine = new WorkflowEngine($tenantId);
            $result = $engine->execute($id, $inputData);

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

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

            $stmt = $pdo->prepare('UPDATE workflows SET ativo = TRUE, status = "ativo" 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()]]);
        }
    }

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

            $stmt = $pdo->prepare('UPDATE workflows SET ativo = FALSE, status = "inativo" 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()]]);
        }
    }

    /**
     * Obtém logs de execução
     */
    public function getLogs(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $pdo = ConnectionManager::forTenant();
            $id = (int)($req->get('params')[0] ?? 0);
            $page = max(1, (int)($req->query['page'] ?? 1));
            $per = min(100, max(1, (int)($req->query['per_page'] ?? 20)));
            $offset = ($page - 1) * $per;

            $sql = "
                SELECT e.*, COUNT(l.id) as logs_count
                FROM workflow_executions e
                LEFT JOIN workflow_execution_logs l ON e.id = l.execution_id
                WHERE e.workflow_id = ? AND e.tenant_id = ?
                GROUP BY e.id
                ORDER BY e.created_at DESC
                LIMIT ? OFFSET ?
            ";
            $stmt = $pdo->prepare($sql);
            $stmt->execute([$id, $tenantId, $per, $offset]);
            $executions = $stmt->fetchAll(PDO::FETCH_ASSOC);

            // Total
            $countStmt = $pdo->prepare('SELECT COUNT(*) FROM workflow_executions WHERE workflow_id = ? AND tenant_id = ?');
            $countStmt->execute([$id, $tenantId]);
            $total = (int)$countStmt->fetchColumn();

            return Response::json([
                'data' => $executions,
                '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()]]);
        }
    }

    /**
     * Obtém estatísticas do workflow
     */
    public function getStats(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $pdo = ConnectionManager::forTenant();
            $id = (int)($req->get('params')[0] ?? 0);

            $stmt = $pdo->prepare('
                SELECT 
                    execucoes_total,
                    execucoes_sucesso,
                    execucoes_erro,
                    ultima_execucao,
                    CASE 
                        WHEN execucoes_total > 0 
                        THEN (execucoes_sucesso * 100.0 / execucoes_total)
                        ELSE 0 
                    END as taxa_sucesso
                FROM workflows
                WHERE id = ? AND tenant_id = ?
            ');
            $stmt->execute([$id, $tenantId]);
            $stats = $stmt->fetch(PDO::FETCH_ASSOC);

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

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

    /**
     * Lista aprovações pendentes
     */
    public function listApprovals(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            $userId = $userContext?->userId;

            $approvalService = new \Modules\Workflows\Services\ApprovalService($tenantId);
            $approvals = $approvalService->listPending($userId);

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

    /**
     * Obtém aprovação por ID
     */
    public function getApproval(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $approvalId = (int)($req->get('params')[0] ?? 0);

            $approvalService = new \Modules\Workflows\Services\ApprovalService($tenantId);
            $approval = $approvalService->getApproval($approvalId);

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

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

    /**
     * Aprova uma aprovação
     */
    public function approveApproval(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $approvalId = (int)($req->get('params')[0] ?? 0);
            $body = is_array($req->body) ? $req->body : [];
            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            $userId = $userContext?->userId;

            if (!$userId) {
                return new Response(401, ['error' => ['code' => 'unauthorized', 'message' => 'Usuário não autenticado']]);
            }

            $comentario = $body['comentario'] ?? null;

            $approvalService = new \Modules\Workflows\Services\ApprovalService($tenantId);
            $approved = $approvalService->approve($approvalId, $userId, $comentario);

            return Response::json([
                'data' => [
                    'success' => true,
                    'approved' => $approved,
                    'message' => $approved ? 'Aprovação concluída' : 'Aprovação registrada, aguardando outros aprovadores'
                ]
            ]);
        } catch (\Exception $e) {
            return new Response(500, ['error' => ['code' => 'error', 'message' => $e->getMessage()]]);
        }
    }

    /**
     * Rejeita uma aprovação
     */
    public function rejectApproval(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $approvalId = (int)($req->get('params')[0] ?? 0);
            $body = is_array($req->body) ? $req->body : [];
            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            $userId = $userContext?->userId;

            if (!$userId) {
                return new Response(401, ['error' => ['code' => 'unauthorized', 'message' => 'Usuário não autenticado']]);
            }

            $motivo = $body['motivo'] ?? 'Rejeitado pelo usuário';

            $approvalService = new \Modules\Workflows\Services\ApprovalService($tenantId);
            $approvalService->reject($approvalId, $userId, $motivo);

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

    /**
     * Lista notificações do usuário
     */
    public function listNotifications(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            $userId = $userContext?->userId;

            if (!$userId) {
                return new Response(401, ['error' => ['code' => 'unauthorized', 'message' => 'Usuário não autenticado']]);
            }

            $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['lida'])) {
                $filters['lida'] = (bool)$req->query['lida'];
            }

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

            $notificationService = new \Modules\Workflows\Services\NotificationService($tenantId);
            $notifications = $notificationService->list($userId, $filters);

            // Total
            $total = count($notificationService->list($userId, ['limit' => 10000]));

            return Response::json([
                'data' => $notifications,
                '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()]]);
        }
    }

    /**
     * Conta notificações não lidas
     */
    public function getUnreadCount(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            $userId = $userContext?->userId;

            if (!$userId) {
                return new Response(401, ['error' => ['code' => 'unauthorized', 'message' => 'Usuário não autenticado']]);
            }

            $notificationService = new \Modules\Workflows\Services\NotificationService($tenantId);
            $count = $notificationService->countUnread($userId);

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

    /**
     * Marca notificação como lida
     */
    public function markNotificationAsRead(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $notificationId = (int)($req->get('params')[0] ?? 0);
            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            $userId = $userContext?->userId;

            if (!$userId) {
                return new Response(401, ['error' => ['code' => 'unauthorized', 'message' => 'Usuário não autenticado']]);
            }

            $notificationService = new \Modules\Workflows\Services\NotificationService($tenantId);
            $success = $notificationService->markAsRead($notificationId, $userId);

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

    /**
     * Marca todas as notificações como lidas
     */
    public function markAllNotificationsAsRead(Request $req): Response {
        try {
            $tenantId = \Gestoreasy\Core\Tenant\TenantContext::getTenantId();
            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            $userId = $userContext?->userId;

            if (!$userId) {
                return new Response(401, ['error' => ['code' => 'unauthorized', 'message' => 'Usuário não autenticado']]);
            }

            $notificationService = new \Modules\Workflows\Services\NotificationService($tenantId);
            $count = $notificationService->markAllAsRead($userId);

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

