<?php
/**
 * Sites Controller
 * Gerencia CRUD de sites
 */

namespace Controllers;

use Core\Request;
use Core\Response;
use Middleware\Auth;

class SitesController
{
    /**
     * Verificar se tabela existe
     */
    private static function tableExists(string $tableName): bool
    {
        $pdo = getDBConnection();
        try {
            $stmt = $pdo->query("SHOW TABLES LIKE '{$tableName}'");
            return $stmt->rowCount() > 0;
        } catch (\Exception $e) {
            return false;
        }
    }
    
    /**
     * Verificar se coluna existe na tabela
     */
    private static function columnExists(string $table, string $column): bool
    {
        $pdo = getDBConnection();
        try {
            $stmt = $pdo->query("SHOW COLUMNS FROM {$table} LIKE '{$column}'");
            return $stmt->rowCount() > 0;
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * GET /sites - Listar todos os sites
     */
    public static function index(): void
    {
        $currentUser = Auth::require();
        $pdo = getDBConnection();
        
        // Verificar se as tabelas/colunas necessárias existem
        $hasApiTokens = self::tableExists('api_tokens') && self::columnExists('sites', 'api_token_id');
        $hasEvents = self::tableExists('events');
        
        // Construir query dinamicamente
        $selectFields = "s.*";
        $joins = "";
        
        if ($hasApiTokens) {
            $selectFields .= ", at.name as api_token_name";
            $joins .= " LEFT JOIN api_tokens at ON at.id = s.api_token_id";
        }
        
        if ($hasEvents) {
            $selectFields .= ", COALESCE(e.total_events, 0) as total_events";
            $selectFields .= ", COALESCE(e.events_today, 0) as events_today";
            $selectFields .= ", COALESCE(e.unique_visitors, 0) as unique_visitors";
            $joins .= " LEFT JOIN (
                SELECT 
                    site_id,
                    COUNT(*) as total_events,
                    SUM(CASE WHEN DATE(created_at) = CURDATE() THEN 1 ELSE 0 END) as events_today,
                    COUNT(DISTINCT visitor_id) as unique_visitors
                FROM events
                GROUP BY site_id
            ) e ON e.site_id = s.id";
        }

        // Se for usuário de site, só pode ver seu próprio site
        if (!Auth::isSuperAdmin($currentUser) && !empty($currentUser['site_id'])) {
            $sql = "SELECT {$selectFields} FROM sites s {$joins} WHERE s.id = ?";
            $stmt = $pdo->prepare($sql);
            $stmt->execute([$currentUser['site_id']]);
        } else {
            // Super admin vê todos os sites
            $sql = "SELECT {$selectFields} FROM sites s {$joins} ORDER BY s.created_at DESC";
            $stmt = $pdo->query($sql);
        }

        $sites = $stmt->fetchAll();

        // Mascarar API keys
        foreach ($sites as &$site) {
            $site['api_key_masked'] = substr($site['api_key'], 0, 8) . '...' . substr($site['api_key'], -4);
            unset($site['api_secret']);
            
            // Garantir que campos existam (valores padrão)
            if (!isset($site['total_events'])) $site['total_events'] = 0;
            if (!isset($site['events_today'])) $site['events_today'] = 0;
            if (!isset($site['unique_visitors'])) $site['unique_visitors'] = 0;
            if (!isset($site['api_token_name'])) $site['api_token_name'] = null;
        }

        Response::success($sites);
    }

    /**
     * POST /sites - Criar novo site (apenas super admin)
     */
    public static function create(): void
    {
        Auth::requireSuperAdmin();

        $name = Request::input('name', '');
        $domain = Request::input('domain', '');

        if (!$name || !$domain) {
            Response::error('Name and domain required', 400);
        }

        $apiKey = generateApiKey();
        $apiSecret = generateSecureToken(64);

        $pdo = getDBConnection();
        
        // Verificar se a coluna api_token_id existe
        $hasApiTokenColumn = false;
        try {
            $checkCol = $pdo->query("SHOW COLUMNS FROM sites LIKE 'api_token_id'");
            $hasApiTokenColumn = $checkCol->rowCount() > 0;
        } catch (\Exception $e) {
            // Ignorar erro, assumir que não existe
        }
        
        if ($hasApiTokenColumn) {
            // API Token ID (opcional)
            $apiTokenId = Request::input('api_token_id', null);
            if ($apiTokenId !== null) {
                $apiTokenId = (int)$apiTokenId;
                if ($apiTokenId <= 0) {
                    $apiTokenId = null;
                }
            }
            
            $stmt = $pdo->prepare("
                INSERT INTO sites (name, domain, api_key, api_secret, description, rate_limit, api_token_id)
                VALUES (?, ?, ?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                $name,
                $domain,
                $apiKey,
                $apiSecret,
                Request::input('description', ''),
                Request::input('rate_limit', 1000),
                $apiTokenId
            ]);
        } else {
            // Tabela sem coluna api_token_id (schema antigo)
            $stmt = $pdo->prepare("
                INSERT INTO sites (name, domain, api_key, api_secret, description, rate_limit)
                VALUES (?, ?, ?, ?, ?, ?)
            ");
            $stmt->execute([
                $name,
                $domain,
                $apiKey,
                $apiSecret,
                Request::input('description', ''),
                Request::input('rate_limit', 1000)
            ]);
        }

        $siteId = $pdo->lastInsertId();

        logAudit('site_created', $siteId, "Site: {$name}", Request::ip());

        Response::success([
            'id' => $siteId,
            'name' => $name,
            'domain' => $domain,
            'api_key' => $apiKey,
            'api_secret' => $apiSecret
        ], 'Site created');
    }

    /**
     * GET /site?id={id} - Obter site específico
     */
    public static function show(): void
    {
        $siteId = (int)Request::get('id', 0);

        if (!$siteId) {
            Response::error('Site ID required', 400);
        }

        Auth::requireSiteAccess($siteId);

        $pdo = getDBConnection();
        
        // Verificar se tabelas existem
        $hasApiTokens = self::tableExists('api_tokens') && self::columnExists('sites', 'api_token_id');
        $hasEvents = self::tableExists('events');
        
        // Construir query dinamicamente
        $selectFields = "s.*";
        $joins = "";
        
        if ($hasApiTokens) {
            $selectFields .= ", at.name as api_token_name";
            $joins .= " LEFT JOIN api_tokens at ON at.id = s.api_token_id";
        }
        
        if ($hasEvents) {
            $selectFields .= ", COALESCE(e.total_events, 0) as total_events";
            $selectFields .= ", COALESCE(e.unique_visitors, 0) as unique_visitors";
            $selectFields .= ", COALESCE(e.pix_count, 0) as pix_count";
            $selectFields .= ", COALESCE(e.pix_value, 0) as pix_value";
            $joins .= " LEFT JOIN (
                SELECT 
                    site_id,
                    COUNT(*) as total_events,
                    COUNT(DISTINCT visitor_id) as unique_visitors,
                    SUM(CASE WHEN event_type IN ('pix_gerado', 'pix_generation_success', 'pix_generated', 'pix_copied', 'pix_copia_cola', 'pix_iniciado') THEN 1 ELSE 0 END) as pix_count,
                    SUM(CASE WHEN event_type IN ('pix_gerado', 'pix_generation_success', 'pix_generated', 'pix_copied', 'pix_copia_cola', 'pix_iniciado') THEN COALESCE(valor, 0) ELSE 0 END) as pix_value
                FROM events
                GROUP BY site_id
            ) e ON e.site_id = s.id";
        }
        
        try {
            $sql = "SELECT {$selectFields} FROM sites s {$joins} WHERE s.id = ?";
            $stmt = $pdo->prepare($sql);
            $stmt->execute([$siteId]);
            $site = $stmt->fetch();
        } catch (\Exception $e) {
            Response::serverError('Database error: ' . $e->getMessage());
        }

        if (!$site) {
            Response::notFound('Site not found');
        }

        // Garantir valores padrão
        if (!isset($site['total_events'])) $site['total_events'] = 0;
        if (!isset($site['unique_visitors'])) $site['unique_visitors'] = 0;
        if (!isset($site['pix_count'])) $site['pix_count'] = 0;
        if (!isset($site['pix_value'])) $site['pix_value'] = 0;
        if (!isset($site['api_token_name'])) $site['api_token_name'] = null;
        
        $site['pix_value'] = round((float)$site['pix_value'], 2);

        Response::success($site);
    }

    /**
     * PUT /site?id={id} - Atualizar site
     */
    public static function update(): void
    {
        $siteId = (int)Request::get('id', 0);

        if (!$siteId) {
            Response::error('Site ID required', 400);
        }

        $currentUser = Auth::requireSiteAccess($siteId);

        // Verificar permissão para editar (super admin sempre pode)
        if (!Auth::isSuperAdmin($currentUser) && !Auth::hasPermission('manage_site', $currentUser)) {
            Response::forbidden('Permissão negada para editar site');
        }

        $pdo = getDBConnection();

        // Verificar se a coluna api_token_id existe
        $hasApiTokenColumn = self::columnExists('sites', 'api_token_id');

        if ($hasApiTokenColumn) {
            // API Token ID (opcional)
            $apiTokenId = Request::input('api_token_id', null);
            if ($apiTokenId !== null && $apiTokenId !== '') {
                $apiTokenId = (int)$apiTokenId;
                if ($apiTokenId <= 0) {
                    $apiTokenId = null;
                }
            }

            $stmt = $pdo->prepare("
                UPDATE sites SET
                    name = ?,
                    domain = ?,
                    description = ?,
                    rate_limit = ?,
                    is_active = ?,
                    api_token_id = ?,
                    updated_at = NOW()
                WHERE id = ?
            ");
            $stmt->execute([
                Request::input('name', ''),
                Request::input('domain', ''),
                Request::input('description', ''),
                Request::input('rate_limit', 1000),
                Request::input('is_active', 1),
                $apiTokenId,
                $siteId
            ]);
        } else {
            // Sem coluna api_token_id
            $stmt = $pdo->prepare("
                UPDATE sites SET
                    name = ?,
                    domain = ?,
                    description = ?,
                    rate_limit = ?,
                    is_active = ?,
                    updated_at = NOW()
                WHERE id = ?
            ");
            $stmt->execute([
                Request::input('name', ''),
                Request::input('domain', ''),
                Request::input('description', ''),
                Request::input('rate_limit', 1000),
                Request::input('is_active', 1),
                $siteId
            ]);
        }

        logAudit('site_updated', $siteId, json_encode(Request::body()), Request::ip());

        Response::success(null, 'Site updated');
    }

    /**
     * DELETE /site?id={id} - Excluir site (apenas super admin)
     */
    public static function delete(): void
    {
        $siteId = (int)Request::get('id', 0);

        if (!$siteId) {
            Response::error('Site ID required', 400);
        }

        Auth::requireSuperAdmin();

        $pdo = getDBConnection();
        $stmt = $pdo->prepare("DELETE FROM sites WHERE id = ?");
        $stmt->execute([$siteId]);

        logAudit('site_deleted', $siteId, '', Request::ip());

        Response::success(null, 'Site deleted');
    }

    /**
     * POST /clear-site-events - Limpar eventos de um site (apenas super admin)
     */
    public static function clearEvents(): void
    {
        Auth::requireSuperAdmin();

        $siteId = (int)(Request::get('site_id') ?? Request::input('site_id', 0));

        if (!$siteId) {
            Response::error('Site ID required', 400);
        }

        $pdo = getDBConnection();

        // Verificar se o site existe
        $stmt = $pdo->prepare("SELECT name FROM sites WHERE id = ?");
        $stmt->execute([$siteId]);
        $site = $stmt->fetch();

        if (!$site) {
            Response::notFound('Site not found');
        }

        // Contar eventos antes de deletar
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM events WHERE site_id = ?");
        $stmt->execute([$siteId]);
        $eventCount = $stmt->fetchColumn();

        // Deletar todos os eventos do site
        $stmt = $pdo->prepare("DELETE FROM events WHERE site_id = ?");
        $stmt->execute([$siteId]);

        // Limpar estatísticas diárias também
        $stmt = $pdo->prepare("DELETE FROM daily_stats WHERE site_id = ?");
        $stmt->execute([$siteId]);

        // Limpar visitantes únicos
        $stmt = $pdo->prepare("DELETE FROM unique_visitors WHERE site_id = ?");
        $stmt->execute([$siteId]);

        logAudit('site_events_cleared', $siteId, "Cleared {$eventCount} events from {$site['name']}", Request::ip());

        Response::success([
            'site_id' => $siteId,
            'site_name' => $site['name'],
            'events_deleted' => $eventCount
        ], 'Events cleared successfully');
    }

    /**
     * POST /sites/regenerate-key - Regenerar API Key de um site
     */
    public static function regenerateKey(): void
    {
        $currentUser = Auth::require();
        
        $siteId = Request::getInt('id') ?: Request::inputInt('site_id');
        
        if (!$siteId) {
            Response::error('Site ID required', 400);
        }
        
        $pdo = getDBConnection();
        
        // Verificar se o site existe
        $stmt = $pdo->prepare("SELECT id, name FROM sites WHERE id = ?");
        $stmt->execute([$siteId]);
        $site = $stmt->fetch();
        
        if (!$site) {
            Response::notFound('Site not found');
        }
        
        // Verificar permissão (super_admin ou dono do site)
        if (!Auth::isSuperAdmin($currentUser) && $currentUser['site_id'] != $siteId) {
            Response::forbidden('You can only regenerate key for your own site');
        }
        
        // Gerar nova API key
        $newApiKey = 'sk_' . bin2hex(random_bytes(24));
        
        $stmt = $pdo->prepare("UPDATE sites SET api_key = ?, updated_at = NOW() WHERE id = ?");
        $stmt->execute([$newApiKey, $siteId]);
        
        logAudit('site_api_key_regenerated', $siteId, "API key regenerated for {$site['name']}", Request::ip());
        
        Response::success([
            'id' => $siteId,
            'api_key' => $newApiKey,
            'message' => 'API key regenerated successfully'
        ]);
    }
}
