package com.writeoff.security;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

@Service
public class PermissionService {
    private final JdbcTemplate jdbcTemplate;

    public PermissionService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public boolean hasPermission(Long userId, String permissionCode) {
        Long tenantId = tenantId();
        if (hasPermissionDirect(userId, tenantId, permissionCode)) {
            return true;
        }
        List<Long> principalUserIds = jdbcTemplate.queryForList(
                "SELECT user_id FROM user_delegation " +
                        "WHERE tenant_id=? AND delegate_user_id=? AND is_deleted=0 AND status='ENABLED' " +
                        "AND effective_from<=CURRENT_TIMESTAMP AND effective_to>=CURRENT_TIMESTAMP",
                Long.class,
                tenantId,
                userId
        );
        for (Long principalUserId : principalUserIds) {
            if (hasPermissionDirect(principalUserId, tenantId, permissionCode)) {
                return true;
            }
        }
        return false;
    }

    public List<String> getPermissions(Long userId) {
        return getPermissions(userId, tenantId());
    }

    public List<String> getPermissions(Long userId, Long tenantId) {
        if (tenantId == null) {
            throw new IllegalStateException("tenant context required");
        }
        Long safeTenantId = tenantId;
        Set<String> result = new LinkedHashSet<>(getPermissionsDirect(userId, safeTenantId));
        List<Long> principalUserIds = jdbcTemplate.queryForList(
                "SELECT user_id FROM user_delegation " +
                        "WHERE tenant_id=? AND delegate_user_id=? AND is_deleted=0 AND status='ENABLED' " +
                        "AND effective_from<=CURRENT_TIMESTAMP AND effective_to>=CURRENT_TIMESTAMP",
                Long.class,
                safeTenantId,
                userId
        );
        for (Long principalUserId : principalUserIds) {
            result.addAll(getPermissionsDirect(principalUserId, safeTenantId));
        }
        return new java.util.ArrayList<>(result);
    }

    public boolean hasPlatformPermission(Long userId, String permissionCode) {
        Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM platform_user_role ur " +
                        "JOIN platform_role_permission rp ON ur.role_id=rp.role_id " +
                        "JOIN platform_permission p ON rp.permission_id=p.id " +
                        "WHERE ur.user_id=? AND p.permission_code=?",
                Integer.class,
                userId,
                permissionCode
        );
        return count != null && count > 0;
    }

    public List<String> getPlatformPermissions(Long userId) {
        return jdbcTemplate.queryForList(
                "SELECT DISTINCT p.permission_code FROM platform_user_role ur " +
                        "JOIN platform_role_permission rp ON ur.role_id=rp.role_id " +
                        "JOIN platform_permission p ON rp.permission_id=p.id " +
                        "WHERE ur.user_id=?",
                String.class,
                userId
        );
    }

    public List<String> getPlatformRoles(Long userId) {
        return jdbcTemplate.queryForList(
                "SELECT DISTINCT r.role_code FROM platform_user_role ur " +
                        "JOIN platform_role r ON ur.role_id=r.id " +
                        "WHERE ur.user_id=? AND r.is_deleted=0",
                String.class,
                userId
        );
    }

    private boolean hasPermissionDirect(Long userId, Long tenantId, String permissionCode) {
        Integer count = jdbcTemplate.queryForObject(
                "SELECT COUNT(1) FROM user_role ur " +
                        "JOIN role_permission rp ON ur.role_id=rp.role_id AND ur.tenant_id=rp.tenant_id " +
                        "JOIN permission p ON rp.permission_id=p.id " +
                        "WHERE ur.user_id=? AND ur.tenant_id=? AND p.permission_code=?",
                Integer.class,
                userId,
                tenantId,
                permissionCode
        );
        return count != null && count > 0;
    }

    private List<String> getPermissionsDirect(Long userId, Long tenantId) {
        return jdbcTemplate.queryForList(
                "SELECT DISTINCT p.permission_code FROM user_role ur " +
                        "JOIN role_permission rp ON ur.role_id=rp.role_id AND ur.tenant_id=rp.tenant_id " +
                        "JOIN permission p ON rp.permission_id=p.id " +
                        "WHERE ur.user_id=? AND ur.tenant_id=?",
                String.class,
                userId,
                tenantId
        );
    }

    private Long tenantId() {
        return AuthContext.requireTenantId();
    }
}
