<?php
namespace Modules\Compras\Controllers;

use Gestoreasy\Core\Http\Request;
use Gestoreasy\Core\Http\Response;
use Gestoreasy\Core\Tenant\ConnectionManager;
use Gestoreasy\Core\Audit\AuditLogger;
use Gestoreasy\Core\Validation\Br;

class SuppliersController {
    public function list(Request $r): Response {
        $pdo = ConnectionManager::forTenant();
        $page = max(1, (int)($r->query['page'] ?? 1));
        $per = min(100, max(1, (int)($r->query['per_page'] ?? 20)));
        $offset = ($page - 1) * $per;
        $q = trim((string)($r->query['q'] ?? ''));
        $where = [];
        $params = [];
        if ($q !== '') {
            $where[] = '(nome LIKE :q OR cnpj LIKE :q OR email LIKE :q OR contato LIKE :q)';
            $params['q'] = '%' . $q . '%';
        }
        $whereSql = $where ? ('WHERE ' . implode(' AND ', $where)) : '';

        $sql = "SELECT id, nome, cnpj, email, contato, created_at FROM suppliers $whereSql ORDER BY id DESC LIMIT :limit OFFSET :offset";
        $stmt = $pdo->prepare($sql);
        foreach ($params as $k => $v) { $stmt->bindValue(':' . $k, $v); }
        $stmt->bindValue(':limit', $per, \PDO::PARAM_INT);
        $stmt->bindValue(':offset', $offset, \PDO::PARAM_INT);
        $stmt->execute();
        $rows = $stmt->fetchAll();

        $countSql = "SELECT COUNT(*) AS c FROM suppliers $whereSql";
        $countStmt = $pdo->prepare($countSql);
        foreach ($params as $k => $v) { $countStmt->bindValue(':' . $k, $v); }
        $countStmt->execute();
        $total = (int)($countStmt->fetch()['c'] ?? 0);

        AuditLogger::logRead('suppliers', null, ['endpoint' => 'compras.fornecedores.list', 'page' => $page, 'per_page' => $per, 'q' => $q]);
        return Response::json(['data' => $rows, 'page' => $page, 'per_page' => $per, 'total' => $total, 'total_pages' => (int)ceil($total / $per)]);
    }

    public function getById(Request $r): Response {
        $pdo = ConnectionManager::forTenant();
        $id = (int)(($r->get('params', [])[0]) ?? 0);
        if ($id <= 0) return new Response(422, ['error' => ['code' => 'invalid_id', 'message' => 'ID inválido']]);
        $stmt = $pdo->prepare('SELECT id, nome, cnpj, email, contato, created_at FROM suppliers WHERE id = ? LIMIT 1');
        $stmt->execute([$id]);
        $row = $stmt->fetch();
        if (!$row) return new Response(404, ['error' => ['code' => 'not_found', 'message' => 'Fornecedor não encontrado']]);
        AuditLogger::logRead('suppliers', $id, ['endpoint' => 'compras.fornecedores.get_by_id']);
        return Response::json(['data' => $row]);
    }

    public function create(Request $r): Response {
        $pdo = ConnectionManager::forTenant();
        $data = $r->body;
        $nome = trim((string)($data['nome'] ?? ''));
        $cnpj = trim((string)($data['cnpj'] ?? ''));
        $email = trim((string)($data['email'] ?? ''));
        $contato = trim((string)($data['contato'] ?? ''));
        if ($nome === '') return new Response(422, ['error' => ['code' => 'nome_required', 'message' => 'Nome é obrigatório']]);
        if ($cnpj !== '' && !Br::isCNPJ($cnpj)) return new Response(422, ['error' => ['code' => 'invalid_cnpj', 'message' => 'CNPJ inválido']]);
        if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) return new Response(422, ['error' => ['code' => 'invalid_email', 'message' => 'E-mail inválido']]);
        $stmt = $pdo->prepare('INSERT INTO suppliers (nome, cnpj, email, contato) VALUES (?, ?, ?, ?)');
        $stmt->execute([$nome, $cnpj !== '' ? $cnpj : null, $email !== '' ? $email : null, $contato !== '' ? $contato : null]);
        $newId = (int)$pdo->lastInsertId();
        AuditLogger::logCreate('suppliers', $newId, ['nome' => $nome, 'cnpj' => $cnpj !== '' ? $cnpj : null, 'email' => $email !== '' ? $email : null, 'contato' => $contato !== '' ? $contato : null]);
        return Response::json(['ok' => true, 'id' => $newId], 201);
    }

    public function update(Request $r): Response {
        $pdo = ConnectionManager::forTenant();
        $id = (int)(($r->get('params', [])[0]) ?? 0);
        if ($id <= 0) return new Response(422, ['error' => ['code' => 'invalid_id', 'message' => 'ID inválido']]);
        $data = $r->body;
        $nome = $data['nome'] ?? null;
        $cnpj = $data['cnpj'] ?? null;
        $email = array_key_exists('email', $data) ? (string)$data['email'] : null;
        $contato = array_key_exists('contato', $data) ? (string)$data['contato'] : null;
        if ($cnpj !== null && $cnpj !== '' && !Br::isCNPJ($cnpj)) return new Response(422, ['error' => ['code' => 'invalid_cnpj', 'message' => 'CNPJ inválido']]);
        if ($email !== null && $email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) return new Response(422, ['error' => ['code' => 'invalid_email', 'message' => 'E-mail inválido']]);
        $beforeStmt = $pdo->prepare('SELECT id, nome, cnpj, email, contato FROM suppliers WHERE id = ? LIMIT 1');
        $beforeStmt->execute([$id]);
        $before = $beforeStmt->fetch();
        if (!$before) return new Response(404, ['error' => ['code' => 'not_found', 'message' => 'Fornecedor não encontrado']]);
        $stmt = $pdo->prepare('UPDATE suppliers SET nome = COALESCE(?, nome), cnpj = COALESCE(?, cnpj), email = COALESCE(?, email), contato = COALESCE(?, contato) WHERE id = ?');
        $stmt->execute([$nome, $cnpj, $email, $contato, $id]);
        $after = $before;
        if ($nome !== null) $after['nome'] = $nome;
        if ($cnpj !== null) $after['cnpj'] = $cnpj;
        if ($email !== null) $after['email'] = $email;
        if ($contato !== null) $after['contato'] = $contato;
        AuditLogger::logUpdate('suppliers', $id, $before ?: [], $after ?: [], ['endpoint' => 'compras.fornecedores.update']);
        return Response::json(['ok' => true]);
    }

    public function delete(Request $r): Response {
        $pdo = ConnectionManager::forTenant();
        $id = (int)(($r->get('params', [])[0]) ?? 0);
        if ($id <= 0) return new Response(422, ['error' => ['code' => 'invalid_id', 'message' => 'ID inválido']]);
        $beforeStmt = $pdo->prepare('SELECT id, nome, cnpj, contato FROM suppliers WHERE id = ? LIMIT 1');
        $beforeStmt->execute([$id]);
        $before = $beforeStmt->fetch();
        if (!$before) return new Response(404, ['error' => ['code' => 'not_found', 'message' => 'Fornecedor não encontrado']]);
        $stmt = $pdo->prepare('DELETE FROM suppliers WHERE id = ?');
        $stmt->execute([$id]);
        AuditLogger::logDelete('suppliers', $id, $before ?: [], ['endpoint' => 'compras.fornecedores.delete']);
        return Response::json(['ok' => true]);
    }
}