<?php

declare(strict_types=1);

final class SubscriptionAccessService
{
    public function __construct(private PDO $pdo)
    {
    }

    /**
     * Devuelve el estado operativo real de un Admin. El Superadmin siempre opera.
     *
     * @return array{admin_id:int,role:string,operational:bool,state:string,plan_name:string,end_date:?string,days_remaining:?int,message:string}
     */
    public function statusForAdmin(int $adminId): array
    {
        if ($adminId <= 0) {
            return $this->emptyStatus($adminId, 'Usuario no válido.');
        }

        $userStmt = $this->pdo->prepare(
            "SELECT u.id, r.nombre_rol
             FROM usuarios u
             LEFT JOIN roles r ON r.id = u.id_rol
             WHERE u.id = ?
             LIMIT 1"
        );
        $userStmt->execute([$adminId]);
        $user = $userStmt->fetch(PDO::FETCH_ASSOC);
        if (!$user) {
            return $this->emptyStatus($adminId, 'No se encontró el propietario de la cuenta.');
        }

        $role = trim((string) ($user['nombre_rol'] ?? ''));
        if (mb_strtolower($role, 'UTF-8') === 'superadmin') {
            return [
                'admin_id' => $adminId,
                'role' => $role,
                'operational' => true,
                'state' => 'activa',
                'plan_name' => 'Superadmin',
                'end_date' => null,
                'days_remaining' => null,
                'message' => 'Acceso operativo.',
            ];
        }

        $stmt = $this->pdo->prepare(
            "SELECT s.id, s.estado, s.fecha_fin, p.nombre_plan
             FROM suscripciones s
             JOIN planes p ON p.id = s.id_plan
             WHERE s.id_admin = ?
             ORDER BY s.fecha_fin DESC, s.id DESC
             LIMIT 1"
        );
        $stmt->execute([$adminId]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$row) {
            return $this->emptyStatus($adminId, 'La cuenta no tiene una suscripción registrada.', $role);
        }

        $state = mb_strtolower(trim((string) ($row['estado'] ?? 'vencida')), 'UTF-8');
        $endRaw = trim((string) ($row['fecha_fin'] ?? ''));
        $endDate = $endRaw !== '' && strtotime($endRaw) !== false ? date('Y-m-d H:i:s', strtotime($endRaw)) : null;
        $today = new DateTimeImmutable('today');
        $endDay = $endDate !== null ? new DateTimeImmutable(date('Y-m-d', strtotime($endDate))) : null;
        $days = $endDay ? (int) $today->diff($endDay)->format('%r%a') : null;
        $stateAllows = in_array($state, ['activa', 'prueba'], true);
        $dateAllows = $days !== null && $days >= 0;
        $operational = $stateAllows && $dateAllows;

        if ($operational) {
            $message = $days === 0
                ? 'La suscripción vence hoy.'
                : 'La suscripción se encuentra operativa.';
        } elseif (!$stateAllows) {
            $message = 'La suscripción no se encuentra activa.';
        } elseif ($days === null) {
            $message = 'La suscripción no tiene una fecha de vencimiento válida.';
        } else {
            $message = 'La suscripción venció hace ' . abs($days) . ' día' . (abs($days) === 1 ? '' : 's') . '.';
        }

        return [
            'admin_id' => $adminId,
            'role' => $role,
            'operational' => $operational,
            'state' => $state,
            'plan_name' => trim((string) ($row['nombre_plan'] ?? 'Sin plan')),
            'end_date' => $endDate,
            'days_remaining' => $days,
            'message' => $message,
        ];
    }

    public function isOperational(int $adminId): bool
    {
        return $this->statusForAdmin($adminId)['operational'];
    }

    /**
     * Determina si se puede abrir el contenido de una búsqueda perteneciente a un Admin.
     * Los resultados se pueden listar, pero el contenido queda bloqueado al vencer.
     */
    public function canOpenSearchResult(int $ownerAdminId): bool
    {
        if ($ownerAdminId <= 0) {
            return false;
        }

        return $this->isOperational($ownerAdminId);
    }

    /** @return array{admin_id:int,role:string,operational:bool,state:string,plan_name:string,end_date:?string,days_remaining:?int,message:string} */
    private function emptyStatus(int $adminId, string $message, string $role = ''): array
    {
        return [
            'admin_id' => $adminId,
            'role' => $role,
            'operational' => false,
            'state' => 'sin_suscripcion',
            'plan_name' => 'Sin plan',
            'end_date' => null,
            'days_remaining' => null,
            'message' => $message,
        ];
    }
}
